2010年8月28日土曜日

バッチやシェルスクリプトには安全装置を


このエントリーをはてなブックマークに追加


インフラ関連の作業をしていると、バッチやシェルスクリプトを山ほど作ると思う。
運用のためだったり、構築段階での効率化を目的としたもの、データ移行を目的としたものやそれこそ様々な用途で活用されている(はず

作業を自動化する上で非常に便利なバッチ・シェルスクリプトだが他人の作ったものを見ていると、Windowsであればダブルクリックするだけで即実行されてしまうものがかなりある。
これは非常に危険で、慣れない顧客環境や、狭くて窮屈なコンソール環境なんかで作業していると、間違って実行してしまったりと危険極まりない。

またバッチからバッチを読んでいるような処理で、呼び先のバッチの中で環境変数をチェックしてない場合も多く、これも危険。
例えば元バッチAで
APPTEMP=/opt/app/tmp とかしてしていて、

呼び先Bで
rm -rf $APPTEMP/data

とかしていると、呼び先バッチBを直接実行されると変数がセットされていないため、これは
rm -rf /data として実行されてしまう。

基本的な事なんだけど、こういった問題を回避して安全に運用するためのTIPSをメモっておく。


(1)間違った実行を防止する(特にWindowsで重要
 これは簡単。バッチやスクリプトの先頭に、明示的な引数が与えられない場合は終了するようにしてしまう。
--------------------------------------
@echo off

if "%1" neq "accept" goto ERROR1

echo main
exit 0

:ERROR1
echo "ERROR-----" You must set "accept" to 1st args.
echo "ERROR-----" Usage: accept arg1 arg2 ...
exit 1
--------------------------------------
こう書いておけば、間違ってエクスプローラーから実行してしまっても、引数が与えられていないため実行されない。

また自動化する場合は引数を与えてしてしておけば、自動実行には問題なく使える。シンプルだが強力な安全装置になる。

*UNIX系ならWindowsほど危険ではないが、同じ手法で問題を回避できる。


(2)環境変数の渡し漏れを防止する
UNIXなら簡単。Bシェル系なら、変数を取り出すところで、

echo ${TEMP:?"is not set"}

とか書いておけば、TEMPが設定されていないとエラーで終了する。その時に?の後ろの文字列が出力される。

[root@ml115g5-1 ~]# export TESTENV=test

[root@ml115g5-1 ~]# echo ${TESTENV:?"is not set"}
test

[root@ml115g5-1 ~]# echo $?
0

[root@ml115g5-1 ~]# unset TESTENV

[root@ml115g5-1 ~]# echo ${TESTENV:?"is not set"}
-bash: TESTENV: is not set

[root@ml115g5-1 ~]# echo $?
1

WindowsやCシェル系は残念ながら、個別に処理を埋め込むしかなさそう。PowerShellならいけるかも?
■参考文献
入門bash第3版
入門bash第3版

価格:2,940円(税込、送料別)

Windows DOS/コマンドプロンプト辞典
Windows DOS/コマンドプロンプト辞典

価格:2,079円(税込、送料別)

Windows PowerShellインアクション
Windows PowerShellインアクション

価格:4,620円(税込、送料別)