相关文章推荐
长情的充电器  ·  Spring在bean ...·  1 年前    · 
想出家的长颈鹿  ·  python - Django ...·  1 年前    · 

对stdin、stdout和stderr感到困惑?

289 人关注

我对这三个文件的目的感到相当困惑。如果我的理解是正确的, stdin 是一个程序写进其请求的文件,以运行进程中的任务。替换代码1】是内核将其输出和请求它的进程访问信息的文件,而 stderr 是将所有异常输入的文件。当我打开这些文件以检查这些是否真的发生时,我发现没有任何东西似乎表明了这一点。

我想知道的是,这些文件的目的究竟是什么,绝对是用很少的技术术语来做的傻瓜式回答!我想知道的是,这些文件究竟是什么?

linux
stdout
stdin
stderr
Shouvik
Shouvik
发布于 2010-08-02
11 个回答
paxdiablo
paxdiablo
发布于 2020-09-17
已采纳
0 人赞同

标准输入 - this is the 文件处理 你的程序会读取这些信息,以获取你的信息。

标准输出 - your process writes conventional output to this 文件处理.

标准误差 - your process writes diagnostic output to this 文件处理.

这已经是我能做到的最简单的了 :-)

Of course, that's mostly by convention. There's nothing stopping you from writing your diagnostic information to standard output if you wish. You can even close the three 文件处理s totally and open your own files for I/O.

当你的进程启动时,它应该已经打开了这些句柄,它可以直接从它们中读取和/或写入。

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

一个例子是。

my_prog <inputfile 2>errorfile | grep XYZ

which will:

  • create a process for my_prog.
  • open inputfile as your standard input (文件处理 0).
  • open errorfile as your standard error (文件处理 2).
  • create another process for grep.
  • attach the standard output of my_prog to the standard input of grep.
  • Re your comment:

    当我在/dev文件夹中打开这些文件时,怎么从来没有看到一个进程运行的输出?

    这是因为它们不是正常的文件。虽然UNIX提出了everything作为文件系统中某处的一个文件,这并不意味着它在最底层也是如此。在/dev层次中的大多数文件是字符或块设备,实际上是一个设备驱动程序。它们没有大小,但它们有一个主要和次要的设备编号。

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

    Linux的/proc文件系统也是如此。那些并不是真正的文件,只是严格控制的通往内核信息的通道。

    这就是你的回答。当我在/dev文件夹中打开这些文件时,为什么我从来没有看到一个进程的输出?假设我在终端上执行top,它是不是应该定期将其结果输出到stdout文件中,因此当它被更新时,我应该能够看到输出的实例被打印到这个文件中。但事实并非如此。那么,这些文件是否不一样(/dev目录下的文件)。
    因为这些在技术上不是文件。它们是设备节点,表示要写到一个特定的设备。UNIX可以 present 一切对你来说都是一个文件的抽象,但这并不意味着在最深层次上是如此。
    @Shouvik,注意 /dev/stdin 是一个指向 /proc/self/fd/0 的符号链接。-- 当前运行的程序所打开的第一个文件描述符。所以, /dev/stdin 所指向的东西会在不同的程序中改变,因为 /proc/self/ 总是指向 "当前运行的程序"。(替换代码0】和它的朋友们被放在那里是为了使setuid shell脚本更安全,并让你把文件名 /dev/stdin 传递给那些只处理文件的程序,但你想更多地进行交互控制。(有一天,这将是一个对你有用的技巧。 :)
    @CarlosW.Mercado,the file 是数据的一种物理表现形式。例如,存储在硬盘上的比特。一个文件 处理 是(通常)一个小标记,一旦你打开了该文件,就用来指代它。
    @Oswin,已将其改为使用ISO标准中的术语(常规和诊断),因为那是确切的来源。
    Jim Lewis
    Jim Lewis
    发布于 2020-09-17
    0 人赞同

    更正确的说法是, stdin stdout stderr 是 "I/O流 "而不是文件。 而不是文件。 正如你所注意到的,这些实体并不存在于文件系统中。 但是 但是,就I/O而言,Unix的哲学是 "一切皆为文件"。在实践中。 这实际上意味着你可以使用相同的库函数和接口( printf 。 替换代码4】、 read write select 等),而不必担心I/O流是否 是连接到一个键盘、一个磁盘文件、一个套接字、一个管道,还是其他一些I/O抽象。

    大多数程序需要读取输入、写入输出和记录错误,因此 stdin stdout 。 和 stderr 是为你预定义的,作为一种编程便利。 这只是 惯例,并不是由操作系统强制执行的。

    谢谢你的意见。你是否知道我如何能拦截一个进程的输出数据流并将其输出到我自己的文件中?
    galeop
    galeop
    发布于 2020-09-17
    0 人赞同

    作为上述答案的补充,这里有一个关于重定向的总结。

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

    第一个例子根本没有使用stdin,它是把 "hello "作为参数传给echo命令。

    The graphic also says 2>&1 has the same effect as &> however

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

    This is because &> requires a file to redirect to, and 2>&1 is simply sending stderr into stdout

    你的评论与已接受的答案相结合,非常有意义,并清楚地解释了事情的真相!谢谢!
    一张图片胜过千言万语 !
    &> requires file to redirect in to, but 2>&1 doesn't &> is for logging, but 2>&1 can be used for logging and terminal STDOUT STDERR view at the same time 2>&1 can be used just to view the STDOUT and STDERR (in the terminal's command_prompt) of your program (depending on your program's ability to handle errors)
    实际上,第一个问题是完全错误的。hello "与 echo 的标准输入没有任何互动。事实上,如果你把 echo 换成一个程序,那么 阅读 标准输入,它将只是坐在那里等待你的终端输入。在这种情况下, hello 被作为一个参数提供(通过 argc/argv )。关于 2>&1 &> 具有相同效果的评论是准确的,如果你看到的效果是这样的。"将stderr与stdout合并"。它们都是这样做的,但方式略有不同。相等的是 > somefile 2>&1 &> somefile
    你最好把图形改写成文字,这样你就可以很容易地删除第一个图形 :-)
    sarnold
    sarnold
    发布于 2020-09-17
    0 人赞同

    恐怕你的理解是完全错误的。 :)

    想想 "标准输入"、"标准输出 "和 "标准误差",从 方案的 perspective, not from the kernel's perspective.

    当一个程序需要打印输出时,它通常打印到 "标准输出"。一个程序通常用 printf 打印输出到标准输出,它只打印到标准输出。

    当一个程序需要打印错误信息时(不一定是异常,那是一种编程语言结构,在更高的层次上强加的),它通常打印到 "标准错误"。它通常用 fprintf 来做,它接受一个文件流,在打印时使用。该文件流可以是任何为写作而打开的文件:标准输出,标准错误,或任何其他已经用 fopen fdopen 打开的文件。

    "standard in "用于文件需要读取输入时,使用 fread fgets ,或 getchar

    这些文件中的任何一个都可以很容易地 redirected from the shell, like this:

    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
    

    或者说,是整个的 "大餐"(enchilada)。

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

    有两个重要的注意点。首先,"标准输入"、"标准输出 "和 "标准误差 "只是一个惯例。它们是一种very strong惯例,但这一切只是一个协议,即能够像这样运行程序是非常好的。替换代码9】,并将每个程序的标准输出与管道中的下一个程序的标准输入相连接。

    第二,我给出了用于处理文件流(FILE *对象)的标准ISO C函数--在内核级别。它是所有文件描述符(int对文件表的引用)和更低级的操作,如readwrite,它们不做ISO C函数的快乐缓冲区。我想保持简单,使用更容易的函数,但我认为你应该知道这些替代方法。)

    那么,是在进程执行时将错误写入stderr文件,还是在程序从源头编译时写入。另外,当我们从编译器的角度谈论这些文件时,它与比方说一个程序的时候是否不同?
    @Shouvik,编译器只是另一个程序,有自己的stdin、stdout和stderr。当编译器需要写警告或错误时,它将把它们写到stderr。当编译器前端为汇编器输出中间代码时,它可能在stdout上写中间代码,而汇编器可能在stdin上接受它的输入,但从你作为用户的角度来看,所有这些都是在幕后进行的)。一旦你有了一个编译的程序,这个程序也可以把错误写到它的标准错误上,但这与被编译没有关系。
    谢谢你提供的这一信息。我想我不从这个角度看问题是非常愚蠢的... :P
    所以你是说,标准帮助我们打印程序
    dee
    dee
    发布于 2020-09-17
    0 人赞同

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

    它也应该用于信息性的信息,这些信息是为运行命令的用户准备的,而不是为数据的任何潜在的下游消费者准备的(例如,如果你运行一个shell管道,将几个命令串联起来,你不希望像 "获取42424的第30项 "这样的信息出现在 stdout 上,因为它们会混淆消费者,但你可能仍然希望用户能看到它们。

    See this 为历史的合理性。

    "所有程序都将诊断程序放在标准输出上。这在输出被重定向到一个文件时 当输出被重定向到一个文件中时,总是引起麻烦,但当输出被发送到一个不知情的人那里时,就变得难以忍受了。 但当输出被发送到毫无戒心的程序时,就变得难以忍受了。 进程时,就变得难以忍受了。尽管如此,我们还是不愿意违背 "标准输入-标准输出 "的简单性。 标准输入-标准输出模型的简单性,人们容忍了这种状态。 事务,直到v6。此后不久,丹尼斯-里奇通过引入标准误差 结,引入了标准误差文件。这还远远不够。 有了管道,诊断可以来自几个程序中的任何一个 同时运行。诊断需要识别自己"。

    历史上的合理性链接已经断裂--域名已经消失了!
    dee
    替换为archive.org链接。
    mikek3332002
    mikek3332002
    发布于 2020-09-17
    0 人赞同

    stdin

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

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

    stdout

    Produces output to the console. Used in C with printf

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

    stderr

    Produces 'error' output to the console. Used in C with fprintf

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

    Redirection

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

    stdout, stderr的目的地也可以被重定向。 例如,stdout可以被重定向到一个文件。ls . > ls-output.txt,在这种情况下,输出被写到文件ls-output.txtStderr可以被重定向 with 2>.

    Sam
    Sam
    发布于 2020-09-17
    0 人赞同

    使用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中写有错误。

    Margach Chris
    Margach Chris
    发布于 2020-09-17
    0 人赞同

    关于这些文件的权威信息,请查看man pages,在你的终端运行命令。

    $ man stdout 
    

    但对于一个简单的答案,每个文件都是为了。

    stdout为流出来的

    stdin用于流式输入

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

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

    geekanil
    geekanil
    发布于 2020-09-17
    0 人赞同

    stderr不会进行IO Cache缓冲,所以如果我们的应用程序需要将关键信息(一些错误、异常)打印到控制台或文件中,就使用它,而使用stdout打印一般的日志信息,因为它使用IO Cache缓冲,有可能在将我们的信息写入文件之前,应用程序就已经关闭了,留下复杂的调试。

    Bahruz Balabayov
    Bahruz Balabayov
    发布于 2020-09-17
    0 人赞同

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

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

    WinEunuuchs2Unix
    WinEunuuchs2Unix
    发布于 2020-09-17
    0 人赞同

    这里有一篇关于 stdin stdout stderr 的长文。

  • What Are stdin, stdout, and stderr on Linux?
  • 总结一下。

    流像文件一样被处理

    Linux中的数据流和其他几乎所有的东西一样,都被当作是 它们是文件。你可以从文件中读取文本,你也可以将文本 写入一个文件。这两个动作都涉及到一个数据流。所以 将数据流作为文件来处理的概念并不是那么夸张。

    每一个与进程相关的文件都被分配了一个唯一的号码来识别它。 识别它。这就是所谓的文件描述符。每当有一个动作 需要对一个文件进行操作时,文件描述符被用来 识别该文件。

    这些值总是用于stdin、stdout和stderr。

    0: stdin