シェルスクリプトではまった点についてまとめる。
■ 検索
● locateとfindの違い
ファイル名が分かっている場合はインデックスを参照するlocateの方が高速。
# インデックスの更新
sudo updatedb
locate ファイル名
■ 計算
● 実数の計算は"bc"コマンドを使う必要がある。
scalceで少数点以下の桁数を調整。
# echo "scale=2; 10 / 3" | bc
3.33
# echo "scale=3; 10 / 3" | bc
3.333
# echo "scale=4; 10 / 3" | bc
3.3333
# echo "scale=4; 0.1 / 10" | bc
.0100
■ 条件分岐
● 文字列比較には=, 数値比較は"-eq"
● if文における [[]] と []の違いについて
-
[] : testコマンドの省略系
-
[[]] : []よりも多機能(条件指定に&&, ||, Pattern matching, 正規表現)
■ 関数
● 関数の戻り値に文字列を指定できない
return コマンドの引数に指定できる値は、1~255 の正の整数のみ
return コマンドの引数に指定できる値は、0~255 の整数のみ
● ローカル変数を使用するには、localを指定する必要がある
一般的なプログラミング言語と異なり、使用する変数はグローバル変数になる。
ローカル変数にするにはlocalを使用する必要がある。
func() {
local x="local"
}
■ shellのオプションを設定するにはsetコマンド
オプション | 内容 |
---|---|
x | コマンドと引数の展開処理(デバッグ)内容を標準エラー出力 |
v | コマンドの実行行を標準エラー出力 |
n | コマンドを実行せず,構文エラーだけを確認する |
u | 未定義の変数を参照するとエラー・メッセージを表示 |
e | コマンドが0以外のステータスで終了した場合,一部の場合を除いて即座に終了する |
f | パス名のワイルドカードによる展開(*や?)を無効にする |
o ignoreof | CTRLキーを押しながらDキーを押しても,シェルを終了しないように設定する。exitコマンドは利用できる |
# xオプションを有効化
set -x
echo "test command"
# +で無効化。
set +x
■ 特殊記号を無効にする
● 関数に特殊文字を渡す
# パス名のワイルドカードによる展開(*や?)を無効にする
set -f
function "* * * argv"
set +f
● grepで特殊記号を無効
grep -Fを使う
grep -Fとは
-F ⇒ --fixed-strings
パターンではなく固定文字列での検索を行う。
■ プロセスが強制停止しても、確実に処理を行いたい場合はtrapコマンド
● trapコマンド
実行中のプロセスに対するシグナルを検知し、指定された処理を返すコマンド
シグナル とは
実行中のプロセスに対して、プロセス停止などのイベントを通知するために>送出される信号
シグナル番号 | シグナル名 | 通知内容 |
---|---|---|
1 | HUP | プロセスに再起動を通知する。 |
2 | INT | プロセスに割り込みを通知する。(Ctrl+c) |
3 | QUIT | プロセスに終了を通知する。(coreを作成する) |
9 | KILL | プロセスに強制終了を通知する。 |
15 | TERM | プロセスに終了を通知する。(デフォルト) |
18 | CONT | プロセスに再開を通知する。 |
19 | STOP | プロセスに中断を通知する。 |
20 | TSTP | プロセスにサスペンドを通知する。(Ctrl+Z) |
# -l シグナル一覧を表示する
# -p 指定された処理を確認できる
trap -l
trap -p
# プロセスの終了シグナル(0)を受け取った際に、コマンドを実行する
# trap "コマンド" [シグナル or シグナル名]
trap "
echo '`basename $0` end.'
echo 'status is $?'
" 0
■ ファイル名の取得
#!/bin/bash
# ファイルのフルパスを取得
# シンボリックリンクの場合は実態の取得
# $0 : 自身のファイルパス
echo $(readlink -f $0)
# -f : ファイルが存在しなくてもフルパスを返す
# -e : ファイルが存在しないときは返り値なし
echo $(readlink -f not_found_file.txt)
echo $(readlink -e not_found_filei.txt)
# ディレクトリ名の取得
echo `dirname $(readlink -f $0)`
# ファイル名の取得
echo `basename $(readlink -f $0)`
■ 2重起動防止
if [ $$ != `pgrep -fo $0` ]; then
echo "[`date '+%Y/%m/%d %T'`] warning already running."
exit 1
fi
処理 | 意味 |
---|---|
$0 | スクリプト名 |
$$ | このシェルスクリプトのプロセスID |
pgrep | プロセス名を指定してプロセスIDを表示 |
pgrep -f | パターンにマッチしたプロセスを全て表示 |
pgrep -o | マッチしたプロセスから最古のものを表示 |
■ ネットワークデバイスのデバイス名が変更される
ネットワークデバイスのデバイス名がeth0⇒eth1がMACアドレスの変更などにより、変更されることがある。
この場合、設定ファイルのデバイス名を書き換えることで、もとに戻せる。
cd /etc/udev/rules.d
view 70-persistent-net.rules
# NAMEをeth0に変更する
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
http://blog.livedoor.jp/itukano/archives/51865711.html
http://d.hatena.ne.jp/ktat/20090716/1247745069
■ 起動時にRamdiskをマウント
■ 変数を2重展開する際はevalコマンドを使う
# 変数名を代入する
$ color="red"
$ VALUE_NAME="color"
# 変数名を使って、変数の値を出力
$ eval echo '$'"${VALUE_NAME}"
red
■ whileの外で変数を使用すると空文字になるケースがある
パイプを使うとパイプ先の処理は、別プロセス(別シェル)になるため、cat file | while ~のようなループ処理をすると、
whileが別シェルとなるので、while文中に定義した変数は、whileの外で使うと未定義のため、空文字になる。
cat "${file}" | while read line;
do
value="${line}";
done
echo "${value}"