我想运行几个命令,并将所有输出捕获到日志文件中。我还想将任何错误打印到屏幕上(或者可选地将输出邮寄给某人)。
这是一个例子。以下命令将运行三个命令,并将所有输出(STDOUT和STDERR)写入单个日志文件。
{ command1 && command2 && command3 ; } > logfile.log 2>&1
以下是我想对这些命令的输出做的事情:
如果返回代码仍然可用,那将是很好的,这样我就可以进行一些错误处理。如果出现错误,我想发送电子邮件,例如:
{command1&& command2&& command3; }> logfile.log 2>& 1 || mailx -s“出现错误”stefanl@example.org
我遇到的问题是STDERR在I / O重定向期间丢失了上下文。 '2>& 1'将STDERR转换为STDOUT,因此如果我做2>我无法查看错误。 error.log中
以下是几个多汁的例子。让我假装我正在运行一些熟悉的构建命令,但我不希望整个构建因为一个错误而停止,所以我使用'--keep-going'标志。
{ ./configure && make --keep-going && make install ; } > build.log 2>&1
或者,这是一个简单的(也许是草率的)构建和部署脚本,它会在发生错误时继续运行。
{ ./configure && make --keep-going && make install && rsync -av --keep-going /foo devhost:/foo} > build-and-deploy.log 2>&1
我认为我想要的是某种Bash I/O Redirection,但我无法弄明白。
答案 0 :(得分:16)
(./doit >> log) 2>&1 | tee -a log
这将使用stdout并将其附加到日志文件。
然后stderr将转换为stdout,将其传送到tee
,并将其附加到日志中(如果您有Bash 4,则可以将2>&1 |
替换为|&
)并且将它发送到stdout,它将出现在tty上,或者可以通过管道输送给另一个命令。
我对两者都使用了append模式,这样无论shell重定向和tee
打开文件的顺序如何,你都不会吹掉原文。也就是说,stderr / stdout可能以意想不到的方式交错。
答案 1 :(得分:1)
如果你的系统有/ dev / fd / *节点,你可以这样做:
( exec 5>logfile.txt ; { command1 && command2 && command3 ;} 2>&1 >&5 | tee /dev/fd/5 )
这会打开日志文件的文件描述符5。执行命令,标准错误指向标准输出,标准输出指向fd 5,管道标准输出(现在只包含stderr)到tee,它将输出复制到fd 5,这是日志文件。
答案 2 :(得分:1)
以下是如何运行一个或多个命令,捕获标准输出和错误,按生成顺序,到日志文件,并在任何终端屏幕上仅显示标准错误你喜欢。适用于linux上的bash。可能适用于大多数其他环境。我将用一个例子来说明它是如何完成的。
预赛:
打开两个窗口(shell,tmux会话,等等)
我将演示一些测试文件,因此创建测试文件:
touch /tmp/foo /tmp/foo1 /tmp/foo2
在window1中:
mkfifo /tmp/fifo
0</tmp/fifo cat - >/tmp/logfile
然后,在window2中:
(ls -l /tmp/foo /tmp/nofile /tmp/foo1 /tmp/nofile /tmp/nofile; echo successful test; ls /tmp/nofile1111) 2>&1 1>/tmp/fifo | tee /tmp/fifo 1>/dev/pts/2
将/dev/pts/2
替换为您希望stderr显示的任何tty。
子shell中各种成功和失败命令的原因只是生成混合的输出和错误消息流,以便您可以在日志文件中验证正确的顺序。一旦理解了它的工作原理,用你选择的脚本或命令替换“ls”和“echo”命令。
使用此方法,将保留输出和错误的顺序,语法简单而干净,并且只有一个对输出文件的引用。此外,还可以灵活地将stderr的额外副本放在任何地方。
答案 3 :(得分:0)
尝试:
command 2>&1 | tee output.txt
此外,您可以将stdout和stderr指向不同的地方:
command > stdout.txt >& stderr.txt
command > stdout.txt |& program_for_stderr
所以上面的一些组合应该适合你 - 例如你可以将stdout保存到一个文件中,并将stderr保存到一个文件和管道到另一个程序(使用tee)。
答案 4 :(得分:0)
在脚本开头添加
#!/bin/bash
set -e
outfile=logfile
exec > >(cat >> $outfile)
exec 2> >(tee -a $outfile >&2)
# write your code here
STDOUT
和STDERR
将写入$outfile
,只有STDERR
才能在控制台上看到