Linux備忘録15:エラーも含めたリダイレクト、空白詰め(置換)、文字抽出(ファイルディスプリタ、tr、cut)

Linux(bash)備忘録。

個人用備忘録のため、内容や記述に誤りがあったら申し訳ありません。

 

【エラー出力および標準出力をログファイルに残す】

・エラーと標準出力をそれぞれ別のファイルに記録する場合

# {コマンドもしくはスクリプト}  1> info.txt 2> err.txt

  ※2>がエラー出力

 

・出力した内容を画面に表示する

# {コマンドもしくはスクリプト}  | tee -a  {出力先ファイル}

 ※パイプで標準出力をteeコマンドに渡す。コンソールに表示。さらに[-a]オプションがファイルにリダイレクトする。

 

・エラー、および標準出力をどちらかの出力にマージする

 

 [>&{ファイルディスクリプタ]を使用し、結果をマージ出来る。

 標準出力を標準エラー出力にマージする場合

 ⇒1>&2

 逆に標準エラー出力を標準出力にマージする場合

 ⇒2>&1

 

参考例

# {コマンドもしくはスクリプト}  > logf.txt 2>&1

※エラー出力を標準出力としてマージ ⇒ エラー出力もリダイレクトされる

※ファイルディスクリプタの記載位置に注意 ⇒ リダイレクト式の後に記載

 

 

・エラー出力も標準出力も「全て画面に表示」し、ログに「リダイレクト」する。

# cat tmp 2>&1 | tee -a log.txt

※1>&2と記載した場合はcatコマンドがエラー出力をしないため、何もリダイレクトされない。

 

※注意事項

 標準エラー出力は捨てるべきでない!!!

例:# command > /dev/null 2>&1

  ⇒この場合、エラー結果も破棄されるため原因特定等が困難になる。よくわからないまま利用するのはよくない

 

 

【スペースを詰め、別の文字列に置き換える】

 ※csvファイルを簡単に作成できる。

 

・改行を置き換えて、複数の行を一行で表示する

# echo -e "ringo\nmikan\nsuika" | tr "\n" " "

※置き換え文字として改行コードを指定   

※[echo -e]オプションはバックスラッシュエスケープを有効にする(-Eは無効(デフォルト))

※trコマンドの第2引数は何らかの文字列を指定しなければいけない→結合は出来なかった。

 

・複数あるスぺ―スを","(カンマ)に置き換える

# tr -s " " ","

 

【文字列の一部を切り取る】

 ※[cut]コマンドを使用して文字列を切り取る

 

・3,6,9文字目を切り取る

# echo "123456789" | cut -c 3,6,9
369

 

・5~8文字目を切り取る

# echo "123456789" | cut -c 5-8
5678

 

Linux備忘録14:sshpassでの一括処理、変数内置換(削除)

 

Linux(bash)備忘録。

個人用備忘録のため、内容や記述に誤りがあったら申し訳ありません。

 

【sshpassを使用しての複数サーバの情報を並列で取得する】

 

 サンプルスクリプト

#!/bin/bash

PASS={パスワード}
LIST_FILE={サーバホスト情報リストのファイルパス}

for HOST in `cat ${LIST FILE}`
 do
  sshpass -p ${PASS} ssh ${HOST} echo `hostname && date '+%H%M%S_%3N'` &
    done

 ※現在検証中

 

・echoを使用すれば、コマンド実行結果を一行で取得できる。

・コマンド最後に&を記述でループ処理をバックグラウンド実行。※並列でコマンド結果が得られる

・dateの”_%3N”の表記は「ミリ秒を3ケタで表示する」という意味 

・60数件の単一コマンド実行であれば、特にラグ等無く、実行結果を得ることが出来た。

 

 

 

【変数内置換パターン】

[#]はコメントアウトで前部分。 [%]は100%で後部分

パターン 動作 使用例
${変数#パターン} 文字列先頭最短マッチ部分を削除 先頭の固定文字列を削除するとき使う
${変数##パターン} 文字列先頭最長マッチ部分を削除 ${HOGE##*/}でbasename
${変数%パターン} 文字列末尾最短マッチ部分を削除

${HOGE%/*}でdirname

末尾の固定文字列を削除するときにも使う

${変数%%パターン} 文字列末尾最長マッチ部分を削除  
${変数/検索文字列/置換文字列}

最初にマッチしたもののみ文字列を置換

 
${変数//検索文字列/置換文字列} 全ての文字列を置換 ${HOGE//{文字列1}/{文字列2}}

【変数がNULLの場合、変数に値を格納する】

※一時的に置き換えるパターンとそのまま代入するパターンがある。

 

echo $HOGE # (null)
echo ${HOGE:-hoge} # hoge $HOGEがNULLの場合に"hoge"に置き換える。代入はされない。
echo $HOGE # (null)

 

echo $FUGA # (null)
echo ${FUGA:=fuga} # fuga $FUGAがNULLの場合に"fuga"に置き換え、かつ、代入もする。
echo $FUGA # fuga ← シェル変数FUGAにfugaが格納される

 

【変数内置換の使用例】

 変数内ファイル名の拡張子のみを取得

HOGE="/home/user/access.log"
echo ${HOGE##*.} #=> logが表示

 ⇒HOGEがピリオドを1個も含まない場合は元の文字列全体になってしまう

 拡張子のみを削除

echo ${HOGE%.*} #=> /home/user/access

 

 

Linux備忘録13:パッケージ関連コマンド(rpm、yum)

使用予定がありそうな、パッケージ関連の備忘録

ほぼコピペなので引用元サイトを記載させていただいております。

※検証はしておりませんため、情報が古い等により実行結果の保障は出来ません。

 

Yum の Tips - Qiita

※上記サイトより引用

 

【パッケージの依存関係を調べる】

パッケージ名から依存関係を調べる

# yum deplist <PKG>

 

RPM ファイルから依存関係を確認する

# rpm -qp --requires <RPM>

 

【ダウンロードしたパッケージからリポジトリを作成する】

# yum install -y createrepo yum-utils
# mkdir -p ~/yum/myrepo/Packages; cd $_
# yumdownloader --resolve <PKG>
# cd ../..
# createrepo myrepo 

作成したリポジトリは tar などで固めて他のサーバに持っていくことも可能。

 

リポジトリを使用可能にする】

# vi /etc/yum.repos.d/myrepo.repo
[myrepo]
name=MyRepo
baseurl=file:///root/yum/myrepo
enabled=1
gpgcheck=0
# yum clean all
# yum repolist
# yum search <PKG>

 

rpmコマンドの主なオプション

【 rpm 】コマンド(応用編その1)――パッケージの情報を調べる(1):Linux基本コマンドTips(48) - @IT

 ※上記サイトより引用

●コマンドオプション

短いオプション 長いオプション 意味
-i --install パッケージファイル名 パッケージをインストールする
-U --upgrade パッケージファイル名 パッケージをアップグレードする(「--install」と同じオプションが使用可能)
-F --freshen パッケージファイル名 以前のバージョンがインストールされているときのみパッケージをアップグレードする
-e --erase パッケージ パッケージをアンインストール(削除)する
-q --query 問い合わせ(パッケージ情報の表示と検索)
-V --verify パッケージを検査する

●共通のオプション(-i、-U、-qなどと同時に使用)

-v   情報表示を増やす
-vv   「-v」指定時よりも詳細な情報を表示する(デバッグ用)
--quiet   情報表示を減らす(エラーメッセージのみになる)

情報問い合わせ関連(-q、-Vと一緒に使用するオプション)

短いオプション 長いオプション 意味
-a --all インストールされているパッケージを一覧表示する
-i   パッケージの情報を表示する
  --provides パッケージが提供する機能(ライブラリなど)を表示する
-R --requires 依存しているファイル名を表示する
  --changelog パッケージの更新情報を表示する
-l --list パッケージに含まれるファイルを表示する
-c --configfiles 設定ファイルのみを表示する(「-l」を指定したものと見なす)
-d --docfiles 文書ファイルのみを表示する(「-l」を指定したものと見なす)
-f ファイル名 --file ファイル名 指定したファイルがどのパッケージからインストールされたのかを表示する(フィールドあるいはフルパスで指定)
-p   パッケージ名ではなく、RPMパッケージファイルを指定して問い合わせる

●インストール/更新時に使用できるオプション

短いオプション 長いオプション 意味
  --excludepath OLDPATH パスの名前が「OLDPATH」で始まるファイルをインストールしない
  --excludedocs 「man」なども含め、文書であるとマーク付されたファイルをインストールしない
  --includedocs 文書ファイルをインストールする(デフォルト)
  --ignoresize インストール前に、ディスクの空き領域をチェックしない
  --ignorearch パッケージのアーキテクチャ(CPUなど)がインストール先と一致しなくてもインストールやアップグレードを行う
  --ignoreos パッケージのOSがインストール先と一致しなくてもインストールやアップグレードを行う
  --nosignature パッケージまたはへッダの署名を検査しない
  --nosuggest 不明な依存性を解消するパッケージを提案しない
  --noscriopts ファイルの配置だけを行いスクリプトは実行しない
  --force 「--replacepkgs」「--replacefiles」「--oldpackage」相当
  --replacepkgs 指定したパッケージが既にインストールされていてもインストールする
  --replacefiles 他のパッケージによってインストールされたファイルを置き換えてしまう場合でもインストールする
  --oldpackage インストール済みのパッケージよりもバージョンが古くても更新する

 

●インストール/更新/削除時に使用できるオプション

-h --hash インストール時の経過を「#」マーク(ハッシュマーク)で表示する
  --test 実際のインストールなどは行わず、テストのみ行う
  --nodeps パッケージの依存関係を検証しない

Linux備忘録12:プロセス、ポート(ps、lsof)、CPUについて

個人備忘録用のため、内容や記述に誤りがあったら申し訳ありません。

 

【ポート番号を使用しているファイルやプロセスを特定する】

<lsof>コマンド:

プロセスが開いているファイルを表示

# lsof -p {プロセス番号}

⇒逆も可

# lsof {ファイルパス}

 

特定ポートの使用状況を調べる

# lsof -i :{ポート番号}

 {:}必須

 ⇒※上記は省略系:正式には[lsof -i(ipv) {protocol}@{server}:{port}]といった感じで指定

 

※※出力内容概要

【COMMAND】⇒ そのプロセスを起動しているコマンド(サービス)

【PID】      ⇒プロセスID

【NAME】   ⇒(LISTEN)と記載されているのがそのポートを待ちうけているプロセス情報

 

上記を利用して確認したプロセスIDを使用してサービスを特定するシェルスクリプト

#!/bin/bash
pid=$1
 systemctl list-units --type=service | \
  cut -d " " -f 1 | \
   while read name
    do
     if systemctl status ${name} | grep -E "PID: +${pid}" ;then
      echo "Service is: ${name}"
      break
     fi
    done

 

 

【psコマンドを使用してプロセス情報を調べる】

 

 <ps>コマンド:

実行中のプロセスの一覧に特定プロセスが含まれるか検索。

# ps -ef | grep "{キーワード}” | grep -v "grep"

プロセスのステータス等を表示したい場合は以下のオプション

# ps aux

 

※※出力内容概要

USER->プロセスの実行ユーザー

%CPU->プロセスのCPU使用率(CPU利用時間/実際の時間)

%MEM->プロセスが確保している物理メモリを百分率で表示

VSZ、RSS->それぞれプロセスが仮想メモリ領域のサイズ、物理メモリ領域のサイズ。後述 大量のスワップが発生している場合、原因となっているプロセスは物理メモリを消費しているとうことなのでRSS列の値が高いも プロセスを確認する必要があります。

STAT->プロセスの状態。後述

---------------------------------------------------------------------------------------------------------------------
①STAT列の1文字目はプロセスの以下を状態を表します。

「R」 ->CPU使用中。実行可能状態なプロセス(実際に実行していないCPU割り当て待ちのプロセスも含む)
「S」 ->割り込み可能な待ち状態。主に復帰時間が予想できるもの。sleepやユーザーの入力待ちなど
「D」 ->ディスクIO待ちの状態(※割り込み不能)

「T」 ->STOPシグナルで一時停止している

「Z」 ->ゾンビプロセス状態(親プロセスに待たれずに死んでしまった子プロセス)

 

②2文字目以降は以下を表す状態。
「+」 ->フォアグラウンドのプロセスグループ
「s」 ->セッションリーダー。httpd等の場合、rootユーザーで実行しているものがセッションリーダーとなっているのがわかる。

「>」 ->優先度が高いプロセス
「N」 ->優先度が低いプロセス
「-l」 ->マルチスレッドのプロセス
---------------------------------------------------------------------------------------------------------------------

 

【プロセスのフルパスを取得する】

topやpsコマンドでは相対パスシンボリックリンクでのコマンド、プログラム名が表示されているため、以下でフルパス取得出来る。

# ls -l /proc/{対象プロセスID}/exe

 →各スレッド(?)等のプログラム大元が確認出来る。

 

※参考例

 →一番メモリ使用率が高いプロセスを確認したらこんな感じだった.

#  ls -l /proc/26212/exe
lrwxrwxrwx 1 oracle oinstall 0 11月 20 22:11 /proc/26212/exe -> /opt/oracle/product/19c/dbhome_1/bin/oracle

 

【CPUについて】

 

物理 CPU の数の確認コマンド

# fgrep 'physical id' /proc/cpuinfo | sort -u | wc -l

 

CPUコア数の確認コマンド
※最近の CPU では、物理的に 1 つの CPU 上に、複数のコアがあるものがある。

# fgrep 'cpu cores' /proc/cpuinfo | sort -u | sed 's/.*: //'

 

論理プロセッサー数(スレッド数)の確認コマンド

# fgrep 'processor' /proc/cpuinfo | wc -l

 

 

Linux備忘録11:ヒアドキュメント

ヒアドキュメントのメモ

 

【概要】
複数行の文字列を簡潔に記述するための機能。
シェルスクリプトの中にちょっとした別のスクリプトを埋め込むときに便利とのこと。
bashの他にも、C、C+、PerlPython等にも同じ機能がある

【ヒアドキュメントは標準入力として扱われる】※文字列リテラルではない
⇒echoで出力は出来ない
⇒標準出力する場合は引数無しのcatに渡して使用する。

 ※catへのリダイレクトは必ず追記:"<<”にする。

 

# 例) oracleDBのテーブル一覧を出力する
sqlplus -S user/pass@sid << EOS
set pagesize 0
set feedback off

select table_name from tabs
order by table_name;
EOS


【通常の利用方法】

cat << EOF
aaaaa
bbbbb
ccccc
EOF

※{EOF}はヒアドキュメントの範囲を示す区切り文字。任意の文字が指定可能。
※区切り文字の【次】の行からの内容がヒアドキュメントとして扱われる。

 

【ファイルの内容を連結して入力(リダイレクト)】

cat - << EOF test.txt > output.txt
aaaaa
bbbbb
EOS

 

catの直後-は、catの仕様として、ファイル名を指定すると標準入力から読み込まなくなるため、明示的に-を指定して、標準入力として渡したい箇所を指定。

 

""で括った文字列リテラルと同様、変数展開やコマンド置換が行われる。
その場合は区切り文字をシングルクォーテションで囲めば、変数展開等を抑止できる。

cat << 'EOF'
$MY_VAR と書いても展開されない
EOF

 

【行頭のタブを取り除く】

cat <<- EOF
<tab> hoge
<tab> fuga
<tab>EOF

※行頭の<tab>が取り除かれ、最終行のEOFが認識される。

 

【変数に代入する】

※ヒアドキュメントの終了文字{EOS}の直後に")"を記述するとエラーになる。

HOGE=$(cat << EOS
hoge
fuga
EOS
)

 

Linux備忘録10:sshコマンドにパスワードを渡す、タイムスタンプ関連(sshpass、date、touch、find)

コマンド備忘録。
※個人用のメモのため、内容、記述に誤りがあったら申し訳ありません。

 

ssh関連コマンドに自動でパスワードを渡す】
 ※シェルスクリプト等で利用が可能。

 <sshpass>コマンドを使用して、scp、rsync等にパスワードを渡す

 

ssh使用例

# sshpass -p {パスワード} ssh -o 'StrictHostKeyChecking no' {ユーザー名}@{対象サーバ} sudo -u root "{実行コマンド列}"

 

※[-o 'StrictHostKeyChecking no']オプションはフィンガープリント登録メッセージを無視する

 

上記{実行コマンド列}内で"*"を使用する場合はクォーテションで囲まなければ、特殊文字として使用は出来た。だけど、コマンドの実行環境の情報を保持するのか、出力結果が少しおかしい部分もあったため、取扱いは注意!!

ファイル構成等が同じの、対象台数が多いサーバ等に対して利用する便利かも。

 

rsync使用例
※検証が必要。オプションとか…

# sshpass -p {パスワード} rsync -rtu --rsync-path="sudo rsync" {ユーザー名}@{対象サーバ}:{同期元パス} {同期先パス}

 

 

【タイムスタンプ操作に関するコマンド】

 ・日数を指定して、該当する年月日を得る

# date '+%Y%m%d' --date '{日数} day ago'
 ※day の部分は他に{week}{month}等の指定が可能。

 ※2日 3:30前の時刻を表示する。

 ⇒date --date '2 day ago 3 hour ago 30 minutes ago'


 ・日数を指定してタイムスタンプを更新する

# touch -d "YYYY-MM-DD hh:mm" {ファイル名}
※上記なような形式で時間および日付を変更。

 


【findコマンドを使用して特定日付のファイルのみを見つける】

 30日より古いファイルのみを検索して表示する

# find {ディレクトリ} -ctime +30 -type f
 ※最終アクセス日で検索する場合、[-atime]オプションを使用する
 ※ディレクトリのみを検索する場合、[-type d]オプションを使用する 

 

 30日以内の範囲のタイムスタンプを検索

# find {ディレクトリ} -ctime -30

 

 ちょうど30日前のものを検索

# find {ディレクトリ} -ctime 30

 

Linux備忘録9:正規表現メモ

備忘録、メモ書き…。 

 

.  ⇒ 改行文字以外の任意の1文字  


* ⇒ 直前の1文字の0回以上の繰り返しに一致。直前の文字は正規表現でも構わない

 

^ ⇒行の先頭


$   ⇒行の末尾


[ ] ⇒ かっこ内の任意の1文字に一致。ハイフン(-)で範囲指定もできる


[^ ] ⇒ かっこ内の任意の1文字に不一致。ハイフン(-)で範囲指定もできる


\+ ⇒ 直前の文字の1個以上の繰り返し


\? ⇒ 直前の文字の0または1文字


\{n\} ⇒ 直前の文字のn個の繰り返し

 

\{n,\} ⇒ 直前の文字のn個以上の繰り返し


\{,m\} ⇒ 直前の文字のm個以下の繰り返し


\{n,m\} ⇒ 直前の文字のn個以上,m個以下の繰り返し


pattern1\|pattern2  ⇒pattern1またはpattern2のいずれか


\(pattern\) ⇒ patternをグループ化する。マッチした内容は\numで参照できる


\ ⇒ 正規表現に使われる記号を普通の文字として扱う