为什么不'>'从gcc重定向错误消息?


Answers:


16

使用编译程序时gcc,会有不同类型的输出:to stdoutstderr。通常,>will将stdout流定向到文件(例如,将a的结果printf("hello world\n");发送到stdout)。但是,stderr继续播放会继续发送到屏幕上,因为它被认为是“需要告知的特殊情况”。

有一种方法可以将stderr重定向到文件-您可以使用以下命令(不是很直观)执行此操作:

gcc new.c &> myFile

&>“ bash速记” 在哪里是“重定向所有内容”。正如@CharlesDuffy指出的那样,符合POSIX的表单是

gcc new.c > myFile 2>&1

这意味着“编译'new.c'并发stdout送到myFile。然后将stderr(2)发送到与stdout&1=“与stdout相同的位置”)相同的位置。

您可以在http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.htmlhttp://mywiki.wooledge.org/BashFAQ/055中找到有关不同重定向的更多详细信息。

顺便说一句,如果您想从程序stderr中将特定的内容发送到,则可以执行以下操作

fprintf(stderr, "hello world - this is urgent.\n");

如果将其包含在程序中,请运行该程序并将“正常”输出发送到文件,该输出仍将出现在控制台上。因此,如果将以上内容编译为可执行文件urgent,则键入

./urgent > /dev/null

在控制台上,您的输出将显示在屏幕上。


2
mywiki.wooledge.org/BashFAQ/055可能是重定向的更好介绍。另外,确实应该引入POSIX兼容格式(>myFile 2>&1)和bash扩展名(&>)。
Charles Duffy 2013年

@CharlesDuffy-都很好。为了完整性,我会将它们包括在我的答案中。
Floris

11

由于>仅重定向标准输出,并且将错误写入stderr,因此您需要使用以下选项之一:

gcc new.c &> temp.txt ## redirect both stdout and stderr using bash or zsh only

...要么...

gcc new.c >temp.txt 2>&1 ## redirect both stdout and stderr in any POSIX shell

&>是重定向既是BASH扩展stdoutstderr到文件; 否则,最简单的方法是先重定向stdout(>temp.txt),然后使stderr(FD 2)成为stdout(FD 1)上已经重定向的文件句柄的副本,如下所示:2>&1


4

正如其他人所说,Linux提供了两种不同的输出流:

stdout或“标准输出”是所有常规输出所在的位置。
              您可以使用文件描述符来引用它1

stderr或“标准错误”是一个单独的流,用于带外信息。
              您可以使用文件描述符来引用它2

为什么会有两个不同的输出流?考虑想象中的命令的管道:

 decrypt $MY_FILE | grep "secret" | sort > secrets.txt

现在,假设decrypt命令失败并生成一条错误消息。如果将消息发送给stdout,它将发送到管道中,除非它带有“秘密”一词,否则您将永远看不到它。因此,您最终将得到一个空的输出文件,不知道出了什么问题。

但是,由于管道仅捕获stdout,因此decrypt命令可以将其错误发送到stderr,并在控制台上显示它们。

您可以重定向stdoutstderr共同或独立:

# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt

您可以将错误重定向到stdout并处理它们,就像它们是正常输出一样:

# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1 

# This may be confusing.  It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by 
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort

您还可以使用“简写”表示法将stdout和stderr 重定向到同一文件:

decrypt $MY_FILE &> output.txt

最后,>操作员将首先截断其输出文件,然后再写入该文件。相反,如果您要将数据追加到现有文件,请使用>>运算符:

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1

1
有两个说法:(1)使用不带引号的参数扩展($FOO)是错误的常见来源,并且在示例中进行演示并不是那么好。(2)使用全大写变量名是环境和内置变量(按惯例大写)与局部变量(按惯例小写)之间命名空间冲突的主要原因。(3)鼓励人们重复使用>>(每次在命令中使用该文件时都会重新打开文件),而不是一次打开文件并使文件描述符保持打开状态以供多个命令使用,这会导致代码效率低下。
查尔斯·达菲

...在最后一点,请比较:exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4
查尔斯·达菲

+1感谢您让我诚实,@ CharlesDuffy。所有的优点。exec为了简化起见,我故意省略了它,尽管在实践中通常是更好的策略。

另外,可以折叠为或(在之前和之后以及之前必须有空格)。command₁ > output_file ; command₂ >> the_same_output_file( command₁ ; command₂ )  > output_file{ command₁ ; command₂ ;  }  > output_file{;}
G-Man说'Resstate Monica''Feb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.