代码之家  ›  专栏  ›  技术社区  ›  kyb thursdaysDove

如何通过subshell stderr与Bash中主shell的stdout同步着色?[副本]

  •  0
  • kyb thursdaysDove  · 技术社区  · 6 年前

    stderr和stdout->只应写入logs.log文件,同时保持顺序

    stderr->应打印到屏幕上,也应写入errors.log

    到目前为止,我可以将它们重定向到screen和log.txt文件,如下所示:

    command 2>&1 | tee logs.log
    

    再次明确结果的必要性。

    执行命令后,我只需要在屏幕上看到stderr的结果,我需要一个名为errors.log的文件和stderr,我需要另一个名为logs.log的文件和stdout和stderr的结果都是按照创建它们的原始顺序创建的。

    0 回复  |  直到 7 年前
        1
  •  3
  •   Charles Duffy    6 年前

    在执行单独的重定向时保持完美的顺序在理论上甚至不可能没有一些丑陋的黑客。 排序只在直接写入同一个文件时(在O_APPEND模式下)保留;只要您将 tee

    那么,那黑客是什么样子的?可能是这样的:

    # 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)
    

    也就是说,这仍然是丑陋的黑客:它只捕获直接到FDs 1和FDs 2的写操作,而不跟踪任何可能发生的进一步重定向。(这可以通过执行对fifo的写操作,并使用sysdig跟踪对那些fifo的写操作来改进;这样 fdup()


    分开处理 明确的

    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 ),这些值必须是常量,才能使上述代码正常工作——可以使用所需的任何临时目录。


    显然,你不应该真的这么做。

        2
  •  1
  •   glenn jackman    7 年前

    这会让你走到那里:

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