我想形成一個管道流,將 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