shell Bash set +x,但不打印

ktca8awb  于 2022-12-13  发布在  Shell
关注(0)|答案(7)|浏览(146)

有没有人知道我们是否可以在bash中说set +x而不打印出来:

set -x
command
set +x

迹线

+ command
+ set +x

但它应该只打印

+ command

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

pn9klfpd

pn9klfpd1#

我也遇到了同样的问题,我找到了一个不使用子shell的解决方案:

set -x
command
{ set +x; } 2>/dev/null
uqdfh47h

uqdfh47h2#

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

( set -x ; command )
zzwlnbp8

zzwlnbp83#

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

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
iq0todco

iq0todco4#

基于@user108471简化版本的解决方案如何:

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

trace_on
...stuff...
trace_off
zdwk9cvp

zdwk9cvp5#

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

#!/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
vecaoik1

vecaoik16#

这是另一个例子。通常你只想在你的脚本中跟踪一个特定的命令。那么为什么不写一个函数来完成这个任务呢?

> 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),我们可以编写非常紧凑和可读的单行程序,同时也可以产生很好的跟踪输出。

bybem2ql

bybem2ql7#

与此问题有些相关的是,如何才能使(逻辑)注解也显示在跟踪的输出中,以便解释脚本的命令正在执行什么高级操作。
如果您不介意最小的开销,我通常的做法是:

一些脚本.sh

#!/usr/bin/env bash
set -x
...
: This shows a directory listing
ls
...

输出示例

+ : This shows a directory listing
+ ls
test.sh

当然,您也可以用单引号或双引号将**:**内置函数的参数括起来,使用双引号(或不使用引号)的好处是,在输出过程中还会发生变量扩展(以及其他副作用)。
然后,可以将此方法用作仅跟踪内联详细消息工具,使您能够在常规跟踪输出中注入其他调试跟踪消息,这些消息在禁用跟踪时不会输出。

相关问题