【问题标题】:how to silently disable xtrace in a shell script?如何在 shell 脚本中静默禁用 xtrace?
【发布时间】:2013-06-28 13:25:30
【问题描述】:

我正在编写一个循环遍历一些值并为每个值运行一个长命令行的 shell 脚本。我想一路打印出这些命令,就像make 在运行makefile 时所做的那样。我知道我可以在运行它们之前“回显”所有命令,但感觉不优雅。所以我正在寻找set -x 和类似的机制:

#!/bin/sh

for value in a long list of values
do
    set -v
    touch $value # imagine a complicated invocation here
    set +v
done

我的问题是:在每次迭代中,不仅会打印出有趣的行,还会打印出 set +x 行。有没有可能防止这种情况发生?如果没有,您推荐什么解决方法?

PS:上面的MWE使用sh,但我也安装了bashzsh以防万一。

【问题讨论】:

标签: shell


【解决方案1】:

在子shell中沙箱:

(set -x; do_thing_you_want_traced)

当然,在该子shell中对变量或环境所做的更改将会丢失。

如果您真的关心这一点,您还可以使用 DEBUG 陷阱(使用 set -T 使其被函数继承)来实现您自己的 set -x 等效项。

例如,如果使用 bash:

trap_fn() {
  [[ $DEBUG && $BASH_COMMAND != "unset DEBUG" ]] && \
    printf "[%s:%s] %s\n" "$BASH_SOURCE" "$LINENO" "$BASH_COMMAND"
  return 0 # do not block execution in extdebug mode
}
trap trap_fn DEBUG

DEBUG=1
# ...do something you want traced...
unset DEBUG

也就是说,发出 BASH_COMMAND(作为 DEBUG 陷阱可以做的)并不完全等同于 set -x;例如,它不显示扩展后的值。

【讨论】:

    【解决方案2】:

    您想尝试使用单行 xtrace:

    function xtrace() {
      # Print the line as if xtrace was turned on, using perl to filter out
      # the extra colon character and the following "set +x" line.
      (
        set -x
        # Colon is a no-op in bash, so nothing will execute.
        : "$@"
        set +x
      ) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2
      # Execute the original line unmolested
      "$@"
    }
    

    原始命令在同一 shell 中执行身份转换。就在运行之前,您会获得参数的非递归 xtrace。这使您可以对您关心的命令进行 xtrace,而无需向 stederr 发送每个“echo”命令的重复副本。

    # Example
    for value in $long_list; do
      computed_value=$(echo "$value" | sed 's/.../...')
      xtrace some_command -x -y -z $value $computed_value ...
    done
    

    【讨论】:

    • 我喜欢这个除了是什么让我用谷歌搜索这个问题!感谢您不坚持 OP 问题描述。 (当人们抱怨松散地适用于 OP 主题的答案时,我真的很恼火。这是关于 1,000,000 人将在 1 OP 之后出现。)
    • 谢谢,虽然我会说我在回答 OP,但我只是在回答未提出的问题,即如何用他们的“set -x”和“set +x”对,而不是被他们提出的字面问题所限制。我发现这在许多专业环境中是一种有用的策略。人们倾向于要求一些超具体的东西,这只是他们问题解决方案的一个例子。
    【解决方案3】:

    下一个命令禁用“xtrace”选项:

    $ set +o xtrace

    【讨论】:

    • 有什么理由比set +x更喜欢它吗?
    • 要清楚,这没有响应的原因是 OP 要求“静默”。这不是沉默; set +o xtrace 包含在跟踪日志中,就像set +x 包含在 OP 原始代码的跟踪日志中一样(这是他们提出的问题以知道如何解决)。
    【解决方案4】:

    我想到了

     set -x >/dev/null 2>1; echo 1; echo 2; set +x >/dev/null 2>&1
    

    但是得到了

    + echo 1
    1
    + echo 2
    2
    + 1> /dev/null 2>& 1
    

    我对这些结果感到惊讶。 .... 但是

    set -x ; echo 1; echo 2; set +x
    + echo 1
    1
    + echo 2
    2
    

    看起来符合您的要求。

    当我将每个语句放在其唯一的行上时,我看到了类似的结果(集合 +x 除外)

    IHTH。

    【讨论】:

    • 仅供参考 -- set -x 输出仅用于标准错误,除非在 bash 4 中被 BASH_XTRACEFD 覆盖。
    • ...顺便说一下,里程确实会有所不同;我无法在 bash 4.2.45(1) 上重现此处报告的行为。
    • @charlesDuffy:我使用 ksh,但我一直都在阅读 bash(这里)。感谢您的详细信息!祝大家好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 2020-01-01
    • 2013-11-17
    • 1970-01-01
    • 2016-04-20
    • 2010-09-06
    相关资源
    最近更新 更多