私はBash 4.3.48(1)を使用しており、テストVPSシステムで次のコマンドパターンを実行しています。
rm -rf ${drt}/${pma}*
このコマンドは、オペレーティングシステム全体(Ubuntu)を削除します。これは、cd /
次のエラーのみを返す実行によって明らかになります。
bash:cd /:そのファイルまたはディレクトリはありません。
詳しくは、上記の元のコマンドで変数が宣言されていないため、これが発生します。
~/repoName/assignments_variables.sh
エクスポートした変数のリスト(drt
および含む)を含むファイルを作成しましたpma
。代わりに
source /etc/bash.bashrc
runningを実行しました/etc/bash.bashrc
が、これはファイルが現在のセッションにのみ関連しているため無効です(後で子セッションでデータを実行するファイル自体を実行するために使用できますが)。
これで、間違ったパスが問題の一般的な原因であることが明らかになりました。もっと深く掘り下げて、次の質問をしたいと思います。
rm -rf
間違った変数拡張が無視され続けるのはなぜですか/*
?rm -rf
ディレクトリを削除する必要があることを知っています。ただ見つかった場合は、存在しないディレクトリへの部分パスに依存してはいけません(/*
オペレーティングシステムが削除される可能性があります)。rm -rf
将来の可能性のある同様の誤ったパス状況(誤った変数拡張のため)を処理するために、このコマンドをどのように改善できますか?
Bashが(指示を元に戻すまで)空の変数を拡張しないようにするBashディレクティブはありますか?
これを強調したいです。私は通常バックアップするのではなく、二重バックアップをします。これは実際にバックグラウンドでx3バックアップを使用するテスト環境です。
答え1
変数が存在しない場合、何が拡張されますか?
試してみましょう(エコに注意してください):
$ unset drt pma
$ echo rm -rf ${drt}/${pma}*
rm -rf /bin /boot /dev /etc /hello /home /initrd.img /lib /lib32 /lib64 /libx32 /media /mnt /opt /proc /root /run /sbin /srv /sys /tmp /usr /var /vmlinuz /vmlinuz.old
これがシステム全体です(すでに確認したように)。
問題はシェルによる拡張です。
防止
これが起こらないようにするにはどうすればよいですか?
シェルが空の変数を拡張するのを防ぎます。 varが空であるか設定されていない場合、
拡張が発生します。${var:?message}
message
そして実行が停止しました(致命的なエラー)。テストを受けてください:
$ echo rm -rf "${drt:?Missing variable drt}"/"${pma:?Missing variable pma}"*
そして、このソリューションはPOSIXと互換性があります。
答え2
すでに指摘したように、これら2つの変数drt
はpma
スクリプト環境には存在しません。つまり、シェルはそれを空の文字列に展開します。生成されたコマンドは次のとおりですrm -rf /*
(*
ルートディレクトリで利用可能なすべてのコマンドにさらに拡張されます)。
ルートとして実行しても、ルートディレクトリ自体は削除されませんrm -rf /*
。また、私(そしてJesse_b誰が指摘しましたか?)エラーメッセージが少し混乱しています。
bash: cd /: No such file or directory
私が直接このエラーメッセージを生成できる唯一の方法は、コマンドを実行することです"cd /"
(引用符を参照)。実際に削除された場合、/
エラーメッセージは次のようになります。
bash: cd: /: No such file or directory
イサクはいくつかのヒントを提供しました。今後このようなことを防止する方法はありますが、提案事項のみ申し上げます。
- ルートシェルプロンプトで作業しないでください。
- root権限を必要とするスクリプトを作成する場合は、
sudo
以下を使用してください。特定これらの昇格されたコマンドは実際に必要です。スクリプト全体をrootとして実行しないでください。特に開発プロセスにはありません。 /etc/bash.bashrc
通常、何らかの理由で連絡する必要はなく、明示的に提供する必要もありません。環境変数は次のように生成できます。- ユーザー自身のもの
$HOME/.bashrc
(対話型セッションでスクリプトを実行したい場合)または - スクリプト自体または
- 別のファイルに(次のように作成されます)~のためscript)はスクリプトから明示的にソースを取得します。
- 環境変数が指すファイルから
BASH_ENV
。
- ユーザー自身のもの
この場合、あなたを救うもう一つのセキュリティ対策は、()の下でスクリプトを実行し、()set -u
の下でスクリプトを実行することです。シェルオプションは設定されていない変数の拡張をエラーとして扱い、コマンドがゼロ以外の終了状態で終了するとすぐにシェルセッションを終了します。nounset
set -e
errexit
nounset
errexit
スクリプト
#!/bin/bash -ue
echo "$hello"
echo "world"
出力されず、代わりworld
にメッセージが発生します。
script.sh: line 3: hello: unbound variable
終了前。 (-u
終了操作を実行し-e
ますが、何もしません。この簡単な例では)。
答え3
変数には補間セットがないため、globが実行され、rm -rf /*
その下のすべての項目が/
壊れます。
エラーチェックを追加します。また、引用してください。"$variables"
そうしないと、シェルがそれを分割して$variables
スペースやその他の問題のある文字が含まれていると、愚かなことが発生する可能性があります。特にaのrm -rf
場合。
if [[ -z "$drt" ]]; then
echo >&2 "drt variable not set ??"
exit 1
fi
if [[ -z "$pma" ]]; then
echo >&2 "pma variable not set ??"
exit 1
fi
rm -rf "${drt}"/"${pma}"*
(または問題の少ない言語でプログラム...)