Answers:
使用bash
4.1及更高版本,您可以执行
BASH_XTRACEFD=7 ./script.bash 7> /dev/null
(当bash
作为调用时也有效sh
)。
基本上,我们要在文件描述符7而不是默认值2上bash
输出xtrace
输出,并将该文件描述符重定向到/dev/null
。fd数是任意的。使用高于2的fd,否则脚本中不会使用该fd。如果您要在其中输入此命令的shell是bash
或yash
,则您甚至可以使用大于9的数字(尽管如果文件描述符由shell内部使用,则可能会遇到问题)。
如果您bash
从中调用该脚本的shell 是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
另一种选择是在每个命令之前执行的$BASH_ENV
文件中添加DEBUG陷阱set +x
。
echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash
但是,如果set -x
在子外壳中完成,那将行不通。
正如@ilkkachu所说,只要您对文件系统上的任何文件夹具有写许可权,您至少应该能够复制该脚本并进行编辑。
如果无处可写脚本副本,或者每次对原始脚本进行更新时都不方便制作和编辑新副本,那么您仍然可以执行以下操作:
bash <(sed 's/set -x/set +x/g' ./script.bash)
如果脚本进行任何花哨的操作$0
或诸如此类的特殊变量$BASH_SOURCE
(例如,查找与脚本本身位置相关的文件),则该方法(和复制方法)可能无法正常工作,因此您可能需要进行更多编辑,例如替换$0
为脚本的路径...
{BASH_XTRACEFD}>
技巧同样适用于bash
4.1或更高版本。
ksh93
或bash
在该变量没有在命令(比较的环境中通过<shell> -c 'export fd; printenv fd {fd}> /dev/null'
的zsh
,bash
和ksh93
)。您可以分两步进行操作,也可以使用来使它在ksh93
/中工作,但如果xtrace选项处于启用状态,则会产生副作用。bash
eval
bash
由于它们是脚本,因此您可以复制它们并进行编辑。
除此之外,过滤输出看起来很简单,您可以显式设置PS4
为比单个加号更不寻常的内容,以使过滤更容易:
PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'
(当然,这会使stdout和stdin崩溃,但是在Bash中仅对stderr进行管道处理会有点毛茸茸,因此我将忽略它)
PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
。
bash
有问题的,因为它grep
是异步运行的(bash没有等待它,因此它可以(而且经常)在脚本中的下一个命令启动后输出东西)。
./script 2>some_file