通常は成功する二次コマンドの出力を抑制して、スクリプトの出力を簡略化したいと思います。
ただし、-q
オンにすると、時々失敗するときに出力が非表示になるため、エラーを理解する方法がありません。さらに、これらのコマンドは出力をstderr
に記録します。
コマンドの出力を抑制する方法はありますか成功した場合のみ?
たとえば(これに限定されませんが)次のようなもの:
mycommand | fingerscrossed
すべてがうまくいけば、fingerscrossed
は出力をキャッチして破棄します。それ以外の場合は、標準出力またはエラー出力(何でも)にエコーします。
### do this bit once at the top of your script
divert=
exec 3<>"${divert:=$(mktmp)}" 4<>/dev/null
rm -- "$divert"; unset divert
### then do this bit as often as needed
command >&3 2>&3
cat <&3 >&"$(((RTN=$?)?2:4))"
これでおそらくうまくいくはずです。各command
の出力を削除された一時ファイルにバッファリングし、その後、戻りステータスがであるかどうかに応じて、出力を/dev/null
またはstderrに吸い上げます。ゼロ。一時ファイルは事前に削除されるため、ファイル記述子の現在のシェルとその子以外のどのプロセスでも読み取ることができません(sneaky /proc/$pid/fd
snoops with適切な権限)、そしてそれ終了時にクリーンアップする必要はありません。
おそらくLinuxシステムではより便利なソリューションです。
divert(){
"$@" >&3 2>&3 ||
eval "cat <&3
return $?"
} 3<<"" 3<>/dev/fd/3
...ほとんどのシェルでは、divert some simple-command with args
のように呼び出すことができることを除いて、他のシェルとほとんど同じように機能します。 "$@"
の高出力コマンドに注意してください。ただし、dash
、yash
、またはパイプを使用してここのドキュメントを実行するその他のシェルの場合-これらのシェルでは、パイプバッファを埋める(linuxesではデフォルトで約128kb)なので、デッドロック。 ksh
、mksh
、bash
、zsh
、またはBourne Shellの場合は心配する必要はありません。これらはすべて基本的に同じです上記でexec
を明示的に指定したもの。
通常、エラーが発生した場合、コマンドはstderr
にメッセージを出力するため、タスクの場合はstdout
を抑制できます。
mycommand > /dev/null
自分を慢性的にする
my_chronic() {
tmp=$(mktemp) || return # this will be the temp file w/ the output
"$@" > "$tmp" 2>&1 # this should run the command, respecting all arguments
ret=$?
[ "$ret" -eq 0 ] || cat "$tmp" # if $? (the return of the last run command) is not zero, cat the temp file
rm -f "$tmp"
return "$ret" # return the exit status of the command
}
私は私のメイクファイルで次のようなことをしています:
if (mycommand) &> mycommand.log; then
echo success
else
c=$?;
echo;echo -e "Bad result from previous command, see mycommand.log for more details";echo;
command_to_run_on_fail
(exit $c)
fi
それを自分の状況に適応させると、次のようなことができます。
if ! (mycommand) &> mycommand.log; then
c=$?;
cat mycommand.log
rm mycommand.log
(exit $c)
fi
したがって、「if」はコマンドを実行し、出力をmycommand.logにパイプします。 stdoutとstdoutを比較する必要がある場合は、パイプコマンド '&>'を '>'に変更する必要がある場合があります。コマンドが失敗した場合は、エラーコードをキャプチャし、mycommand.logの内容を出力して、mycommand.logを削除し、最後に元のエラーコードで戻ります。
(exit $ c)がないと、「rm」コマンドが返したものと一致する終了コードで戻ります。
最後に、1つのライナーが必要な場合は、このようなものが機能します。
mycommand &> mycommand.log || cat mycommand.log; rm mycommand.log