在Shell脚本中回显一些命令行(对于单个命令打开回显)

24
在shell脚本中,我想要为状态和调试目的回显一些主要的(长时间运行的)命令。我知道可以使用set -xset -v命令为所有命令启用回显。但是我不想看到所有命令(特别是不想看到echo命令)。有没有一种方法只针对一个命令打开回显?
我可以这样做,但这样做很丑,并且也会回显set +x这一行:
#!/bin/sh

dir=/tmp
echo List $dir

set -x
ls $dir
set +x

echo Done!

有更好的方法吗?


为什么不在脚本的各个关键点添加一些回显呢? - John3136
@John3136:因为它很麻烦且不可靠...特别是,你最终会重复命令,将其写两次,这将成为维护负担。 - Jonathan Leffler
那是我的第一个想法,但我实际运行的命令有几行长 - 这将会更加混乱... - Den
相关链接:https://dev59.com/Qmct5IYBdhLWcg3wPbMm https://dev59.com/yHE85IYBdhLWcg3wShaf - mjs
另一个不这样做的原因是,它会涉及到引号和变量扩展,并且你仍然不知道你正在运行的确切命令。 - Jannes
4个回答

33

以一个进程的代价,您可以使用:

(set -x; ls $dir)

这会在一个子shell中运行命令,因此set -x仅影响括号内的内容。你不需要编写或查看set +x。我在需要进行选择性跟踪时使用它。


6
这种技术只有在需要跟踪的命令需要设置变量以供父shell使用时才会出现问题。基本上,子shell无法修改原始shell的变量,因此修改严格局限于括号内部的代码。 - Jonathan Leffler
8
此命令为:{ set +x; } 2>/dev/null - 参考自 Bash set +x without it being printed - Stack Overflow - sdaau
@sdaau:有趣的——一旦看到就很明显,但在你看到之前并不明显。 - Jonathan Leffler

5
使用这个函数怎么样?
runtraced() {
    echo "$@"
    "$@"
}

dosomething
runtraced dosomethingelse

这很不错——直到你需要跟踪管道。runtraced ls | wc -l并不像你期望的那样工作(它跟踪了ls但没有跟踪wc -l)。或者其他类似的结构。 - Jonathan Leffler
返回翻译后的文本:True。也许一个工作版本会包括一个 eval "$1"(使用 runtraced "ls | wc -l")。 - Jo So

2
一种简单的方法是使用heredoc和未解释的字符串。它在POSIX上可移植且快速。
...
% cmd='ls ${dir}'
% sh -x <<_EOF_
> ${cmd}
> _EOF_
...

您可以按照这种方式构建整个脚本,根据需要进行解析和/或修改,将它们保存到并从shell变量中调用它们,并在另一个脚本或shell函数中运行它们:
...
% script="$(cat </some/entire/script.sh)"
% script="$(pipeline | processing | on | ${script})"    
% sh -x <<_EOF_ 2>&1 | grep ${specific_cmds_Im_looking_for}
> ${script}
> _EOF_
<desired output>

在我的回答POSIX compliant way to see if a function is defined in an sh script中,我更详细地描述了这个问题的原因和解决方法。在 Stack Exchange 上,我详细讨论了如何使用heredoc来解决一些烦人的引用问题,以回答Is there a way to get actual (uninterpreted) shell arguments in a function or script?
-Mike

2

基于Jonathan Leffler的答案,这个方法的工作方式相同,只是更加清晰,因为命令后不需要任何内容。但是你需要指定使用哪个shell。这是一个sh的示例:

sh -xc ls $dir

1
您的版本可能需要额外使用管道符号进行引用和转义。例如(set -x; echo'toronto"s rules'| wc -c)与sh -xc'echo'"''"'toronto"s rules'"'"'| wc -c' - iruvar
没错,它并不在所有情况下都能很好地工作。感谢提示! - Den

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接