将 stderr 重定向到文件,但仅在发生任何 stderr 时才创建?

将 stderr 重定向到文件,但仅在发生任何 stderr 时才创建?

我正在运行如下命令:

parallel --spreadstdin --line-buffered 'some_command 2> `mktemp --tmpdir /tmp/stderr`' | do_something

诀窍是parallel创建很多进程,它们都会得到一个 stderr 文件,其中大部分是无趣的,因为它们是空的。如何让 shell 仅在实际发生任何标准错误输出时才生成 std​​err 文件?

答案1

据我所知,这是不可能的。shell 从右到左读取,因此如果2> error存在,error则会创建一个文件。我认为没有办法解决这个问题。

您也许可以执行一些复杂的技巧,例如使用命名管道并测试其输出,但我真的认为这不值得。相反,我要么inotify按照另一个答案中的说明使用,要么创建 tmp 文件并将它们复制到不同的位置(如果它们包含数据)。

tmp=$(mktemp); command 2> "$tmp"; [ -s "$tmp" ] && cp "$tmp" /path/to/log/files

答案2

并行 --spreadstdin --line-buffered 'some_command 2 \

mktemp --tmpdir /tmp/stderr' | do_something && if [test -s /tmp/stderr];然后;睡眠.1;别的; rm /tmp/stderr

  • 单行测试文件是否存在并且大小是否大于零(如果为 TRUE);如果为 FALSE 则为空。

IT 就是做一些有效的事情。停止计算位和字节,并在启动时创建 inotifywait 触发器来检查日志是否为空,将结果记录到数据表,并在完成时擦除日志;然后编写一个网络界面,当错误日志中出现关键字时,该界面会向您发送电子邮件。

while:
  do
    inotifywait -e create /tmp/* && \
      if [ -s /tmp/stderr ]
        then
        ##put it in a datatable
        ##remove the log
      fi
  done

iNotifyWait 还可以监视内核 F/S 子系统以查看文件是否已更改(如果正在追加)。否则,修改源代码并重新编译,通过修改 try() catch() 或错误报告部分(将错误代码打印到屏幕的部分)来防止产生错误。

答案3

令人惊讶的是答案如此接近关于SO的另一个问题来回答这个问题却没有击中要害。像这样定义一个 shell 函数(或编写一个脚本):

save_err()
{
    # Check that "$1" is set and either complain/abort or generate a default.
    if read -r x
    then
        { printf "%s\n" "$x"; cat; } > "$1"
    fi
}

然后用作:

some_command 2> >( save_err $(mktemp --tmpdir /tmp/stderr) )

注意事项:如果 stderr 输出是单行,这将失败 不以换行符结尾。要解决这个问题,请将函数的内部更改为

    if read -r x
    then
        { printf "%s\n" "$x"; cat; } > "$1"
    elif [ "$x" != "" ]
    then
        printf "%s" "$x" > "$1"
    fi

我使用printf而不是echo防止以破折号开头或包含反斜杠的文本。如果 stderr 输出的第一行包含非 ASCII 字符,则可能会出现问题。

相关内容