アカウント名:
パスワード:
> スクリプトはある時点でデータの保存場所を「$STEAMROOT」にセットし、後で「rm -rf "$STEAMROOT/"*」を実行する。しかし、データの保存場所が移動されると「$STEAMROOT」が空の文字列を返すため、「rm -rf "/"*」が実行され、予期しない削除が実行されるというものだ。
こう聞くと自分もうっかり書いてしまいそうなミスに見えますが、同じようなケースで事故を回避するベストプラクティスはどんな感じですかね。
Shell Scriptを使わない本当に安易に使わないほうが良いのかもしれません
私が20数年前に先輩から聞いていまでも注意していることとして以下があります。・シェルスクリプト、Cなどいかなる状況でもパス文字列の先頭を/にしないこと(絶対パスではなく相対パスにするべし) これは最悪ルートからファイルを削除することになるため。・あるディレクトリ以下のファイル、ディレクトリをすべて削除したい場合、対象ディレクトリにcdで移動してからファイルを削除、上位ディレクトリに移動してからrmdirでディレクトリを削除すること・ファイル数が不定の場合、パイプするときにはかならずxargsを用いるべし
これだけでは防げないかもしれませんがいまのところ重要ファイルを削除した経験はないです。
test -z "$STEAMROOT" やら test -n "$STEAMROOT" やらでチェックするんじゃないっすかね.
STEAMROOT="/tmp "
STEAMROOT="/"
まず、消す直前に意図したものがあるのかチェックしてないのは致命的。ディレクトリがあるのかもそうだけど、自分が作ったものならどんなファイルがそこにあるか知ってるはずだろ。ものぐさせずに*じゃなく全部の名前を書くべき。そして、STEAMROOTを保存するときに、/を付けた状態で保存してないのもミスの原因。必ず/を付けてコマンド打つなら保存するときにつけるべき。でも、Sym-linkしてあってもシェルベースではファイルがないということはないのでは。このSTEAMROOTとかをCのバイナリで作ったなら、その中でlstatしてないのかもね。これもまぁよくあるバグ。
bashならスクリプトの先頭に set -u しておく。というか、自分なら未定義の変数を空文字列として展開する言語を使用しない。
今回の場合、変数は未定義ではなく空文字列に定義されていたので、 set -u じゃ防げないと思うよ。ただし、僕は議論をちゃんと追っておらず、どうして空文字列に定義されていたのかは知らないので、理由によっては空文字列に定義する部分で set -u されていれば防げた可能性はあるけど (でもぱっと見ではそうは見えない。どちらかというと set -e の方が関係ありそう)。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
Stableって古いって意味だっけ? -- Debian初級
対策 (スコア:1)
> スクリプトはある時点でデータの保存場所を「$STEAMROOT」にセットし、後で「rm -rf "$STEAMROOT/"*」を実行する。しかし、データの保存場所が移動されると「$STEAMROOT」が空の文字列を返すため、「rm -rf "/"*」が実行され、予期しない削除が実行されるというものだ。
こう聞くと自分もうっかり書いてしまいそうなミスに見えますが、
同じようなケースで事故を回避するベストプラクティスはどんな感じですかね。
Re:対策 (スコア:2)
Shell Scriptを使わない
本当に安易に使わないほうが良いのかもしれません
Re:対策 (スコア:2, 参考になる)
私が20数年前に先輩から聞いていまでも注意していることとして以下があります。
・シェルスクリプト、Cなどいかなる状況でもパス文字列の先頭を/にしないこと(絶対パスではなく相対パスにするべし)
これは最悪ルートからファイルを削除することになるため。
・あるディレクトリ以下のファイル、ディレクトリをすべて削除したい場合、対象ディレクトリにcdで移動してからファイルを削除、上位ディレクトリに移動してからrmdirでディレクトリを削除すること
・ファイル数が不定の場合、パイプするときにはかならずxargsを用いるべし
これだけでは防げないかもしれませんがいまのところ重要ファイルを削除した経験はないです。
Re:対策 (スコア:1)
test -z "$STEAMROOT" やら test -n "$STEAMROOT" やらでチェックするんじゃないっすかね.
Re: (スコア:0)
STEAMROOT="/tmp "
Re: (スコア:0)
STEAMROOT="/"
Re: (スコア:0)
まず、消す直前に意図したものがあるのかチェックしてないのは致命的。
ディレクトリがあるのかもそうだけど、自分が作ったものならどんなファイルがそこにあるか知ってるはずだろ。ものぐさせずに*じゃなく全部の名前を書くべき。
そして、STEAMROOTを保存するときに、/を付けた状態で保存してないのもミスの原因。必ず/を付けてコマンド打つなら保存するときにつけるべき。
でも、Sym-linkしてあってもシェルベースではファイルがないということはないのでは。
このSTEAMROOTとかをCのバイナリで作ったなら、その中でlstatしてないのかもね。これもまぁよくあるバグ。
Re: (スコア:0)
bashならスクリプトの先頭に set -u しておく。
というか、自分なら未定義の変数を空文字列として展開する言語を使用しない。
Re:対策 (スコア:2)
今回の場合、変数は未定義ではなく空文字列に定義されていたので、 set -u じゃ防げないと思うよ。ただし、僕は議論をちゃんと追っておらず、どうして空文字列に定義されていたのかは知らないので、理由によっては空文字列に定義する部分で set -u されていれば防げた可能性はあるけど (でもぱっと見ではそうは見えない。どちらかというと set -e の方が関係ありそう)。