在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
在一个shell脚本,我如何回显所有shell命令调用和展开任何变量名?
例如,给定以下一行:
ls $DIRNAME
我希望脚本运行该命令并显示以下内容
ls /full/path/to/some/dir
目的是保存所有调用的shell命令及其参数的日志。是否有更好的方法来生成这样的日志?
当前回答
Set -x会得到你想要的。
下面是一个示例shell脚本来演示:
#!/bin/bash
set -x #echo on
ls $PWD
这将展开所有变量,并在输出命令之前打印完整的命令。
输出:
+ ls /home/user/
file1.txt file2.txt
其他回答
对于zsh,使用echo
setopt VERBOSE
为了调试,
setopt XTRACE
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的开销。
我使用一个函数来回显并运行命令:
#!/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和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
根据TLDP的Bash初学者指南:第2章。编写和调试脚本:
2.3.1. 调试整个脚本 $ bash -x script1.sh ... 现在在SourceForge上有一个成熟的Bash调试器。从3.x开始,这些调试特性在大多数现代版本的Bash中都可以使用。 2.3.2. 调试脚本的一部分 set -x #从这里激活调试 w set +x #从这里停止调试 ... 表2 - 1。set调试选项概述
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十五