bash 将 STDOUT & STDERR 写入日志文件,同时将 STDERR 写入屏幕
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2871233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write STDOUT & STDERR to a logfile, also write STDERR to screen
提问by Stefan Lasiewski
I would like to run several commands, and capture all output to a logfile. I also want to print any errors to the screen (or optionally mail the output to someone).
我想运行几个命令,并将所有输出捕获到日志文件中。我还想将任何错误打印到屏幕上(或者可以选择将输出邮寄给某人)。
Here's an example. The following command will run three commands, and will write all output (STDOUT and STDERR) into a single logfile.
这是一个例子。以下命令将运行三个命令,并将所有输出(STDOUT 和 STDERR)写入单个日志文件。
{ command1 && command2 && command3 ; } > logfile.log 2>&1
Here is what I want to do with the output of these commands:
这是我想对这些命令的输出执行的操作:
- STDERR and STDOUT for all commands goes to a logfile, in case I need it later--- I usually won't look in here unless there are problems.
- Print STDERR to the screen (or optionally, pipe to /bin/mail), so that any error stands out and doesn't get ignored.
It would be nice if the return codes were still usable, so that I could do some error handling. Maybe I want to send email if there was an error, like this:
{ command1 && command2 && command3 ; } > logfile.log 2>&1 || mailx -s "There was an error" [email protected]
- 所有命令的 STDERR 和 STDOUT 都进入日志文件,以防我以后需要它——除非有问题,否则我通常不会在这里查看。
- 将 STDERR 打印到屏幕(或可选地,通过管道传输到 /bin/mail),以便任何错误都能突出显示并且不会被忽略。
如果返回代码仍然可用,那就太好了,这样我就可以进行一些错误处理。如果出现错误,也许我想发送电子邮件,如下所示:
{ command1 && command2 && command3 ; } > 日志文件.log 2>&1 || mailx -s “出现错误” [email protected]
The problem I run into is that STDERR loses context during I/O redirection. A '2>&1' will convert STDERR into STDOUT, and therefore I cannot view errors if I do 2> error.log
我遇到的问题是 STDERR 在 I/O 重定向期间丢失了上下文。'2>&1' 会将 STDERR 转换为 STDOUT,因此如果我执行 2> error.log,我将无法查看错误
Here are a couple juicier examples. Let's pretend that I am running some familiar build commands, but I don't want the entire build to stop just because of one error so I use the '--keep-going' flag.
这里有几个更有趣的例子。让我们假设我正在运行一些熟悉的构建命令,但我不希望整个构建仅仅因为一个错误而停止,所以我使用了“--keep-going”标志。
{ ./configure && make --keep-going && make install ; } > build.log 2>&1
Or, here's a simple (And perhaps sloppy) build and deploy script, which will keep going in the event of an error.
或者,这是一个简单的(也许是草率的)构建和部署脚本,它会在出现错误时继续运行。
{ ./configure && make --keep-going && make install && rsync -av --keep-going /foo devhost:/foo} > build-and-deploy.log 2>&1
I think what I want involves some sort of Bash I/O Redirection, but I can't figure this out.
我认为我想要的涉及某种Bash I/O Redirection,但我无法弄清楚。
回答by R Samuel Klatchko
(./doit >> log) 2>&1 | tee -a log
This will take stdout and append it to log file.
这将采用标准输出并将其附加到日志文件中。
The stderr will then get converted to stdout which is piped to tee
which appends it to the log (if you are have Bash 4, you can replace 2>&1 |
with |&
) and sends it to stdout which will either appear on the tty or can be piped to another command.
然后,标准错误将被转换到其被管道输送到标准输出tee
其附加到记录(如果你是有击4,可以替换2>&1 |
使用|&
),并将其发送到将任一出现在TTY或者可以通过管道输送到另一个命令标准输出.
I used append mode for both so that regardless of which order the shell redirection and tee
open the file, you won't blow away the original. That said, it may be possible that stderr/stdout is interleaved in an unexpected way.
我对两者都使用了附加模式,这样无论 shell 重定向和tee
打开文件的顺序如何,都不会破坏原始文件。也就是说,stderr/stdout 可能以一种意想不到的方式交错。
回答by Geoff Reedy
If your system has /dev/fd/* nodes you can do it as:
如果您的系统有 /dev/fd/* 节点,您可以这样做:
( exec 5>logfile.txt ; { command1 && command2 && command3 ;} 2>&1 >&5 | tee /dev/fd/5 )
This opens file descriptor 5 to your logfile. Executes the commands with standard error directed to standard out, standard out directed to fd 5 and pipes stdout (which now contains only stderr) to tee which duplicates the output to fd 5 which is the log file.
这将打开文件描述符 5 到您的日志文件。执行定向到标准输出的标准错误命令,定向到 fd 5 的标准输出和管道 stdout(现在只包含 stderr)到 tee,它将输出复制到 fd 5,即日志文件。
回答by Michael Martinez
Here is how to run one or more commands, capturing the standard output and error, in the order in which they are generated, to a logfile, and displaying only the standard error on any terminal screen you like. Works in bash on linux. Probably works in most other environments. I will use an example to show how it's done.
以下是如何运行一个或多个命令,按照生成顺序将标准输出和错误捕获到日志文件中,并在您喜欢的任何终端屏幕上仅显示标准错误。在 Linux 上的 bash 中工作。可能适用于大多数其他环境。我将使用一个例子来展示它是如何完成的。
Preliminaries:
预赛:
Open two windows (shells, tmux sessions, whatever)
打开两个窗口(shell、tmux 会话等等)
I will demonstrate with some test files, so create the test files:
我将使用一些测试文件进行演示,因此创建测试文件:
touch /tmp/foo /tmp/foo1 /tmp/foo2
in window1:
在窗口 1 中:
mkfifo /tmp/fifo
0</tmp/fifo cat - >/tmp/logfile
Then, in window2:
然后,在窗口 2 中:
(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
Where you replace /dev/pts/2
with whatever tty you want the stderr to display.
/dev/pts/2
用您希望 stderr 显示的任何 tty替换的位置。
The reason for the various successful and unsuccessful commands in the subshell is simply to generate a mingled stream of output and error messages, so that you can verify the correct ordering in the log file. Once you understand how it works, replace the “ls” and “echo” commands with scripts or commands of your choosing.
subshell 中各种成功和不成功的命令的原因只是为了生成混合的输出和错误消息流,以便您可以验证日志文件中的正确排序。一旦你理解了它是如何工作的,用你选择的脚本或命令替换“ls”和“echo”命令。
With this method, the ordering of output and error is preserved, the syntax is simple and clean, and there is only a single reference to the output file. Plus there is flexiblity in putting the extra copy of stderr wherever you want.
使用这种方法,输出和错误的顺序被保留,语法简单干净,并且只有一个对输出文件的引用。此外,您可以灵活地将额外的 stderr 副本放置在您想要的任何位置。
回答by reto
add this at the beginning of your script
将此添加到脚本的开头
#!/bin/bash
set -e
outfile=logfile
exec > >(cat >> $outfile)
exec 2> >(tee -a $outfile >&2)
# write your code here
STDOUT
and STDERR
will be written to $outfile
, only STDERR
will be seen on the console
STDOUT
并且STDERR
将被写入$outfile
,只会STDERR
在控制台上看到
回答by Ether
Try:
尝试:
command 2>&1 | tee output.txt
Additionally, you can direct stdout and stderr to different places:
此外,您可以将 stdout 和 stderr 定向到不同的地方:
command > stdout.txt >& stderr.txt
command > stdout.txt |& program_for_stderr
So some combination of the above should work for you -- e.g. you could save stdout to a file, and stderr to both a file and piping to another program (with tee).
所以上面的一些组合应该对你有用——例如你可以将 stdout 保存到一个文件,并将 stderr 保存到一个文件和管道到另一个程序(使用 tee)。