在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
attributes和debugging上查看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 "\$ $@" ; "$@" ; }
这看起来很有希望,但我不能为我的生活弄清楚它的作用。我在Google bash页面搜索并搜索了“\ $”和“$ @”,并且一无所获。
我知道正在创建一个名为“exec()”的函数。我理解花括号标记了函数的开头和结尾。我想我明白,分号标志着多行命令之间的“硬回程”,所以'{echo“\ $ $ @”; “$ @”;从本质上说:
{
echo "\$ $@"
"$@"
}
任何人都可以给我一个简短的解释,或者在哪里可以找到这些信息,因为很明显我的google-fu失败了吗?
(没有意义在旧线程上开始一个新问题,我的目标是将输出重新路由到文件。“set -x; [commands]; set + x”方法对我来说效果很好,但我可以' t弄清楚如何将结果回显到文件而不是屏幕,所以我试图理解这个其他方法,希望我可以使用非常糟糕的理解重定向/管道/ tee /等来做同样的事情。)
谢谢!
后期编辑:
经过一些修补,我相信我弄明白了。这是我需要的等效代码:
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
正是我需要的。谢谢!
对于zsh echo
setopt VERBOSE
并用于调试
setopt XTRACE
对于csh
和tcsh
,你可以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.
为了允许回复复合命令,我使用eval
加上Soth的exe
函数来回显然后运行命令。这对于管道命令非常有用,否则管道命令只会显示或者只显示管道命令的初始部分。
没有评估:
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
set -x
会给你你想要的东西。
这是一个示例shell脚本来演示:
#!/bin/bash
set -x #echo on
ls $PWD
这会扩展所有变量并在输出命令之前打印完整命令。
输出:
+ ls /home/user/
file1.txt file2.txt
你也可以通过将它们包装在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
我使用函数来回显然后运行命令
#!/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
命令被回应,你失去了用$?
测试退出代码的能力,因为它被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的开销。
另一种选择是将“-x”放在脚本的顶部而不是命令行:
$ cat ./server
#!/bin/bash -x
ssh user@server
$ ./server
+ ssh user@server
user@server's password: ^C
$
(对于所选答案的评论不足。)
根据TLDP的Bash Guide for Beginners: Chapter 2. Writing and debugging scripts
2.3.1。调试整个脚本
$ bash -x script1.sh
...
现在有一个完整的Bash调试器,可以在SourceForge上找到。大多数现代版本的Bash都提供这些调试功能,从3.x开始。
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.
...
或者,可以在脚本本身中通过向第一行shell声明添加所需选项来指定这些模式。可以组合选项,通常是UNIX命令的情况:
#!/bin/bash -xv
在bash脚本的名称前面的命令行上键入“bash -x”。例如,要执行foo.sh,请键入:
bash -x foo.sh
您可以使用-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