Edited at

Tips: 実行中のシェルスクリプトを書きかえるときには

More than 1 year has passed since last update.

実行中のシェルスクリプトを編集すると実行している途中から動作を変えることができることはよく知られている。 例: http://d.hatena.ne.jp/sleepy_yoshi/20090917/p1

「変えることができる」というよりも現実のケースでは、実行中に意図せず内容を変えてしまうことで予想しない挙動をさせてしまうことがありうる。これを防ぐにはどうするか。


次のようなスクリプトを実行中に書き換えてみる


run.sh

#!/bin/sh

sleep 30
echo foo

$ run.sh &

$ vim run.sh
(30 秒以内に foo を bar に変えて保存する)
bar

編集後の bar という文字が表示されてしまう。

この例ではまだマシだが、現実のケースでは予期せずして if 文まるごと貫通するなど、破滅をもたらしてしまうことがある。


対策

新たにファイルを作成しなおして編集すればいい。

シェルが掴んでいるのは旧い i-node のファイルの方で、新たに編集する方とは別の i-node にする。

特に cp して mv すると楽。

$ run.sh &

$ cp run.sh run.sh.tmp
$ mv run.sh.tmp run.sh
$ vim run.sh
(30 秒以内に foo を bar に変えて保存する)
foo

ちゃんと結果は foo のままになっている。


超余談

リネームは bash の展開を使うと間違えにくく、楽

$ cp run.sh{,.tmp}

$ mv run.sh{.tmp,}


テスト

最近は私はなるべく Tips もテストつきで管理しています。そうすると Tips が時代の変化に強くなります。

https://github.com/kitsuyui/kitsuyui/tree/master/tips/shellscript-editing-during-running