现在我正在使用exec将stderr重定向到带有
的错误日志exec 2>> ${errorLog}
唯一的缺点是我必须以时间戳开始每次运行,因为exec只是将文本直接推送到日志文件中。有没有办法重定向stderr,但允许我向其附加文本,例如时间戳?
答案 0 :(得分:16)
这非常有趣。我问过一个非常了解bash的人,他这样告诉我:
foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; };
首先,它创建了一个从stdin读取一行原始输入的函数,而对IFS的赋值使它不会忽略空白。读完一行后,它会以前面的相应数据输出。然后你必须告诉bash将stderr重定向到该函数:
exec 2> >(foo)
你写入stderr的所有内容现在都将通过foo函数。请注意,当您在交互式shell中执行此操作时,您将不会再看到提示,因为它已打印到stderr,并且foo中的读取是行缓冲的:)
答案 1 :(得分:1)
你可以简单地使用:
exec 1> >( sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1
这不能完全解决你的提示未显示的问题(它会在短时间后显示,但不会实时显示,因为管道会缓存一些数据......),但会在stdout上显示输出1:1和文件一样。
唯一的问题是,我无法解决,是从一个函数执行此操作,因为这会打开一个子shell,其中exec对主程序无用...
答案 2 :(得分:0)
此示例重定向stdout和stderr而不会丢失原始stdout和stderr。 stdout处理程序中的错误也会记录到stderr处理程序中。文件描述符保存在变量中,并在子进程中关闭。 Bash注意不要发生碰撞。
#! /bin/bash
stamp ()
{
local LINE
while IFS='' read -r LINE; do
echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE"
done
}
exec {STDOUT}>&1
exec {STDERR}>&2
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp)
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp)
for n in $(seq 3); do
echo loop $n >&$STDOUT
echo o$n
echo e$n >&2
done
这需要当前的Bash版本,但多亏Shellshock,现在可以依赖它了。
答案 3 :(得分:-1)
我只是在找同样的小东西。在看到这篇文章之后,我看到了另一种看起来很有希望的方法:http://utcc.utoronto.ca/~cks/space/blog/unix/PipingJustStderr
答案 4 :(得分:-1)
cat q23123 2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file