Bash
重定向和記錄腳本輸出
我正在嘗試整理以下片段,設計目標是記錄腳本的所有輸出,而不應該是包裝器。線越少越好。
我不關心使用者輸入(在這個階段),目標腳本以非互動方式執行。
片段需要
- 將標準輸出輸出到日誌,並始終回顯到控制台
- 如果啟用了調試,則輸出 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 過程之一,例如msg_con "hello world"
.此外,腳本輸出將通過在呼叫時設置為環境變數(例如
DEBUG_TEST=true myscript
.我已經讀過 exec 可能無法在某些 shell(例如busybox)中工作。在https://stackoverflow.com/a/5200754有一個 mkfifo 和 fork 組合可以做類似的事情,但除非絕對需要,否則我寧願不使用 fork。
請首選 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 設置為
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}
當您手動呼叫腳本並且想要查看輸出時,只需呼叫它而不進行重定向。