我尝试寻找这个问题的答案,但到目前为止没有运气:
我有一个运行其他一些脚本的脚本,其中许多其他脚本都有“set -x”,这使它们打印它们执行的每个命令。我想摆脱它,但如果任何脚本将错误消息发送到 stderr,则保留信息。
所以我不能简单地写 ./script 2>/dev/null
另外,我没有编辑其他脚本的权限,因此我无法手动更改设置选项。
我正在考虑将所有内容从 stderr 记录到单独的文件并过滤掉跟踪命令,但也许有更简单的方法?
答案1
使用bash
4.1 及更高版本,您可以执行以下操作
BASH_XTRACEFD=7 ./script.bash 7> /dev/null
bash
(当作为 调用时也有效sh
)。
基本上,我们告诉在文件描述符 7 而不是默认的 2 上bash
输出输出xtrace
,并将该文件描述符重定向到/dev/null
. fd 号是任意的。使用脚本中未使用的高于 2 的 fd。如果您在其中输入此命令的 shell 是bash
或yash
,您甚至可以使用大于 9 的数字(尽管如果文件描述符由 shell 内部使用,您可能会遇到问题)。
如果您调用该脚本的 shellbash
是zsh
,您还可以执行以下操作:
(export BASH_XTRACEFD; ./script.bash {BASH_XTRACEFD}> /dev/null)
为变量自动分配 9 以上的第一个空闲 fd。
对于旧版本的bash
,另一种选择是,如果使用(与或相对)xtrace
打开,则将重新定义为导出函数,该函数在传递时不执行任何操作(尽管这会破坏脚本,如果它(或它调用的任何其他脚本)用于设置位置参数)。set -x
#! /bin/bash -x
set -o xtrace
set
-x
bash
set
喜欢:
set()
case $1 in
(-x) return 0;;
(-[!-]|"") builtin set "$@";;
(*) echo >&2 That was a bad idea, try something else; builtin set "$@";;
esac
export -f set
./script.bash
另一种选择是在文件中添加一个 DEBUG 陷阱,该陷阱在每个命令之前$BASH_ENV
执行。set +x
echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash
set -x
但是,当在子 shell 中完成时,这将不起作用。
正如 @ilkkachu 所说,只要您对文件系统上的任何文件夹具有写入权限,您至少应该能够复制脚本并对其进行编辑。
如果没有地方可以编写脚本的副本,或者每次更新原始脚本时不方便制作和编辑新副本,您仍然可以执行以下操作:
bash <(sed 's/set -x/set +x/g' ./script.bash)
$0
如果脚本执行任何奇特的操作或特殊变量$BASH_SOURCE
(例如查找与脚本本身位置相关的文件),则该方法(以及复制方法)可能无法正常工作,因此您可能需要进行更多编辑,例如替换$0
为脚本的路径...
答案2
因为它们是脚本,所以你可以复制它们并进行编辑。
除此之外,过滤输出看起来很简单,您可以显式设置PS4
为比单个加号更不寻常的内容,以使过滤更容易:
PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'
(当然,这会崩溃 stdout 和 stdin,但是在 Bash 中仅通过管道传输 stderr 会有点麻烦,所以我会忽略它)