对stdin,stdout和stderr感到困惑?

时间:2010-08-02 05:20:24

标签: linux stdout stdin stderr

我对这三个文件的目的感到困惑。如果我的理解是正确的,stdin是程序写入其在进程中运行任务的请求的文件,stdout是内核写入其输出的文件和请求它的进程访问来自的信息,stderr是输入所有例外的文件。在打开这些文件以检查这些文件是否确实发生时,我发现似乎没有任何建议!

我想知道的是这些文件的目的究竟是什么,用非常少的技术术语绝对愚蠢地回答!

11 个答案:

答案 0 :(得分:196)

标准输入 - 这是您的流程从中获取信息的文件句柄

标准输出 - 您的进程会将正常信息写入此文件句柄。

标准错误 - 您的进程会将错误信息写入此文件句柄。

这就像我能做到的那样愚蠢: - )

当然,这主要是按照惯例。如果您愿意,没有什么可以阻止您将错误信息写入标准输出。您甚至可以完全关闭三个文件句柄并打开您自己的I / O文件。

当你的进程开始时,它应该已经打开了这些句柄,它只能读取和/或写入它们。

默认情况下,它们可能已连接到您的终端设备(例如/dev/tty),但shell允许您在这些句柄与特定文件和/或设备之间建立连接(甚至可以连接到其他进程的管道) )在你的过程开始之前(可能的一些操作相当聪明)。

一个例子是:

my_prog <inputfile 2>errorfile | grep XYZ

将:

  • my_prog
  • 创建流程
  • 打开inputfile作为标准输入(文件句柄0)。
  • 打开errorfile作为标准错误(文件句柄2)。
  • grep创建另一个进程。
  • my_prog的标准输出附加到grep的标准输入。

重新评论:

  

当我在/ dev文件夹中打开这些文件时,为什么我永远不会看到正在运行的进程的输出?

这是因为它们不是普通文件。虽然UNIX将所有作为文件系统中的文件提供给某个地方,但这并不是最低级别的。 /dev层次结构中的大多数文件都是字符或块设备,实际上是设备驱动程序。它们没有大小,但它们有一个主设备号和次设备号。

当您打开它们时,您已连接到设备驱动程序而不是物理文件,并且设备驱动程序足够聪明,可以知道应单独处理单独的进程。

Linux /proc文件系统也是如此。这些不是真正的文件,只是严格控制内核信息的网关。

答案 1 :(得分:44)

stdinstdoutstderr是“I / O流”更为正确 比文件。正如您所注意到的,这些实体并不存在于文件系统中。但是 就I / O而言,Unix哲学是“一切都是文件”。在实践中, 这实际上意味着您可以使用相同的库函数和接口(printfscanfreadwriteselect等),无需担心I / O流 连接到键盘,磁盘文件,套接字,管道或其他一些I / O抽象。

大多数程序需要读取输入,写入输出和日志错误,因此stdinstdout, 并为您预定义stderr,方便编程。这只是 约定,并不由操作系统强制执行。

答案 2 :(得分:31)

作为上述答案的补充,以下是关于重定向的总结: Redirections cheatsheet

编辑:这张图不完全正确,但我不确定为什么......

图形说2&gt;&amp; 1具有与&amp;&gt;相同的效果然而

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

答案 3 :(得分:22)

我担心你的理解是完全倒退的。 :)

程序的角度考虑“标准输入”,“标准输出”和“标准错误”,而不是从内核的角度来看。

当程序需要打印输出时,通常会打印到“标准输出”。程序通常使用printf将输出打印到标准输出,该打印仅打印到标准输出。

当程序需要打印错误信息时(不一定是异常,那些是编程语言结构,强加到更高级别),它通常会打印到“标准错误”。它通常使用fprintf来完成,它接受打印时要使用的文件流。文件流可以是为写入而打开的任何文件:标准输出,标准错误或使用fopenfdopen打开的任何其他文件。

当文件需要使用freadfgetsgetchar来读取输入时,会使用

“standard in”。

这些文件中的任何一个都可以从shell中轻松重定向,如下所示:

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

或者,整个辣酱玉米饼馅:

cat < /etc/passwd > /tmp/out 2> /tmp/err

有两个重要的警告:第一,“标准输入”,“标准输出”和“标准错误”只是一种惯例。它们是非常强大的约定,但它只是一个协议,能够运行这样的程序非常好:grep echo /etc/services | awk '{print $2;}' | sort并且每个程序的标准输出都挂钩到管道中下一个程序的标准输入。

其次,我已经给出了使用文件流(FILE *对象)的标准ISO C函数 - 在内核级别,它是文件描述符(int对文件表的引用和readwrite这样的低级操作,它们不能快速缓冲ISO C函数。我想保持简单并使用更简单的功能,但我认为你应该知道其他选择。 :)

答案 4 :(得分:7)

标准输入

通过控制台读取输入(例如键盘输入)。 在C中使用scanf

scanf(<formatstring>,<pointer to storage> ...);

标准输出

生成输出到控制台。 在C中使用printf

printf(<string>, <values to print> ...);

stderr的

向控制台生成“错误”输出。 在C中使用fprintf

fprintf(stderr, <string>, <values to print> ...);

重定向

可以重定向stdin的源。例如,它不是来自键盘输入,而是来自文件(echo < file.txt)或其他程序(ps | grep <userid>)。

stdout,stderr的目标也可以重定向。例如,可以将stdout重定向到文件:ls . > ls-output.txt,在这种情况下,输出将写入文件ls-output.txtStderr can be redirected2>

答案 5 :(得分:4)

我认为人们说stderr只应该用于错误信息是误导性的。

它还应该用于为运行命令的用户提供的信息性消息,而不是用于数据的任何潜在下游消费者(即,如果您运行shell管道链接几个命令,则不需要信息性信息,例如“获取”第42条中的第424项“显示在stdout上,因为它们会使消费者感到困惑,但您可能仍希望用户看到它们。

请参阅this了解历史原因:

  

“所有程序都在标准输出上放置了诊断信息   当输出被重定向到文件时总是会引起麻烦,但是   当输出被发送到毫无戒心的时候变得无法容忍   处理。尽管如此,不愿违反简单的   标准输入标准输出模型,人们容忍这种状态   事务通过v6。此后不久,丹尼斯·里奇切断了戈尔迪安   通过引入标准错误文件来打结。这还不够。   使用管道诊断可以来自几个程序中的任何一个   同时跑步。诊断需要识别自己。“

答案 6 :(得分:3)

使用ps -aux显示当前进程,所有这些进程都列在/ proc / as / proc /(pid)/中,通过调用cat / proc /(pid)/ fd / 0它会打印出在我认为该过程的标准输出。或许,

/ proc /(pid)/ fd / 0 - 标准输出文件
/ proc /(pid)/ fd / 1 - 标准输入文件
/ proc /(pid)/ fd / 2 - 标准错误文件

例如my terminal window

但是对于/ bin / bash只能很好地工作,其他进程通常在0中没有任何内容,但很多都有错误写入2

答案 7 :(得分:2)

stderr不会执行IO缓存缓存,因此如果我们的应用程序需要将关键消息信息(一些错误,异常)打印到控制台或文件使用它,那么使用stdout打印一般日志信息,因为它使用IO Cache缓冲,在将消息写入文件应用程序之前可能会关闭,从而使调试复杂

答案 8 :(得分:2)

有关这些文件的权威信息,请查看手册页,在终端上运行命令。

$ man stdout 

但是为了简单回答,每个文件都用于:

标准输出以流式播放

stdin 用于流输入

stderr 打印错误或日志消息。

每个unix程序都有其中的每个流。

答案 9 :(得分:0)

具有关联缓冲的文件称为流,并声明为指向已定义类型FILE的指针。 fopen()函数为流创建某些描述性数据,并返回指针以指定所有其他事务中的流。通常,有三个开放流,在标头中声明了常量指针,并与标准打开文件相关联。 在程序启动时,预定义了三个流,无需明确打开:标准输入(用于读取常规输入),标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。打开时,标准错误流未完全缓冲;当且仅当可以确定流不参考交互设备时,标准输入和标准输出流是完全缓冲的

https://www.mkssoftware.com/docs/man5/stdio.5.asp

答案 10 :(得分:0)

以下是一篇关于stdinstdoutstderr的文章:

总结:

流的处理方式类似于文件

Linux中的流(几乎与其他所有流一样)被视为 他们是文件。您可以从文件中读取文本,也可以编写文本 到文件中。这两个动作都涉及数据流。所以 将数据流作为文件处理的概念并不是很多 伸展。

与进程关联的每个文件都分配有唯一的编号,以 识别它。这称为文件描述符。每当行动 需要在文件上执行,文件描述符用于 识别文件。

这些值始终用于stdin,stdout和stderr:

0: stdin
1: stdout
2: stderr

具有讽刺意味的是,我在堆栈溢出和上面的文章中发现了这个问题,因为我正在搜索有关异常/非标准流的信息。所以我的搜索继续。