我想执行一个命令,并希望重定向stderr和stdout,如下所示:
stderr和stdout - >应该只保留订单
,只写入logs.log文件stderr - >应该打印到SCREEN并写入errors.log
到目前为止,我可以将它们重定向到屏幕和文件log.txt,如下所示:
command 2>&1 | tee logs.log
但上述不是我需要的。
再次更清楚地说明结果需要是什么。
执行命令后,我需要在屏幕上只看到stderr的结果,我需要有一个名为errors.log的文件和stderr,我需要另一个名为logs.log的文件,其结果为stdout和stderr按照创建它们的原始顺序。
答案 0 :(得分:3)
在没有一些丑陋的hackery的情况下,在执行单独的重定向时保留完美的顺序甚至在理论上是不可能的。排序只保留在写入(在O_APPEND模式下)直接到同一个文件;一旦你把tee
之类的东西放在一个进程而不是另一个进程中,排序保证就会消失,如果不保留有关以什么顺序调用哪些系统调用的信息就无法检索。
那么,那个hackery会是什么样子?它可能看起来像这样:
# eat our initialization time *before* we start the background process
sudo sysdig-probe-loader
# now, start monitoring syscalls made by children of this shell that write to fd 1 or 2
# ...funnel content into our logs.log file
sudo sysdig -s 32768 -b -p '%evt.buffer' \
"proc.apid=$$ and evt.type=write and (fd.num=1 or fd.num=2)" \
> >(base64 -i -d >logs.log) \
& sysdig_pid=$!
# Run your-program, with stderr going both to console and to errors.log
./your-program >/dev/null 2> >(tee errors.log)
也就是说,这仍然是丑陋的hackery:它只捕获直接写入FD 1和2的写入,并且不跟踪可能发生的任何进一步的重定向。 (这可以通过执行对FIFO的写入,并使用sysdig跟踪对这些FIFO的写入来改进;这种方式fdup()
和类似的操作可以按预期工作;但上面的内容足以证明这个概念。) p>
这里我们演示如何使用它来仅对stderr进行着色,并让stdout单独使用 - 告诉sysdig
生成一个JSON流作为输出,然后迭代它:
exec {colorizer_fd}> >(
jq --unbuffered --arg startColor "$(tput setaf 1)" --arg endColor "$(tput sgr0)" -r '
if .["fd.filename"] == "stdout" then
("STDOUT: " + .["evt.buffer"])
else
("STDERR: " + $startColor + .["evt.buffer"] + $endColor)
end
'
)
sudo sysdig -s 32768 -j -p '%fd.filename %evt.buffer' \
"proc.apid=$$ and evt.type=write and proc.name != jq and (fd.num=1 or fd.num=2)" \
>&$colorizer_fd \
& sysdig_pid=$!
# Run your-program, with stdout and stderr going to two separately-named destinations
./your-program >stdout 2>stderr
因为我们要关闭输出文件名(stdout
和stderr
),所以这些代码必须是常量才能使上述代码正常工作 - 可以使用任何所需的临时目录。
显然,您实际上不应该这样做。更新您的程序以支持其本机语言可用的任何日志记录基础结构(Java中的Log4j,Python日志记录模块等)以允许它的日志记录将被明确配置。
答案 1 :(得分:1)
这将帮助你完成大部分工作:
your_command 2> >(tee -a logs.log errors.log) 1>>logs.log
但我认为你不能完全保留logs.log文件中输出的顺序。