8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

对 stdin、stdout 和 stderr 感到困惑?

Norman Smith 1月前

36 0

我对这三个文件的用途感到很困惑。如果我的理解正确的话,stdin 是程序写入其在进程中运行任务的请求的文件,stdout 是...

我对这三个文件的用途感到困惑。如果我的理解正确,它们 stdin 是程序写入其在进程中运行任务的请求的文件、 stdout 内核写入其输出以及请求它的进程从中访问信息的文件、以及 stderr 所有异常都输入到的文件。打开这些文件以检查这些是否确实发生,我发现似乎没有任何迹象表明如此!

我想知道的是这些文件到底有什么用途,用很少的技术术语来给出绝对简化的答案!

帖子版权声明 1、本帖标题:对 stdin、stdout 和 stderr 感到困惑?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Norman Smith在本站《symfony》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 具有相关缓冲的文件称为流,并被声明为指向已定义类型 FILE 的指针。fopen() 函数为流创建某些描述性数据,并返回一个指针以在所有进一步的事务中指定该流。通常有三个打开的​​流,其常量指针在标头中声明并与标准打开文件相关联。在程序启动时,有三个流是预定义的,不需要明确打开:标准输入(用于读取常规输入)、标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。打开时,标准错误流未完全缓冲;当且仅当可以确定流不引用交互式设备时,标准输入和标准输出流才会完全缓冲

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

  • 和 的 stdin , stdout 长篇文章 stderr

    • Linux 上的 stdin、stdout 和 stderr 是什么?

    总结一下:

    像文件一样处理流

    Linux 中的流(与几乎所有其他东西一样)被视为文件。您可以从文件中读取文本,也可以将文本写入文件。这两种操作都涉及数据流。因此,将数据流作为文件处理的概念并不那么夸张。

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

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

    0: stdin
    1: stdout
    2: stderr
    

    讽刺的是,我在搜索有关异常/非标准流的信息时,在 stack overflow 和上述文章中发现了这个问题。所以我的搜索继续。

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

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

    $ man stdout 
    

    但简单来说,每个文件用于:

    stdout 用于流输出

    stdin 用于流输入

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

    每个unix程序都有这样的流。

  • 使用 ps -aux 可以显示当前进程,所有这些进程都列在 /proc/ 中作为 /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 中写入了错误

  • 只是提到 echo < file.txt 不起作用,如上所述,echo 接受字符串作为参数,不读取 stdin

  • 标准输入

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

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

    标准输出

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

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

    标准错误

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

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

    重定向

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

    stdout、stderr 的目标也可以重定向。例如,stdout 可以重定向到文件: ls . > ls-output.txt ,在这种情况下,输出将写入文件。stderr ls-output.txt . 使用以下方式 重定向 2> .

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

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

    请参阅 此内容 以了解历史原因:

    \'所有程序都将诊断信息放在标准输出上。当输出重定向到文件时,这总是会造成麻烦,但当输出发送到毫无防备的进程时,这种情况就变得无法容忍了。尽管如此,人们不愿意破坏标准输入标准输出模型的简单性,所以在 v6 中容忍了这种情况。此后不久,丹尼斯·里奇 (Dennis Ritchie) 通过引入标准错误文件解决了这一难题。但这还不够。有了管道,诊断信息可以来自同时运行的多个程序中的任何一个。诊断信息需要自我识别。\'

  • @Shouvik,编译器只是另一个程序,有自己的 stdin、stdout 和 stderr。当编译器需要写入警告或错误时,它会将它们写入 stderr。当编译器前端为汇编程序输出中间代码时,它可能会将中间代码写入 stdout,而汇编程序可能会在 stdin 上接受其输入,但从用户的角度来看,所有这些都是在幕后进行的。)一旦您有一个编译好的程序,该程序也可以将错误写入其标准错误,但这与编译无关。

  • 那么,是在执行进程时将错误写入此 stderr 文件,还是在从源代码编译程序时将错误写入此 stderr 文件。此外,当我们从编译器的角度谈论这些文件时,它与与程序进行比较时有什么不同吗?

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

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

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

    当程序需要打印错误信息(不一定是异常,异常是编程语言构造,强加在更高级别)时,它通常会打印到“标准错误”。它通常使用 来执行此操作 fprintf fopen 打开的任何其他文件 fdopen .

    当文件需要读取输入时,使用 \'standard in\',使用 fread fgets 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 对文件表的引用)和许多低级操作(如 read 和) write ,它们不能像 ISO C 函数那样进行愉快的缓冲。我想保持简单并使用更简单的函数,但我认为您应该知道替代方案。:)

  • 实际上,第一个是完全错误的。\'hello\' 绝对不会与 echo 的标准输入交互。事实上,如果您用读取标准输入的程序替换 echo,它只会坐在那里等待您的终端输入。在这种情况下,hello 作为参数提供(通过 argc/argv)。如果您看到的效果如下所述,那么关于 2>&1 和 &> 具有相同效果的评论是正确的:“将 stderr 与 stdout 合并”。它们都这样做,但方式略有不同。等效项将是 > somefile 2>&1 和 &> somefile。

  • &> 需要文件来重定向,但 2>&1 不需要 &> 用于日志记录,但 2>&1 可同时用于日志记录和终端 STDOUT STDERR 视图 2>&1 仅可用于查看程序的 STDOUT 和 STDERR(在终端的命令提示符中)(取决于程序处理错误的能力)

  • 作为以上答案的补充,这里是关于重定向的总结:

    编辑:该图并不完全正确。

    第一个例子根本不使用 stdin,它将 \'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

  • 流术语是正确的,而不是文件,它符合 - en.wikipedia.org/wiki/Standard_streams

  • 引用 17

    @Shouvik 你可以使用 \'pipe\' 来实现这一点。如果我们以程序 echo 为例:echo 'foo' > target.txt。通常 echo 会将其输出发送到 stdout,这里我们将该输出重定向到 target.txt。

  • 引用 18

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

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

  • 请注意,stderr 通常用于诊断消息。实际上,只有正常输出才应写入 stdout。我有时会看到人们将日志拆分为 stdout 和 stderr。这不是预期的使用方式。整个日志应该一起进入 stderr。

  • 引用 20

    @CarlosW.Mercado,文件是数据的物理表现形式。例如,存储在硬盘上的位。文件句柄(通常)是打开文件后用于引用该文件的小标记。

返回
作者最近主题: