web-dev-qa-db-ja.com

bashシェルスクリプトでコマンドをエコーするが、実行しない方法は?

コマンドをエコーし​​てシェルスクリプトを実行する方法はありますかbut実際には実行していませんか?

名前が変数に格納されているファイルを削除するスクリプトがあるとします。

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

set -vを追加すると、実行前に次のコマンドがエコーされます。

$ ./scr.sh
FN="filename"
rm -f ${FN}

ここで、実際にファイルを削除しないこのスクリプトのフローを確認します。 IOW、外部環境やファイルシステムへの影響を防ぎたい。これは可能ですか?

すべてのコマンドをechoコマンドでラップすることもできますが、長いスクリプトを使用するのは面倒です。

11
ysap

実際にそれを行わずにスクリプトを実行する方法を確認するためにスクリプトをステップ実行する方法はありません。あなたの例では、ifステートメントやループはありません。しかし、実際のスクリプトでは、多くの場合、条件付きステートメントがたくさんあります。どのブランチが取得されるかは、シェルが前のコマンドを実行したときに何が起こったかに依存することがよくあります。コマンドが実行されない場合、シェルが生成する出力や、次の条件付き分岐や割り当てステートメントが依存する可能性のある戻りコードがどのようなものであるかをシェルが知る方法はありません。

スクリプトを精査し、スクリプトを実行する前にそれが何をするのかを知りたいということであれば、それは悪い考えではありません。しかし現実的には、そのための最善の方法は、lessまたはviまたは類似のものでファイルを参照することです。

追加

スクリプトを開発していて、それを最初からステップ実行してロジックをテストしたいが、バグがあった場合に実際には何のダメージも与えたくない場合、私がよく使用できる解決策は、変更のみです。 echoを前面に貼り付けることにより損傷を与える可能性のあるステートメント。

これは、(a)反復する項目のリストまたは変数に設定する値の生成は、ファイルシステムを変更せずに生成できることが多く、通常は(b)通常は十分なため、典型的な実際のスクリプトで機能します。コマンドを実行した場合、成功すると想定します。

8
Nicole Hamilton

エコーする必要があると思いますが、コマンドを変数に入れれば、オンとオフを切り替えることができます。また、コマンドは関数にすることも、必要に応じて洗練させることもできます。

#!/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
8
user191016

Bashの-xオプションを使用してフローをトレースしますが、これでもコマンドは実行されます。

あなたができる最善のことは、エコーのように置くか、rmのような外部効果を持つコマンドをコメントアウトすることです。少なくとも、すべての行を変更する必要はありません。

5
parkydr

ドライランの特定の方法はわかりませんが、不明なスクリプトを理解するためにいくつかの予防策を使用できます。

  1. chroot環境を使用してデバッグスクリプトを実行します。サンドボックスとして機能し、メインシステムファイルの削除/変更に対する保護を提供します。
  2. 構文チェックには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.

  1. 少なくとも一度はスクリプトを読んでください。 answer by user191016 で説明されているように、debugのエコーステートメントを使用できます。
    • 疑わしいコードや危険な傾向のあるコードを探します。
    • 例えばrm、/ dev/sdaなどに影響するコマンドに関連.
  2. 常に通常のユーザーとしてスクリプトを実行するようにしてください不明なスクリプトをrootとして実行しないでください
  3. エイリアスを定義して、スクリプトの開始時にファイルをインタラクティブに変更できるコマンドを作成できます例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>に置き換えます

また、緊急データが復元できるように、システムにバックアップポイントを保持することを常にお勧めします。

4

set –nを実行するか、既存のset –vコマンドにnを追加します。ただし、これによりシェルはコマンドを評価せず、ifwhileも評価しないため、操作の流れをよく理解できなくなる可能性があります。

3
Scott

ここに私が使用したい小さな構成があります:

#!/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
3
Edward Falk

変更が行われないようにする場合は、特権を持たないユーザーとしてスクリプトを実行できます。

Sudo -u nobody ./scr.sh

あなたの例では、これはFN="filename" いつものように。技術的にはコマンドrm -f ${FN}同様に、nobodyにファイルを削除するために必要な権限がない場合は何も起こりません。

もちろん、これは条件付きワークフローで問題を引き起こします。 rmコマンドが失敗したという事実は、スクリプトの他の部分に影響を与える可能性があります。

2
Dennis