在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
当前回答
Set -x或Set -o xtrace展开变量并在行前打印一个小的+号。
Set -v或Set -o verbose不会在打印之前展开变量。
使用set +x和set +v关闭上述设置。
在脚本的第一行,可以输入#!/bin/sh -x(或-v)与后面脚本中的set -x(或-v)具有相同的效果。
上面的代码也适用于/bin/sh。
关于set属性和调试,请参阅bash-hackers的wiki。
$ cat shl
#!/bin/bash
DIR=/tmp/so
ls $DIR
$ bash -x shl
+ DIR=/tmp/so
+ ls /tmp/so
$
其他回答
我使用一个函数来回显并运行命令:
#!/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
Shuckc对回显选择行的回答有一些缺点:您最终也会回显以下set +x命令,并且您失去了使用$?因为它被集合+x覆盖了。
另一种选择是在子shell中运行命令:
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
但是,这确实会导致为命令创建新子shell的开销。
在命令行上,在bash脚本名称之前键入“bash -x”。例如,要执行foo.sh,输入:
bash -x foo.sh
对于zsh,使用echo
setopt VERBOSE
为了调试,
setopt XTRACE
可以使用-x选项在调试模式下执行Bash脚本。
这将回显所有命令。
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