コマンドをエコーしてシェルスクリプトを実行する方法はありますかbut実際には実行していませんか?
名前が変数に格納されているファイルを削除するスクリプトがあるとします。
#!/bin/bash
set -v
FN="filename"
rm -f ${FN}
set -v
を追加すると、実行前に次のコマンドがエコーされます。
$ ./scr.sh
FN="filename"
rm -f ${FN}
ここで、実際にファイルを削除しないこのスクリプトのフローを確認します。 IOW、外部環境やファイルシステムへの影響を防ぎたい。これは可能ですか?
すべてのコマンドをecho
コマンドでラップすることもできますが、長いスクリプトを使用するのは面倒です。
実際にそれを行わずにスクリプトを実行する方法を確認するためにスクリプトをステップ実行する方法はありません。あなたの例では、if
ステートメントやループはありません。しかし、実際のスクリプトでは、多くの場合、条件付きステートメントがたくさんあります。どのブランチが取得されるかは、シェルが前のコマンドを実行したときに何が起こったかに依存することがよくあります。コマンドが実行されない場合、シェルが生成する出力や、次の条件付き分岐や割り当てステートメントが依存する可能性のある戻りコードがどのようなものであるかをシェルが知る方法はありません。
スクリプトを精査し、スクリプトを実行する前にそれが何をするのかを知りたいということであれば、それは悪い考えではありません。しかし現実的には、そのための最善の方法は、less
またはvi
または類似のものでファイルを参照することです。
追加
スクリプトを開発していて、それを最初からステップ実行してロジックをテストしたいが、バグがあった場合に実際には何のダメージも与えたくない場合、私がよく使用できる解決策は、変更のみです。 echo
を前面に貼り付けることにより損傷を与える可能性のあるステートメント。
これは、(a)反復する項目のリストまたは変数に設定する値の生成は、ファイルシステムを変更せずに生成できることが多く、通常は(b)通常は十分なため、典型的な実際のスクリプトで機能します。コマンドを実行した場合、成功すると想定します。
エコーする必要があると思いますが、コマンドを変数に入れれば、オンとオフを切り替えることができます。また、コマンドは関数にすることも、必要に応じて洗練させることもできます。
#!/bin/bash
echo 'Debug'
D=echo
:>| testy
ls -l testy
$D rm -f testy
ls -l testy
echo $'\n\nLive'
D=
:>| testy
ls -l testy
$D rm -f testy
ls -l testy
!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
Live
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
ls: cannot access testy: No such file or directory
Bashの-xオプションを使用してフローをトレースしますが、これでもコマンドは実行されます。
あなたができる最善のことは、エコーのように置くか、rmのような外部効果を持つコマンドをコメントアウトすることです。少なくとも、すべての行を変更する必要はありません。
ドライランの特定の方法はわかりませんが、不明なスクリプトを理解するためにいくつかの予防策を使用できます。
bash -n <script>
を使用します。 gnu bashマニュアルから https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html-n Read commands but do not execute them; this may be used to check a script for syntax errors. This option is ignored by interactive shells.
alias rm="rm -i" alias cp="cp -i" alias mv="mv -i"
sedのようなストリームエディタの場合sed -i
(-iを指定せずにファイルを変更します-iはsedの予行演習を行います。詳細はマニュアルページを確認してください)コマンド全体をコピーして実行できます。実際のコマンドの直前に画面に出力を表示し、コマンドを使用してユーザー入力が続行されるのを待ちます。例sed -i <pattern>
_sed <pattern> read -p "Press any key..." sed -i <pattern>
に置き換えますまた、緊急データが復元できるように、システムにバックアップポイントを保持することを常にお勧めします。
set –n
を実行するか、既存のset –v
コマンドにn
を追加します。ただし、これによりシェルはコマンドを評価せず、if
やwhile
も評価しないため、操作の流れをよく理解できなくなる可能性があります。
ここに私が使用したい小さな構成があります:
#!/bin/sh
verbose=false
really=true
# parse arguments
while [ $# -ge 1 ]
do
case "$1" in
-v) verbose=true ;;
-n) really=false; verbose=true ;;
esac
shift
done
doCmd() {
if $verbose; then echo "$@"; fi
if $really; then "$@"; fi
}
doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah
変更が行われないようにする場合は、特権を持たないユーザーとしてスクリプトを実行できます。
Sudo -u nobody ./scr.sh
あなたの例では、これはFN="filename"
いつものように。技術的にはコマンドrm -f ${FN}
同様に、nobodyにファイルを削除するために必要な権限がない場合は何も起こりません。
もちろん、これは条件付きワークフローで問題を引き起こします。 rm
コマンドが失敗したという事実は、スクリプトの他の部分に影響を与える可能性があります。