次のコードスニペットを作成しようとしています。設計目標はスクリプトのすべての出力を記録することであり、ラッパーにしてはいけません。行が少ないほど良いです。
(この段階では)ユーザー入力に興味がなく、ターゲットスクリプトは非対話型で実行されます。
この作品には以下が必要です。
- ログにstdoutを出力し、常にコンソールにエコーされます。
- デバッグが有効になっている場合は、stderrをログに出力してコンソールにエコーします。
- stderrメッセージにはタイムスタンプと他の便利なプレフィックスが必要です。
現在、最新バージョンのbash(4.2+?)でのみテストされています。たとえば、Ubuntuではうまく動作しますが、CentOS6では正しく動作しません。
DEBUG_LOG="${0##*/}.log"
# copy stdout to log always and echo to console
exec > >(tee -a ${DEBUG_LOG})
# copy stderr to log only, unless debugging is enabled
[ $DEBUG_TEST = "true" ] \
&& exec 2> >(tee -a ${DEBUG_LOG} >&2) \
|| exec 2>> ${DEBUG_LOG}
だからこれ...
# Expand escaped characters, wrap at 70 chars on spaces,
# and indent wrapped lines
msg_log() {
echo -e "$(date +%T) ${0##*/}: $1" \
| fold -w70 -s | sed '2~1s/^/ /' >&2;
}
msg_con() {
if [ "${DEBUG_TEST}" = "true" ]; then
msg_log "$1"
else
echo -e "$1" | fold -w70 -s | sed '2~1s/^/ /';
fi
}
echo
たとえば、これらのmsgプロシージャの1つを呼び出すことができますmsg_con "hello world"
。
また、スクリプト出力は、呼び出し時に設定された環境変数(例えば DEBUG_TEST=true myscript
。
一部のシェル(ビジボックスなど)では、execが機能しない可能性があることを読みました。 mkfifoとフォークの組み合わせがありますhttps://stackoverflow.com/a/5200754同様のことをしましたが、必ずしも必要でない限り、フォークを使用しないことをお勧めします。
bashの例を好みます。しかし、shで動作するものや移植性が良い方が良いでしょう。どんなアイデアがありますか?
ベストアンサー1
function startLogging {
exec > >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' | tee -a $logfile)
[ ! -z "$DEBUG" ] && exec 2>&1 || exec 2> >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' >>$logfile)
echo "=== Log started for $$ at $(date +%F-%T) ==="
}
$ logfileを何かに設定する必要があります