Last Modified:

Shellのset +xをxtraceで出さない方法Shell

#! /bin/sh
set -x
command
set +x

の場合に、

$ ./a.sh
+ command
+ set +x

となってset +xが邪魔なのでどうにかしたいという話。

shell - Bash set +x without it being printed - Stack Overflow

によると{ set +x; } 2>/dev/nullで良いそうです。

ただ、そこにあるコメント

This zeroes the exit status. – Garth Kidd Jan 6 at 0:21

の通り、終了ステータスが0set +xを実行した結果)になってしまってはやはり使いものにならない。

解決方法

いつものように$?を一時保存してreturnすればいい。

f()
{
    set -x
    command # xtrace
    { local r=$?; set +x; return $r; } 2>/dev/null
}

逆に元々set -xされていて一時的に無効にしたい場合(例えば簡単なログ関数などでxtraceを出して欲しくない場合)は、

g()
{
    { set +x; } 2>/dev/null
    command # NOT xtrace
    { local r=$?; set -x; return $r; } 2>/dev/null
}

とすればいい。

更にxtraceの設定を元に戻せるようにした最終形は以下の通り。

f()
{
    { local xtrace_=+x; test -o xtrace && xtrace_=-x; set -x; } 2>/dev/null
    command # xtrace
    { local xtrace_r=$?; set $xtrace_; return $xtrace_r; } 2>/dev/null
}

g()
{
    { local xtrace_=+x; test -o xtrace && xtrace_=-x; set +x; } 2>/dev/null
    command # NOT xtrace
    { local xtrace_r=$?; set $xtrace_; return $xtrace_r; } 2>/dev/null
}

ずいぶん冗長だけど。

おまけ:$BASH_XTRACEFD

xtraceの出力先はBASH_XTRACEFDで変更できます。

exec 3<>/tmp/a.xtrace
BASH_XTRACEFD=3

としておくと/tmp/a.xtraceに出力されます。しかしそこには忌まわしきset +xが…。

単純に2>/dev/null${BASH_XTRACEFD:-2}>/dev/nullのようにしてもsyntax errorになってしまう。 これの解決方法は今のところわからず