简体   繁体   English

如何将 output 重定向到文件和标准输出

[英]How to redirect output to a file and stdout

In bash, calling foo would display any output from that command on the stdout.在 bash 中,调用foo将在标准输出上显示来自该命令的任何 output。

Calling foo > output would redirect any output from that command to the file specified (in this case 'output').调用foo > output会将任何 output 从该命令重定向到指定的文件(在本例中为“输出”)。

Is there a way to redirect output to a file and have it display on stdout?有没有办法将 output 重定向到文件显示在标准输出上?

The command you want is named tee :您想要的命令名为tee

foo | tee output.file

For example, if you only care about stdout:例如,如果您只关心标准输出:

ls -a | tee output.file

If you want to include stderr, do:如果要包含 stderr,请执行以下操作:

program [arguments...] 2>&1 | tee outfile

2>&1 redirects channel 2 (stderr/standard error) into channel 1 (stdout/standard output), such that both is written as stdout. 2>&1将通道 2(标准错误/标准错误)重定向到通道 1(标准输出/标准输出),这样两者都被写入为标准输出。 It is also directed to the given output file as of the tee command.tee命令开始,它也被定向到给定的输出文件。

Furthermore, if you want to append to the log file, use tee -a as:此外,如果要附加到日志文件,请使用tee -a作为:

program [arguments...] 2>&1 | tee -a outfile
$ program [arguments...] 2>&1 | tee outfile

2>&1 dumps the stderr and stdout streams. 2>&1转储 stderr 和 stdout 流。 tee outfile takes the stream it gets and writes it to the screen and to the file "outfile". tee outfile获取它获取的流并将其写入屏幕和文件“outfile”。

This is probably what most people are looking for.这可能是大多数人正在寻找的。 The likely situation is some program or script is working hard for a long time and producing a lot of output.可能的情况是某个程序或脚本长时间工作并产生大量输出。 The user wants to check it periodically for progress, but also wants the output written to a file.用户希望定期检查进度,但也希望将输出写入文件。

The problem (especially when mixing stdout and stderr streams) is that there is reliance on the streams being flushed by the program.问题(尤其是在混合 stdout 和 stderr 流时)是依赖于程序刷新的流。 If, for example, all the writes to stdout are not flushed, but all the writes to stderr are flushed, then they'll end up out of chronological order in the output file and on the screen.例如,如果对 stdout 的所有写入都未刷新,但对 stderr 的所有写入都已刷新,则它们将在输出文件和屏幕上按时间顺序结束。

It's also bad if the program only outputs 1 or 2 lines every few minutes to report progress.如果程序每几分钟只输出 1 或 2 行来报告进度,那也很糟糕。 In such a case, if the output was not flushed by the program, the user wouldn't even see any output on the screen for hours, because none of it would get pushed through the pipe for hours.在这种情况下,如果程序没有刷新输出,用户甚至在几个小时内都不会在屏幕上看到任何输出,因为在几个小时内它都不会被推送到管道中。

Update: The program unbuffer , part of the expect package, will solve the buffering problem.更新:程序unbufferexpect包的一部分,将解决缓冲问题。 This will cause stdout and stderr to write to the screen and file immediately and keep them in sync when being combined and redirected to tee .这将导致 stdout 和 stderr 立即写入屏幕和文件,并在组合并重定向到tee时使它们保持同步。 Eg:例如:

$ unbuffer program [arguments...] 2>&1 | tee outfile

Another way that works for me is,另一种对我有用的方法是,

<command> |& tee  <outputFile>

as shown in gnu bash manualgnu bash 手册中所示

Example:例子:

ls |& tee files.txt

If '|&' is used, command1's standard error , in addition to its standard output , is connected to command2's standard input through the pipe;如果使用'|&',除了它的标准输出之外,command1 的标准错误通过管道连接到command2 的标准输入; it is shorthand for 2>&1 |.它是2>&1 | 的简写 This implicit redirection of the standard error to the standard output is performed after any redirections specified by the command.标准错误到标准输出的这种隐式重定向是在命令指定的任何重定向之后执行的。

For more information, refer redirection有关更多信息,请参阅重定向

您可以主要使用Zoredache解决方案,但如果您不想覆盖输出文件,您应该使用 -a 选项编写 tee 如下:

ls -lR / | tee -a output.file

Something to add ...有什么要补充的...

The package unbuffer has support issues with some packages under fedora and redhat unix releases.在 fedora 和 redhat unix 版本下,包 unbuffer 对某些包有支持问题。

Setting aside the troubles抛开烦恼

Following worked for me以下为我工作

bash myscript.sh 2>&1 | tee output.log

Thank you ScDF & matthew your inputs saved me lot of time..谢谢ScDF & matthew你的输入为我节省了很多时间..

使用tail -f output应该可以工作。

You can do that for your entire script by using something like that at the beginning of your script :您可以通过在脚本开头使用类似的内容来为整个脚本执行此操作:

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

This redirect both stderr and stdout outputs to the file called mylogfile and let everything goes to stdout at the same time .这两种重定向标准错误和标准输出输出到文件名为mylogfile 让一切都到stdout在同一时间

It is used some stupid tricks :它使用了一些愚蠢的技巧:

  • use exec without command to setup redirections,使用没有命令的exec来设置重定向,
  • use tee to duplicates outputs,使用tee复制输出,
  • restart the script with the wanted redirections,使用所需的重定向重新启动脚本,
  • use a special first parameter (a simple NUL character specified by the $'string' special bash notation) to specify that the script is restarted (no equivalent parameter may be used by your original work),使用特殊的第一个参数(由$'string'特殊 bash 符号指定的简单NUL字符)来指定重新启动脚本(您的原始作品可能不会使用等效参数),
  • try to preserve the original exit status when restarting the script using the pipefail option.尝试使用pipefail选项重新启动脚本时保留原始退出状态。

Ugly but useful for me in certain situations.丑陋但在某些情况下对我有用。

Bonus answer since this use-case brought me here:奖金答案,因为这个用例把我带到了这里:

In the case where you need to do this as some other user如果您需要以其他用户身份执行此操作

echo "some output" | sudo -u some_user tee /some/path/some_file

Note that the echo will happen as you and the file write will happen as "some_user" what will NOT work is if you were to run the echo as "some_user" and redirect the output with >> "some_file" because the file redirect will happen as you.请注意,回声会发生在你和文件写入会发生的“some_user”不会工作,如果你要运行回声为“some_user”,并与输出重定向>>“SOME_FILE”,因为文件重定向会发生什么像你一样。

Hint: tee also supports append with the -a flag, if you need to replace a line in a file as another user you could execute sed as the desired user.提示:tee 还支持附加 -a 标志,如果您需要以另一个用户身份替换文件中的一行,您可以以所需用户身份执行 sed。

< command > |& tee filename # this will create a file "filename" with command status as a content, If a file already exists it will remove existed content and writes the command status. < command > |& tee filename # 这将创建一个文件“filename”,以命令状态作为内容,如果文件已经存在,它将删除现有内容并写入命令状态。

< command > | tee >> filename < command > | tee >> filename # this will append status to the file but it doesn't print the command status on standard_output (screen). < command > | tee >> filename # 这会将状态附加到文件,但它不会在标准输出(屏幕)上打印命令状态。

I want to print something by using "echo" on screen and append that echoed data to a file我想通过在屏幕上使用“回声”来打印一些东西并将回显的数据附加到文件中

echo "hi there, Have to print this on screen and append to a file" 

In my case I had the Java process with output logs.就我而言,我有带有输出日志的 Java 进程。 The simplest solution to display output logs and redirect them into the file(named logfile here) was:显示输出日志并将它们重定向到文件(此处命名为 logfile)的最简单解决方案是:

my_java_process_run_script.sh |& tee logfile

Result was Java process running with output logs displaying and putting them into the file with name log file结果是 Java 进程运行并显示输出日志并将它们放入名为 log file 的文件中

T恤非常适合这个,但这也可以完成这项工作

ls -lr / > output | cat output

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM