Pump 命令輸出作為函數參數

Pump 命令輸出作為函數參數

我的腳本中有這個非常簡單的函數:

# Used for debug tracing.
log()
{
    :
    echo "log: $1"
}

這個想法是能夠在一個地方自訂/關閉日誌記錄。非常粗糙。

現在我希望我的腳本在發布配置中完全不產生輸出。我想到的唯一解決方案,但非常不乾燥:

TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"

為了每一個命令。對此如何改進呢?


編輯:我想收集全部輸出到stdoutstderr並透過 進行引導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設定重定向。

相關內容