web-dev-qa-db-ja.com

シェルコマンドが実行されるとエコーする方法

シェルスクリプトで、呼び出されたすべてのシェルコマンドをエコーし​​て変数名を展開する方法を教えてください。

たとえば、次の行があるとします。

ls $DIRNAME

スクリプトでコマンドを実行して次のように表示します。

ls /full/path/to/some/dir

目的は、呼び出されたすべてのシェルコマンドとその引数のログを保存することです。そのようなログを生成するためのおそらくよりよい方法はありますか?

718
Jack Nock

set -xまたはset -o xtraceは、変数を展開して行の前に小さな+記号を表示します。

set -vまたはset -o verboseは、印刷前に変数を展開しません。

上記の設定を無効にするには、set +xset +vを使用します。

スクリプトの最初の行に、スクリプトの後半で#!/bin/sh -x(または-v)と同じ効果を持たせるためにset -x(または-v)を配置できます。

上記は/bin/shでも動作します。

setの属性 および debugging のbash-hackersのwikiを参照してください。

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$
808
Tom

set -xはあなたが欲しいものをあなたに与えるでしょう。

これを示すためのシェルスクリプトの例を次に示します。

#!/bin/bash
set -x #echo on

ls $PWD

これにより、すべての変数が展開され、コマンドの出力前に完全なコマンドが表示されます。

出力:

+ ls /home/user/
file1.txt file2.txt
270
radman

set -xset +xでそれらをラップすることによってあなたのスクリプトの選択行に対してこれを切り替えることもできます。

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi
79
shuckc

関数を使ってエコーしてからコマンドを実行します

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

どの出力

$ echo hello world
hello world

編集する

もっと複雑なコマンドパイプなどにはevalを使うことができます。

#!/bin/bash
#function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello World' | cut -d ' ' -f1"

どの出力

$  echo 'Hello World' | cut -d ' ' -f1
Hello
71
Soth

shuckcの選択行のエコーに対する回答にはいくつかの欠点があります。次のset +xコマンドもエコーされることになり、$?で終了コードを上書きするため終了コードをテストすることができなくなります。 set +x

別のオプションは、サブシェルでコマンドを実行することです:

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

次のような出力が得られます。

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

ただし、これにより、コマンドの新しいサブシェルを作成するオーバーヘッドが発生します。

48
bhassel

別のオプションは、コマンドラインではなく、スクリプトの先頭に "-x"を付けることです。

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

(選択した回答にコメントするには担当者が不十分です。)

32
nooj

_ tldp _ による 初心者向けBashガイド:第2章スクリプトの作成とデバッグ

2.3.1。スクリプト全体のデバッグ

$ bash -x script1.sh

...

SourceForge で入手可能なBash用の本格的なデバッガーがあります。これらのデバッグ機能は、3.x以降の最新バージョンのBashで使用できます。

2.3.2。スクリプトの一部のデバッグ

set -x            # activate debugging from here
w
set +x            # stop debugging from here

...

表2-1。デバッグオプション設定の概要

Short  | Long notation | Result  
-------+---------------+--------------------------------------------------------------
set -f | set -o noglob | Disable file name generation using metacharacters (globbing).  
set -v | set -o verbose| Prints Shell input lines as they are read.  
set -x | set -o xtrace | Print command traces before executing command.  

...

あるいは、これらのモードは、最初の行のシェル宣言に必要なオプションを追加することによって、スクリプト自体で指定できます。通常UNIXコマンドの場合のように、オプションを組み合わせることができます。

#!/bin/bash -xv
19
Afriza N. Arief

コマンドラインでbashスクリプトの名前の前に「bash -x」と入力します。たとえば、foo.shを実行するには、次のように入力します。

bash -x foo.sh
17
Alan

デバッグモードでは、-xオプションを使用してbashスクリプトをexecuteできます。
これはすべてのコマンドをエコーし​​ます。

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt


スクリプトに-xオプションを保存するとすることもできます。 Shebangで-xオプションを指定するだけです。

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt



8
RenRen

上記の誰かが投稿しました:

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

そして、これは有望に見えます、しかし、私は私の人生のためにそれが何をするかについて理解することができません。私はグーグルでman bashページで "\ $"と "$ @"を検索しましたが、絶対に nothing を見つけました。

"exec()"という名前の関数が作成されているのがわかります。中括弧は関数の始まりと終わりを表します。セミコロンは複数行のコマンドの間の「ハードリターン」を示していると私は理解していると思います。その結果、 '{echo "\ $ $ @"; "$ @";本質的には、

{
echo "\$ $@"
"$@"

}

誰かが私に簡単な説明を、またはどこでこの情報を見つけるために与えることができます、明らかに私のgoogle-fuは私に失敗しているので?

(古いスレッドで新しい質問を始めることを意味するものではなく、私の目的は出力をファイルに転送することです。 "set -x; [commands]; set + x"メソッドは私には十分うまくいくでしょうが。画面ではなくファイルに結果を表示する方法を理解するために、リダイレクト/パイプ/ティーなどの理解が非常に乏しいことを期待して、この他の方法を理解しようとしていました。)

ありがとうございます。

後編集:

少し手を加えて、私はそれを考え出したと思います。これが、私が必要としているものと同等のコードです。

SCRIPT_LOG="\home\buddy\logfile.txt"
exe () {
  params="$@"                       # Put all of the command-line into "params"
  printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG"   # Print the command to the log file
  $params                           # Execute the command
}

exe rm -rf /Library/LaunchAgents/offendingfile
exe rm -rf /Library/LaunchAgents/secondoffendingfile

Logfile.txtの結果は次のようになります。

Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/offendingfile
Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/secondoffendingfile

必要なものだけ。ありがとうございます。

5
DebianFanatic

Zshエコー用

 setopt VERBOSE

そしてデバッグ用

 setopt XTRACE
3
zzapper

cshtcshには、set verboseまたはset echoを使用できます(または、両方を設定することもできますが、ほとんどの場合は重複する可能性があります)。

verboseオプションは、入力した正確なShell式をほとんどそのまま表示します。

echoオプションは、スポーンによって実行される内容をより明確に示します。


http://www.tcsh.org/tcsh.html/Special_Shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_Shell_variables.html#echo


Special Shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.

2
cnst
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;

bash -x exampleScript.sh

出力は以下のとおりです。

enter image description here

1
Karthik Arun

複合コマンドがエコーされるようにするために、エコーするためにevalとSothのexe関数を使用してからコマンドを実行します。これは、他の方法ではパイプコマンドの何も表示されない、または最初の部分だけが表示されるようなパイプコマンドに役立ちます。

評価なし

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

出力:

$
file.txt

評価付き:

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

どの出力

$ exe eval 'ls -F | grep *.txt'
file.txt
1
Paul Havens