如何在执行shell命令时回显它们

在外壳脚本中,我如何回显所有调用的shell命令并展开任何变量名?

例如,给定以下行:

ls $DIRNAME

我希望脚本运行命令并显示以下内容

ls /full/path/to/some/dir

目的是保存所有调用的shell命令及其参数的日志。也许有更好的方法来生成这样的日志吗?

997881 次浏览

set -xset -o xtrace扩展变量并在行前打印一个小+号。

set -vset -o verbose在打印前不展开变量。

使用set +xset +v关闭上述设置。

在脚本的第一行,可以将#!/bin/sh -x(或-v)与脚本中稍后的set -x(或-v)具有相同的效果。

以上也适用于/bin/sh

请参阅#0属性调试上的bash黑客wiki。

$ cat shl#!/bin/bash
DIR=/tmp/sols $DIR
$ bash -x shl+ DIR=/tmp/so+ ls /tmp/so$

set -x会给你你想要的。

下面是一个示例外壳脚本来演示:

#!/bin/bashset -x #echo on
ls $PWD

这将扩展所有变量并在命令输出之前打印完整命令。

输出:

+ ls /home/user/file1.txt file2.txt

您还可以通过将脚本中的选定行包装在set -xset +x中来切换它,例如,

#!/bin/bash...if [[ ! -e $OUT_FILE ]];thenecho "grabbing $URL"set -xcurl --fail --noproxy $SERV -s -S $URL -o $OUT_FILEset +xfi

另一种选择是将“-x”放在脚本顶部而不是命令行上:

$ cat ./server#!/bin/bash -xssh user@server
$ ./server+ ssh user@serveruser@server's password: ^C$

为了zsh,回声

setopt VERBOSE

为了调试,

setopt XTRACE

shuckc的回答用于呼应选择行有一些缺点:您最终也会呼应以下set +x命令,并且您失去了使用$?测试退出代码的能力,因为它会被set +x覆盖。

另一种选择是在子shell中运行命令:

echo "getting URL..."( set -x ; curl -s --fail $URL -o $OUTFILE )
if [ $? -eq 0 ] ; thenecho "curl failed"exit 1fi

这将为您提供如下输出:

getting URL...+ curl -s --fail http://example.com/missing -o /tmp/examplecurl failed

但是,这确实会产生为命令创建新子shell的开销。

在命令行的Bash脚本名称之前键入"bash-x"。例如,要执行foo.sh,请键入:

bash -x foo.sh

我使用一个函数来回显并运行命令:

#!/bin/bash# Function to display commandsexe() { echo "\$ $@" ; "$@" ; }
exe echo hello world

其输出

$ echo hello worldhello world

对于更复杂的命令管道等,您可以使用val:

#!/bin/bash# Function to display commandsexe() { echo "\$ ${@/eval/}" ; "$@" ; }
exe eval "echo 'Hello, World!' | cut -d ' ' -f1"

其输出

$  echo 'Hello, World!' | cut -d ' ' -f1Hello

对于cshtcsh,您可以设置set verboseset 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

冗长如果设置,则会在历史替换(如果有)后打印每个命令的单词。由-v命令行选项设置。

回声如果设置了,每个命令及其参数都会在执行前得到回声。对于非内置命令,所有扩展都在回声之前进行。内置命令在命令和文件名替换之前得到回声,因为这些替换是有选择地完成的。由-x命令行选项设置。

为了允许回传复合命令,我使用eval加上Soth的exe函数来回传并运行命令。这对于管道命令很有用,否则这些命令只会显示任何或仅显示管道命令的初始部分。

不包括ava:

exe() { echo "\$ $@" ; "$@" ; }exe ls -F | grep *.txt

产出:

$file.txt

使用ava:

exe() { echo "\$ $@" ; "$@" ; }exe eval 'ls -F | grep *.txt'

其输出

$ exe eval 'ls -F | grep *.txt'file.txt

根据TLDPBash初学者指南:第2章.编写和调试脚本

2.3.1。整个脚本调试

$ bash -x script1.sh

现在有一个成熟的Bash调试器,可在SourceForge获得。这些调试功能在大多数现代版本的Bash中都可用,从3. x开始。

2.3.2。调试脚本的一部分

set -x            # Activate debugging from herewset +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
$ cat exampleScript.sh#!/bin/bashname="karthik";echo $name;
bash -x exampleScript.sh

产出如下:

在此处输入图片描述

您可以使用#0选项在调试模式下执行 Bash脚本。

这将响应所有命令。

bash -x example_script.sh
# Console output+ cd /home/user+ mv text.txt mytext.txt

您也可以在脚本中保存-x选项。只需在sheang中指定-x选项。

######## example_script.sh ####################!/bin/bash -x
cd /home/usermv text.txt mytext.txt
##############################################
./example_script.sh
# Console output+ cd /home/user+ mv text.txt mytext.txt

综合所有的答案,我发现这是最好的,最简单的

#!/bin/bash# https://stackoverflow.com/a/64644990/8608146exe(){set -x"$@"{ set +x; } 2>/dev/null}# exampleexe go generate ./...

{ set +x; } 2>/dev/nullhttps://stackoverflow.com/a/19226038/8608146

如果需要命令的退出状态,如上所述这里

使用

{ STATUS=$?; set +x; } 2>/dev/null

然后使用$STATUS,就像最后使用exit $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/nullecho + "$@""$@"}exe()\{\{ _exe "$@"; } 2>/dev/null}
# examplesexe on # turn on same as set -xecho This command prints with +echo This too prints with +exe off # same as set +xecho This does not
# can also be used for individual commandsexe echo what up!