首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将STDOUT & STDERR写入日志文件,也将STDERR写入屏幕

将STDOUT & STDERR写入日志文件,也将STDERR写入屏幕
EN

Stack Overflow用户
提问于 2010-05-20 05:30:58
回答 5查看 27.3K关注 0票数 16

我想运行几个命令,并将所有输出捕获到一个日志文件中。我还想将任何错误打印到屏幕上(或者可选地将输出发送给某人)。

下面是一个例子。下面的命令将运行三个命令,并将所有输出(STDOUT和STDERR)写入一个日志文件。

代码语言:javascript
复制
{ command1 && command2 && command3 ; } > logfile.log 2>&1

下面是我想对这些命令的输出所做的事情:

  • 所有命令的STDERR和STDOUT都会转到一个日志文件中,以防我以后需要它--除非出现问题,否则我通常不会在这里查看。
  • 将STDERR打印到屏幕上(或者可选地将管道发送到/bin/mail),这样任何错误都会突出,不会被忽略。
  • 如果返回代码仍然可用,那就太好了,这样我就可以做一些错误处理了。如果有错误的话,也许我想发电子邮件,比如: { command1 & command2 & command3;}> logfile.log 2>&1 \x/ mailx -s“有一个错误”stefanl@example.org

我遇到的问题是STDERR在I/O重定向过程中丢失了上下文。“2>&1”将将STDERR转换为STDOUT,因此,如果执行2> error.log,则无法查看错误

以下是几个更好的例子。让我们假设我正在运行一些熟悉的构建命令,但我不希望整个构建仅仅因为一个错误而停止,所以我使用了“--持续”标志。

代码语言:javascript
复制
{ ./configure && make --keep-going && make install ; } > build.log 2>&1

或者,这里有一个简单的(也可能是草率的)构建和部署脚本,如果出现错误,它将继续运行。

代码语言:javascript
复制
{ ./configure && make --keep-going && make install && rsync -av --keep-going /foo devhost:/foo} > build-and-deploy.log 2>&1

我想我想要的是某种Bash I/O重定向,但我不明白。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-05-20 06:00:50

代码语言:javascript
复制
(./doit >> log) 2>&1 | tee -a log

这将获取stdout并将其附加到日志文件中。

然后,stderr将被转换为stdout,该stdout被管道传输到tee,后者将其附加到日志中(如果您有Bash 4,您可以用|&替换2>&1 | ),并将它发送到stdout,stdout将出现在tty上,或者可以通过管道传输到另一个命令。

我对这两种方式都使用了追加模式,这样无论shell重定向和tee打开文件的顺序如何,您都不会将原始文件吹走。也就是说,stderr/stdout可能以一种意想不到的方式交织在一起。

票数 19
EN

Stack Overflow用户

发布于 2010-05-20 06:26:04

如果您的系统有/dev/fd/*节点,您可以这样做:

代码语言:javascript
复制
( exec 5>logfile.txt ; { command1 && command2 && command3 ;} 2>&1 >&5 | tee /dev/fd/5 )

这将打开日志文件的文件描述符5。执行指向标准输出的标准错误的命令、指向fd 5的标准输出和将输出复制到fd 5(日志文件)的管道stdout (现在只包含stderr)。

票数 2
EN

Stack Overflow用户

发布于 2013-08-01 03:44:17

下面是如何运行一个或多个命令,按照生成它们的顺序将标准输出和错误捕获到日志文件,并在任何您喜欢的终端屏幕上只显示标准错误。在linux上使用bash。可能在大多数其他环境中都能工作。我将用一个例子来说明它是如何完成的。

预告片:

打开两个窗口(shell、tmux会话等)

我将用一些测试文件演示,因此创建测试文件:

代码语言:javascript
复制
touch /tmp/foo /tmp/foo1 /tmp/foo2

在window1中:

代码语言:javascript
复制
mkfifo /tmp/fifo

0</tmp/fifo cat - >/tmp/logfile

然后,在window2中:

代码语言:javascript
复制
(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

在这里,您用任何要显示stderr的tty替换/dev/pts/2

子subshell中的各种成功和不成功命令的原因只是为了生成一个混合的输出流和错误消息流,这样您就可以在日志文件中验证正确的顺序。一旦您了解了它的工作原理,将“ls”和“echo”命令替换为您选择的脚本或命令。

使用该方法,可以保持输出和错误的顺序,语法简单明了,并且只有一个对输出文件的引用。另外,在你想要的任何地方放置额外的stderr副本都是灵活的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2871233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档