
我的腳本中有這個非常簡單的函數:
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
這個想法是能夠在一個地方自訂/關閉日誌記錄。非常粗糙。
現在我希望我的腳本在發布配置中完全不產生輸出。我想到的唯一解決方案,但非常不乾燥:
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
這將影響 shell 本身以及它之後執行的任何命令。有條件地運行該命令以選擇輸出重定向的位置。
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
儘管請注意,使用 shell 循環處理輸出並不是一個好主意,但至少它很慢。看:為什麼使用 shell 循環處理文字被認為是不好的做法?。如果您想要的只是重定向一個文件,或者重定向到/dev/null
,只需使用exec
設定重定向。