私は次のスニペットを整理しようとしています。設計の目標はスクリプトからのすべての出力をログに記録することであり、ラッパーであってはなりません。行が少ないほど良いです。
(この段階では)ユーザー入力は気にしません。ターゲットスクリプトは非対話的に実行されます。
スニペットはする必要があります
現時点では、Ubuntuのように最近のバージョンのbash(4.2+?)でのみテストする次のものがありますが、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"
。
また、スクリプト出力は、呼び出し時に環境変数として設定することでstderrに送られます(例:DEBUG_TEST=true myscript
。
Execがbusyboxなどの一部のシェルでは機能しない可能性があることを読みました。 https://stackoverflow.com/a/5200754 にmkfifoとフォークの組み合わせがあります。これは似たようなことをしますが、どうしても必要な場合を除いて、フォークは使いたくありません。
Bashの例をお勧めしますが、shで動作するもの、またはより移植性の高いものがあればいいでしょう。何か案は?
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を何かに設定する必要があります
tee
コマンドまたはscript
コマンドを使用できます。どちらも非常に便利です。
_exec > filename
_はshで動作するはずであり、実際にはbusybox v1.15.3(2011年11月)で動作します。ただし、プロセス置換>(command)
は、bash拡張機能であるため、移植できません。スクリプトでの使用は避けてください。なぜ_>>
_では不十分なのですか?
_exec 1>>${DEBUG_LOG}
exec 2>>${DEBUG_LOG}
_
別の解決策は、スクリプトの外部でリダイレクトを指定することです。スクリプトがバックグラウンドで(cronやシステムスクリプトなどによって)呼び出される場合は、次のように呼び出す必要があります。
_./my_script 1>>${DEBUG_LOG} 2>>${DEBUG_LOG}
_
スクリプトを手動で呼び出して出力を確認したい場合は、リダイレクトせずに呼び出すだけです。
これらの2つの例は、あなたが述べた目的を実行します
echo -n $(date) >> $DEBUG_LOG
command 2>&1 | tee -a $DEBUG_LOG
または
echo -n $(date) >> $DEBUG_LOG
command >> $DEBUG_LOG 2>&1