Linux shell:將 stderr 和 stdout 透過管道傳輸到一個檔案並同時傳輸到各個檔案(使用 tee?)

Linux shell:將 stderr 和 stdout 透過管道傳輸到一個檔案並同時傳輸到各個檔案(使用 tee?)

我想形成一個管道流,將 stdout 捕獲到一個文件,將 stderr 捕獲到另一個文件,並且兩者都在第三個文件中(因此完整的終端輸出也位於一個文件中)

像這樣:

process ----+-- <stdout> --- + --- stdlog.txt 
            |                |
            |                }---- <terminal> --- alllog.txt
            |                |
            \-- <stderr> --- +---- errlog.txt 

我知道我必須使用 T 卹,但我不明白。你們有解決辦法嗎?首選 Bash/sh...

感謝您的幫助,我真的很感激!

答案1

首先:我不建議您這樣做,在單個文件中添加時間戳和標籤(例如 [INFO] 和 [ERROR])或僅在兩個文件中添加時間戳可能是一個更好、更可靠的想法。 。同時仍然允許您使用 grep 或排序來建立您想要的其他檔案。

對於您的問題:我從來沒有這樣做過,但您可能需要使用命名管道。未經測試的 bash 範例:

# Log one output type
function logger() {
    unique_file="$1"
    common_file="$2"
    # Tee reads from the function's standard input, writes to unique_file, appends to common_file, then outputs what was written
    tee "$unique_file" | tee -a "$common_file"
}

# Call your code's main function to start processing
main > >(logger info_log_file common_log_file) 2> >(logger error_log_file common_log_file >&2)

您可能會想使用exec >"$info_pipe" 2>"$error_pipe".不要這樣做,否則您將產生一個循環,使您的日誌檔案填滿所有可用磁碟空間

請注意,如果您的 bash 不支援隱式命名管道(它應該,但我見過不支援的環境),您可能希望透過呼叫 mkfifo 來明確使用它們,但是,這需要更多管道:

# Log one output type
function logger() {
    unique_file="$1"
    common_file="$2"
    # Tee reads from the function's standard input, writes to unique_file, appends to common_file, then outputs what was written
    tee "$unique_file" | tee -a "$common_file"
}

# Setup logging
function prepare() {
    tmp_pipe_dir="$(mktemp -d)"
    error_pipe="$(mkfifo "$tmp_pipe_dir/error")"
    info_pipe="$(mkfifo "$tmp_pipe_dir/info")"
}

function cleanup() {
    rm -rf "$tmp_pipe_dir"
}

prepare
# Start logging, note that logger won't stop on its own. Removing the pipe files should do the trick
logger info_log_file common_log_file <"$info_pipe" &
logger error_log_file common_log_file <"$error_pipe" >&2 &
# Call your code's main function to start processing
main >"$info_pipe" 2>"$error_pipe"
cleanup

相關內容