いろんなスクリプトの実行のしかた
シェルスクリプトを実行するときは、いろんなところから実行するパターンがあったりします。
- 相対パス
~/bin$ ./command.sh
- 絶対パス
~$ /home/ika/bin/command.sh
- cronから
10 * * * * ika /home/ika/bin/command.sh
このとき、実行するところによってスクリプトが始まったときのカレントディレクトリがまちまちなので、スクリプト内で一時作業ファイルを出力する際に想定外のディレクトリに吐き出されてしまったりしますし、個々の環境へチェックアウトして各個人が実行する場合などは、実行ユーザの違い等によってパーミッションエラーになったりしてしまったりすることがあったりします。
cronから実行される場合に至ってはカレントやらなんやらがどうなってるのか正直よくわかりません。
カレントディレクトリの統一
対策として、ファイル名等に絶対パスを使ったりもできます。
WORK_FILE="/tmp/command.sh.workfile"
が、これだけですと同時に複数実行されたとき等に予期せぬ動作をしたりする可能性がありますし、スクリプトから外れたディレクトリで作業するのもなんかキモいので、カレントディレクトリを常に実行したファイルの位置に持ってくるときっとわかりやすいともいます。
cd `dirname $0`
と、スクリプトの最初に書いておけば、どこから実行されても常に自分のスクリプトの位置にカレントディレクトリが来るので、作業ファイルや作業ディレクトリがどこかに行ってしまうこともなくなって快適なスクリプトが書けることうけあいです。
$0 のせつめい
実行しているスクリプト名前です。
~/bin/$ ./command.sh
と実行されたら ./command.sh が、
~$ /home/ika/bin/command.sh
と実行されたら /home/ika/bin/command.sh が
それぞれ $0
から取得できます。
dirname のせつめい
ディレクトリ名を返します。
dirname ./command.sh
だったら . (←ドットだけ) が、
dirname /home/ika/bin/command.sh
だったら /home/ika/bin が、
それぞれ返ってきます。
おまけ
ちなみに、絶対パスでさくっとファイル名をかぶらないようにしたいだけでしたら、プロセス番号を以下のように使うと便利です。
WORK_FILE="/tmp/command.sh.workfile.$$"
$$
と書くとスクリプトを実行した子プロセスのPIDが出てくるので、通常は被らないとおもいます。
$RANDOM
というランダムな数値(0 ~ 32767) を返してくれる特殊な変数もありますが、こちらは完全にランダムな上にPIDよりも範囲が狭いのに対して、PIDは基本的にインクリメントして振られていく(Winは違うかも)ため、被りにくいという意味では $$
の方が使い勝手がよいとおもいます。