我想形成一个管道流,将 stdout 捕获到一个文件,将 stderr 捕获到另一个文件,并将两者都捕获到第三个文件中(因此完整的终端输出也在同一个文件中)
不知怎的像这样:
process ----+-- <stdout> --- + --- stdlog.txt
| |
| }---- <terminal> --- alllog.txt
| |
\-- <stderr> --- +---- errlog.txt
我知道我必须使用 tee,但我搞不懂。你们有解决方案吗?最好使用 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