单独重定向和重新组合stderr / stdout而不会丢失排序

时间:2017-08-18 15:57:22

标签: linux bash scripting

我想执行一个命令,并希望重定向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按照创建它们的原始顺序。

2 个答案:

答案 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

因为我们要关闭输出文件名(stdoutstderr),所以这些代码必须是常量才能使上述代码正常工作 - 可以使用任何所需的临时目录。

显然,您实际上不应该这样做。更新您的程序以支持其本机语言可用的任何日志记录基础结构(Java中的Log4j,Python日志记录模块等)以允许它的日志记录将被明确配置。

答案 1 :(得分:1)

这将帮助你完成大部分工作:

your_command 2> >(tee -a logs.log errors.log) 1>>logs.log

但我认为你不能完全保留logs.log文件中输出的顺序。