
私のスクリプトには、次のような非常に単純な関数があります。
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
アイデアは、ログ記録を 1 か所でカスタマイズ/オフにできるようにすることです。非常に粗雑です。
今、リリース構成ではスクリプトがまったく出力を生成しないようにしたいです。私が考えた唯一の解決策ですが、非常に非DRYです。
TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"
のためにすべてのコマンドこれをどう改善すればいいでしょうか?
編集: 集めたい全てstdout
およびに出力しstderr
、 を経由して送信しますlog()
。その後、log()
すべてを無視するか、ファイルに記録するか、印刷するかなどを選択できます。
答え1
$1
まず、ではなく を使用しているため、この関数は送信されたすべての最初の「単語」のみをログに記録します"$*"
。
第二に、(POSIX の場合よくあることですが)この種のことを実行する方法は無数にあります。私ならおそらく次のような方法を採用するでしょう。
log() {
cat - >> "$logfile"
}
do_stuff | log
ただし、次のこともできます。
(
do_stuff
do_more_stuff
) >> "$logfile"
すべての出力を完全に抑制することに関しては、./thing 1> /dev/null 2> &1
いわゆる「コード内」でロックダウンするのではなく、呼び出し元の環境 (例 ) に残しておくのが通常は最善です。つまり、
squashout="true" # comment this out to stop killing output
if ! [[ "true" = "${squashout-false}" ]]; then
# Redirect stdout and stderr to the null device.
exec 1> /dev/null
exec 2> /dev/null
fi
答え2
出力はまったくありません。スクリプトのstdout
とstderr
を にリダイレクトするだけです/dev/null
。
exec >/dev/null 2>&1
これはシェル自体と、その後に実行されるすべてのコマンドに影響します。条件付きで実行して、出力のリダイレクト先を選択します。
if [ "$output_to_file" = 1 ]; then
exec > "$outputfilename" 2>&1
elif [ "$output_suppress" = 1 ]; then
exec > /dev/null 2>&1
fi
注意:抑制全て出力はおそらく良いアイデアではない。ユーザーはおそらくいくつかのエラーの通知。
出力を関数に渡す必要がある場合 (Bash/ksh/Zsh を実行している場合)、プロセス置換を使用できます。
#!/bin/bash
mangle_output() {
# do something smarter here
while read -r line; do
echo "output: $line";
done;
}
# redirect stdout and stderr to the function
exec > >(mangle_output) 2>&1
echo something that produces output
ただし、シェル ループで出力を処理するのはあまり良いアイデアではないことに注意してください。少なくとも遅いです。参照:シェル ループを使用してテキストを処理するのはなぜ悪い習慣だと考えられるのでしょうか?ファイルを または にリダイレクトするだけの場合は/dev/null
、 を使用してexec
リダイレクトを設定します。