275

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

我想知道的是这些文件的确切目的是什么,用很少的技术术语绝对愚蠢的回答!

4

11 回答 11

294

标准输入- 这是您的进程为从您那里获取信息而读取的文件句柄。

标准输出- 您的进程将常规输出写入此文件句柄。

标准错误- 您的进程将诊断输出写入此文件句柄。

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

当然,这主要是按照惯例。如果您愿意,没有什么能阻止您将诊断信息写入标准输出。您甚至可以完全关闭三个文件句柄并打开您自己的文件进行 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是字符设备或块设备,实际上是设备驱动程序。它们没有大小,但有主要和次要设备号。

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

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

于 2010-08-02T05:34:08.517 回答
74

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

大多数程序都需要读取输入、写入输出和记录错误,因此为了方便编程stdin,为您预定义了 、stdout和。stderr这只是一个约定,操作系统不强制执行。

于 2010-08-02T05:36:59.550 回答
67

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

编辑:这个图形并不完全正确。

第一个示例根本不使用标准输入,它将“hello”作为参数传递给 echo 命令。

该图还显示 2>&1 与 &> 具有相同的效果,但是

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

这是因为 &> 需要重定向到一个文件,而 2>&1 只是将 stderr 发送到 stdout

于 2018-04-09T14:25:41.023 回答
27

恐怕你的理解完全倒退了。:)

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

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

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

当文件需要读取输入时使用“标准输入”,使用freador fgets, or getchar

这些文件中的任何一个都可以轻松地从 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对文件表的引用)和更低级别的操作,例如readandwrite对 ISO C 函数进行愉快的缓冲。我想保持简单并使用更简单的功能,但我认为你应该知道替代方案。:)

于 2010-08-02T05:47:13.357 回答
13

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

它还应该用于为运行命令的用户而不是任何潜在的数据下游消费者提供的信息性消息(即,如果您运行一个链接多个命令的 shell 管道,您不想要信息性消息,例如“获取项目 30 42424" 出现,stdout因为它们会使消费者感到困惑,但您可能仍希望用户看到它们。

有关历史原因,请参阅此:

“所有程序都在标准输出上放置诊断。当输出被重定向到一个文件时,这总是会造成麻烦,但当输出被发送到一个毫无戒心的进程时,就变得无法容忍了。尽管如此,不愿意违反标准输入的简单性——标准输出模型,人们通过 v6 容忍了这种状态。此后不久,丹尼斯·里奇通过引入标准错误文件打破了困境。这还不够。使用管道,诊断可以来自同时运行的多个程序中的任何一个。需要诊断来识别自己。”

于 2017-01-20T15:14:44.433 回答
12

标准输入

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

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

标准输出

产生输出到控制台。在 C 中与 printf 一起使用

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

标准错误

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

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

重定向

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

stdout、stderr 的目的地也可以被重定向。例如 stdout 可以重定向到 file: ls . > ls-output.txt,在这种情况下输出被写入 file ls-output.txtStderr 可以2>.

于 2010-08-02T05:46:52.987 回答
5

使用 ps -aux 显示当前进程,所有这些都在 /proc/ 中列为 /proc/(pid)/,通过调用 cat /proc/(pid)/fd/0 它打印在标准输出中找到的任何内容我认为的那个过程。所以也许,

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

例如我的终端窗口

但只适用于 /bin/bash 其他进程通常在 0 中没有任何内容,但许多在 2 中写入错误

于 2014-07-27T00:16:04.113 回答
4

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

$ man stdout 

但对于一个简单的答案,每个文件用于:

用于流输出的标准输出

输入的标准输入

stderr用于打印错误或日志消息。

每个 Unix 程序都有这些流中的每一个。

于 2018-07-17T14:58:46.320 回答
2

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

于 2018-02-13T14:02:13.933 回答
0

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

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

于 2017-09-28T13:57:35.093 回答
0

这是一篇关于stdin和的长stdoutstderr

总结一下:

流像文件一样被处理

Linux 中的流——就像几乎所有其他东西一样——被视为文件。您可以从文件中读取文本,也可以将文本写入文件。这两个动作都涉及数据流。因此,将数据流作为文件处理的概念并没有那么牵强。

与进程关联的每个文件都分配有一个唯一编号来标识它。这称为文件描述符。每当需要对文件执行操作时,都会使用文件描述符来标识文件。

这些值始终用于标准输入、标准输出和标准错误:

0: stdin
1: stdout
2: stderr

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

于 2020-09-17T01:31:13.133 回答