[シェルスクリプト] めちゃめちゃ気づきにくいバックスラッシュによるバグ

どっかで拾ったinit.dスクリプトをコピペしてデーモンを起動しようとしたら、オプションが期待通りに動作しないという不具合に遭遇しました。

仮に、/etc/init.d/hoged で hoged サーバを起動したかったとします。

拾ってきた起動スクリプトはこのようなものでした。
/etc/init.d/hoged
#!/bin/sh
OPTS=" -foo \"bar\" "
CMD=" /usr/loca/bin/hoged $OPTS"
$CMD
このスクリプトを実行しても、hogedデーモンはオプション-fooの値を解釈してくれませんでした。

実験してみる

これは良く考えると当たり前で、実験してみるとわかります。
/etc/init.d/hoged
#!/bin/sh
OPTS=" -foo \"bar\" "
CMD=" /tmp/show_args.sh $OPTS"
$CMD
/tmp/show_args.sh (デーモンのかわり)
#!/bin/sh
echo $@
実行すると、
/etc/init.d/hoged
foo "bar"
ダブルクォートがそのまま表示されてしまっています。

実験その2

/tmp/show_args.sh foo "bar"
foo bar
これは期待どおりに動いてくれます。
一方、
/tmp/show_args.sh foo \"bar\"
foo "bar"
おお、"bar"となりました。

つまり、冒頭のシェルスクリプトはこれををやってしまっていたのですね。

まとめ

  • シェルスクリプトのバックスラッシュを甘く見るな
  • エスケープのバグは気づきにくい
  • エスケープしなくてよいならするな
カテゴリ:

人気記事