在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
当前回答
为了允许复合命令被回显,我使用eval加上Soth的exe函数来回显和运行命令。这对于管道命令非常有用,否则这些管道命令只显示不显示或只显示管道命令的初始部分。
没有eval:
exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt
输出:
$
file.txt
eval:
exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'
的输出
$ exe eval 'ls -F | grep *.txt'
file.txt
其他回答
在命令行上,在bash脚本名称之前键入“bash -x”。例如,要执行foo.sh,输入:
bash -x foo.sh
我使用一个函数来回显并运行命令:
#!/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
为了允许复合命令被回显,我使用eval加上Soth的exe函数来回显和运行命令。这对于管道命令非常有用,否则这些管道命令只显示不显示或只显示管道命令的初始部分。
没有eval:
exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt
输出:
$
file.txt
eval:
exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'
的输出
$ exe eval 'ls -F | grep *.txt'
file.txt
另一种选择是在你的脚本顶部放置"-x",而不是在命令行上:
$ cat ./server
#!/bin/bash -x
ssh user@server
$ ./server
+ ssh user@server
user@server's password: ^C
$
综合所有的答案,我发现这是最好的,最简单的
#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
exe(){
set -x
"$@"
{ set +x; } 2>/dev/null
}
# example
exe go generate ./...
{set +x;} 2>/dev/null from https://stackoverflow.com/a/19226038/8608146
如果需要命令的退出状态,如这里所述
Use
{ STATUS=$?; set +x; } 2>/dev/null
然后使用$STATUS,比如在最后退出$STATUS
一个稍微有用一点的
#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
_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!