我正在运行如下命令:
parallel --spreadstdin --line-buffered 'some_command 2> `mktemp --tmpdir /tmp/stderr`' | do_something
诀窍是parallel
创建很多进程,它们都会得到一个 stderr 文件,其中大部分是无趣的,因为它们是空的。如何让 shell 仅在实际发生任何标准错误输出时才生成 stderr 文件?
答案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 字符,则可能会出现问题。