112

有谁知道我们是否可以set +x在不打印的情况下用 bash 说:

set -x
command
set +x

痕迹

+ command
+ set +x

但它应该只打印

+ command

Bash 是版本 4.1.10(4)。这让我困扰了一段时间 - 输出中充满了无用set +x的行,使得跟踪工具没有它应该的那么有用。

4

6 回答 6

173

我有同样的问题,我能够找到一个不使用子shell的解决方案:

set -x
command
{ set +x; } 2>/dev/null
于 2013-10-07T13:21:30.140 回答
50

您可以使用子shell。退出子shell后,设置x将丢失:

( set -x ; command )
于 2012-11-02T12:56:29.510 回答
8

最近,当我对此感到恼火时,我破解了一个解决方案:

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
于 2014-07-01T18:32:39.717 回答
8

基于@user108471的简化版本的解决方案怎么样:

shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ set +x; } 2>/dev/null'

trace_on
...stuff...
trace_off
于 2018-07-26T23:11:00.843 回答
2

这是一些想法的组合,可以包含代码块并保留退出状态。

#!/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
于 2020-04-18T20:24:31.860 回答
0

这是另一个。通常您只想跟踪脚本中的特定命令。那为什么不写一个函数呢?

> 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

这是一个真实的例子,它调用 Rhapsody CLI 程序从带有命令行选项的 .rcl 文件生成源代码:

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)

或者在成功的情况下脚本继续。使用这两个函数 (calldie),我们可以编写非常紧凑且可读的单行代码,同时也可以产生很好的跟踪输出。

于 2021-03-23T18:05:08.127 回答