有人知道在bash中是否可以使用set +x
而不被打印出来吗:
set -x
command
set +x
痕迹
+ command
+ set +x
但它应该只是打印
+ command
Bash的版本是4.1.10(4)。这个问题困扰我有一段时间了——输出被无用的set +x
行所淹没,使跟踪功能不如它本应该有用。
我遇到了同样的问题,但是我找到了一种不使用子shell的解决方案:
set -x
command
{ set +x; } 2>/dev/null
set +x
就是这样一个成功的命令。 - Daniel Aldercommand
的退出状态,可以使用以下形式:{ STATUS=$?; set +x; } 2>/dev/null
。然后在随后的行中轻松检查 $STATUS
。 - Greg Price{ set +x; } 2>&-
。这个命令会直接关闭文件描述符2,而不是将其重定向到/dev/null。有些程序无法处理将输出发送至stderr的情况,因此通常使用/dev/null比较好;但是,Shell的set -x
追踪可以很好地处理它,因此在此处它完美地发挥作用,并且可以使这个命令更加简短。 - Greg Price您可以使用子shell。在退出子shell时,x
的设置将会丢失:
( set -x ; command )
( set -x \n command \n )
比set -x \n command \n set +x
更糟糕在哪里。 - chepnercd
命令:它不会改变父 shell 中的当前目录。 - Andreas Spindlershopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ set +x; } 2>/dev/null'
trace_on
...stuff...
trace_off
function () { set_plus_x='{ set +x; } 2>/dev/null' }
- LexH我最近对此感到非常烦恼,所以我想出了一个解决方案:
shopt -s expand_aliases
_xtrace() {
case $1 in
on) set -x ;;
off) set +x ;;
esac
}
alias xtrace='{ _xtrace $(cat); } 2>/dev/null <<<'
通过如下配置,您可以启用或禁用xtrace,并记录参数分配给变量的方式:
xtrace on
ARG1=$1
ARG2=$2
xtrace off
然后您会得到类似以下的输出:
$ ./script.sh one two
+ ARG1=one
+ ARG2=two
alias xtrace='{ read -t 0&&read;[[ $REPLY == on ]]&&set -x||set +x; } 2>&- <<<'
(如果您在读取时使用默认的REPLY变量,则最好避免使用此方法) - mr.spuratic#!/bin/bash
shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ PREV_STATUS=$? ; set +x; } 2>/dev/null; (exit $PREV_STATUS)'
trace_on
echo hello
trace_off
echo "status: $?"
trace_on
(exit 56)
trace_off
echo "status: $?"
执行时:
$ ./test.sh
+ echo hello
hello
status: 0
+ exit 56
status: 56
exit
周围的()
是不必要的。好吧,也许这有点多虑,但如果这段代码被普遍使用,你就会有一个很好的攻击向量:重新定义trace_on
和trace_off
并注入读取执行命令的代码。如果你单独使用这样的“工具”,那么它是有益的,但如果代码与其他人一起使用,你必须考虑这些非标准化函数的好处是否超过了缺点。就个人而言,我已经选择了{ set +x; } 2>/dev/null
,因为这种结构是通用的,并且不改变退出状态。 - Andreas Spindler()
包裹 exit 56
的部分; 这只是为了展示子进程的 exit 状态在 bash 脚本中是可访问的;如果没有括号,它就不会成为子进程,脚本将在那个点上退出,状态为 65。 - user3286792> call() { set -x; "$@"; { set +x; } 2>/dev/null; }
> call uname -a
+ uname -a
CYGWIN_NT-6.1-WOW W530 3.1.7(0.340/5/3) 2020-08-22 19:03 i686 Cygwin
> call make -j8 *.mak
+ make -j8 some_name.mak
> call() { local rc; set -x; "$@"; rc=$?; { set +x; } 2>/dev/null; return $rc; }
> call true && echo yes
+ true
+ rc=0
yes
> call false && echo yes
+ false
+ rc=1
die() {
local c=${1:--1} m=${2:-'Died'}
echo "$m at ${BASH_SOURCE[1]}:${FUNCNAME[1]} line ${BASH_LINENO[0]} (exit $c)" >&2
exit $c
}
call() { local rc; set -x; "$@"; rc=$?; { set +x; } 2>/dev/null; return $rc; }
call "$opt_rhapsodycl" -f $rclfile || die $? 'Rhapsody license server not reachable'
+ path/to/RhapsodyCL.exe -f configuration.rcl
+ rc=127
Rhapsody license server not reachable at ./Build:main line 167 (exit 127)
或者在成功的情况下,脚本会继续执行。通过这两个函数(call
和 die
),我们可以编写非常紧凑且易读的单行代码,并且还能产生良好的跟踪输出。
rc=$?
放在 { set +x; }
的内部,它也会被静音:call() { local rc; set -x; "$@"; { rc=$?; set +x; } 2>/dev/null; return $rc; }
- undefinedsome_script.sh
#!/usr/bin/env bash
set -x
...
: This shows a directory listing
ls
...
示例输出
+ : This shows a directory listing
+ ls
test.sh
script.sh 2>&1 | grep -v 'set +x'
? - cdarke