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
。
请参阅 bash-hackers' wiki 上关于 set
属性 和 调试 的内容。
$ cat shl
#!/bin/bash
DIR=/tmp/so
ls $DIR
$ bash -x shl
+ DIR=/tmp/so
+ ls /tmp/so
$
set -x
会给你想要的结果。
这里是一个演示脚本的示例:
#!/bin/bash
set -x #echo on
ls $PWD
这将展开所有变量并在输出命令之前打印完整的命令。
输出:
+ ls /home/user/
file1.txt file2.txt
set -o verbose
或者 set -v
(只有“verbose”)或者 set -o xtrace
或者 set -x
(只有“xtrace”)或者 set -xv
(两者都有)或者 set -o xtrace -o verbose
(两者都有)。 - Dennis Williamson我使用一个函数来回显和运行命令:
#!/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
++ set +x
,同时看起来更干净。但是,对于只有一两个语句的情况,bhassel 的答案使用子 shell 是最方便的。 - Brent Faustcp "foo bar" baz
和 cp foo "bar baz"
。 因此,它适用于向用户显示进度信息,但不适用于调试输出或记录可重现命令等场景。不同的使用情况。在 zsh
中,你可以使用 :q
修改符来保留引号:exe() { echo '$' "${@:q}" ; "$@" ; }
。 - Andrew Jankeexe(cut -d ' ' -f9,10 --complement ${folder}/hog_crop_px.txt) | paste - ${folder}/lbp_crop_px.txt > ${folder}/crop_px.tx
给出了syntax error near unexpected token
cut'`错误,尽管在没有exe()命令的情况下可以完美执行。有什么建议吗? - penelopeeval
单词的实例。因此,不要期望它能正确处理 exe eval "echo 'eval world'"
! - mwfearnley您也可以通过将脚本中需要调试的代码放在set -x
和set +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
set +x
。 - ilw{ set +x; } &> /dev/null
来消除set +x
的输出。 - Kjulyshuckc的回答用于回显特定行有一些缺点:你最终会看到set +x
命令的输出,而且你失去了使用$?
测试退出码的能力,因为它被set +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 的开销。
++ set +x
输出的好方法。 - Brent Faustif [ $? -eq 0 ]
жӣҝжҚўдёәif (set -x; COMMAND)
гҖӮ - Amedee Van Gasse2.3.1. Debugging on the entire script
$ bash -x script1.sh
...
There is now a full-fledged debugger for Bash, available at SourceForge. These debugging features are available in most modern versions of Bash, starting from 3.x.
2.3.2. Debugging on part(s) of the script
set -x # Activate debugging from here w set +x # Stop debugging from here
...
Table 2-1. Overview of set debugging options
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.
...
Alternatively, these modes can be specified in the script itself, by adding the desired options to the first line shell declaration. Options can be combined, as is usually the case with UNIX commands:
#!/bin/bash -xv
另一个选择是在脚本顶部放置“-x”,而不是在命令行中使用:
$ cat ./server
#!/bin/bash -x
ssh user@server
$ ./server
+ ssh user@server
user@server's password: ^C
$
你可以使用-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
bash -vx
与 set -x
相同,都可以打开调试模式,但不会进行变量替换。 - loa_in_综合所有答案,我发现这是最好的、最简单的。
#!/bin/bash
# https://dev59.com/yHE85IYBdhLWcg3wShaf#64644990
exe(){
set -x
"$@"
{ set +x; } 2>/dev/null
}
# example
exe go generate ./...
{ set +x; } 2>/dev/null
来自 https://dev59.com/Q2Ys5IYBdhLWcg3wBvf7#19226038
如果需要命令的退出状态,如 这里 所提到的
可以使用
{ STATUS=$?; set +x; } 2>/dev/null
在结束时可以像这样使用$STATUS
,比如exit $STATUS
稍微有点用处的一个
#!/bin/bash
# https://dev59.com/yHE85IYBdhLWcg3wShaf#64644990
_exe(){
[ $1 == on ] && { set -x; return; } 2>/dev/null
[ $1 == off ] && { set +x; return; } 2>/dev/null
echo + "$@"
"$@"
}
exe(){
{ _exe "$@"; } 2>/dev/null
}
# examples
exe on # turn on same as set -x
echo This command prints with +
echo This too prints with +
exe off # same as set +x
echo This does not
# can also be used for individual commands
exe echo what up!
#!/bin/bash
。 - mhck在Bash脚本名称前,在命令行上键入“bash -x”。例如,要执行foo.sh,请键入:
bash -x foo.sh