我对这三个文件的目的感到困惑。如果我的理解是正确的,stdin
则是程序在其中写入其在进程中运行任务的请求stdout
的文件,是内核在其中写入其输出以及请求其从中访问信息的进程stderr
的文件,并且是该文件。输入所有例外。在打开这些文件以检查它们是否确实发生时,我发现似乎没有任何暗示!
我想知道的是这些文件的目的是什么,用很少的技术术语就完全可以解决问题了!
我对这三个文件的目的感到困惑。如果我的理解是正确的,stdin
则是程序在其中写入其在进程中运行任务的请求stdout
的文件,是内核在其中写入其输出以及请求其从中访问信息的进程stderr
的文件,并且是该文件。输入所有例外。在打开这些文件以检查它们是否确实发生时,我发现似乎没有任何暗示!
我想知道的是这些文件的目的是什么,用很少的技术术语就完全可以解决问题了!
Answers:
标准输入 -这是您的过程读取以获取您的信息文件句柄。
标准输出 -您的进程将正常信息写入此文件句柄。
标准误差 -您的进程将错误信息写入此文件句柄。
这就是我所能做到的愚蠢:-)
当然,这主要是按照惯例。如果您愿意,没有什么可以阻止您将错误信息写入标准输出。您甚至可以完全关闭三个文件句柄,并为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
文件系统也是如此。这些不是真实的文件,只是对内核信息进行严格控制的网关。
xyz >xyz.out
会将您的标准输出写入一个物理文件,其他进程可以读取该文件。xyz | grep something
将xyz
stdout grep
更直接地连接到stdin。如果您希望不受限制地访问过程,那么就需要研究类似的东西/proc
或编写代码以某种方式挂接到内核来过滤输出。可能还有其他解决方案,但它们彼此之间可能同样危险:-)
/dev/stdin
是一个符号链接/proc/self/fd/0
-当前正在运行的程序已打开的第一个文件描述符。因此,所指向的内容/dev/stdin
将在程序之间变化,因为它/proc/self/
始终指向“当前正在运行的程序”。(使用哪个程序进行open
调用。)/dev/stdin
和朋友一起放在那里,以使setuid shell脚本更安全,并允许您将文件名传递/dev/stdin
给仅适用于文件的程序,但您希望以更具交互性的方式进行控制。(总有一天,这将是一个有用的窍门。:)
这将是更正确的说stdin
,stdout
和stderr
有“I / O流”,而不是文件。您已经注意到,这些实体不存在于文件系统中。但是就I / O而言,Unix的哲学是“一切都是文件”。在实践中,确实意味着你可以使用相同的库功能和接口(printf
,
scanf
,read
,write
,select
,等),而不必担心I / O流是否连接到键盘,磁盘文件,插座,管道,或其他一些I / O抽象。
大多数程序需要读取输入,输出写入和错误日志,所以stdin
,stdout
和stderr
预定义的你,作为一个编程方便。这只是一个约定,不能由操作系统强制执行。
编辑:此图形不是完全正确,但我不确定为什么...
图形显示2>&1与&>具有相同的效果
ls Documents ABC > dirlist 2>&1
#does not give the same output as
ls Documents ABC > dirlist &>
恐怕您的理解是完全落后的。:)
从程序的角度而不是从内核的角度考虑“标准输入”,“标准输出”和“标准错误” 。
当程序需要打印输出时,通常会打印为“标准输出”。程序通常使用来将输出打印到标准输出printf
,而仅将输出打印到标准输出。
当程序需要打印错误信息时(不一定是例外,那些例外是一种编程语言结构,要强加于更高的级别),通常会打印为“标准错误”。通常使用来执行此操作fprintf
,它接受打印时要使用的文件流。文件流可以是为写入而打开的任何文件:标准输出,标准错误,或已使用fopen
或打开的任何其他文件fdopen
。
当文件需要使用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函数的缓冲。我想使其保持简单并使用更简单的功能,但我认为您应该知道所有替代方法。:)
通过控制台读取输入(例如键盘输入)。与scanf一起在C中使用
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
,在这种情况下,输出将写入文件ls-output.txt
。 标准错误可以重定向用2>
。
我认为有人说stderr
只应将错误消息用于误导。
它也应该用于提供给运行该命令的用户的信息性消息,而不是给数据的任何潜在下游使用者(例如,如果您运行将多个命令链接在一起的shell管道,则您不希望获得诸如“获取第30条信息”之类的信息性消息)。 42424“出现在屏幕上,stdout
因为它们会使消费者感到困惑,但是您可能仍希望用户看到它们。
见这个历史的理由:
“所有程序都会对标准输出进行诊断。这总是在将输出重定向到文件时引起麻烦,但是在将输出发送到毫无疑问的过程时就变得无法忍受。但是,不愿意违反标准输入的简单性。在标准输出模型中,人们通过v6容忍了这种状况,此后不久,丹尼斯·里奇(Dennis Ritchie)通过引入标准错误文件削减了戈尔迪诺的结,这还不够。来证明自己。”
具有关联缓冲的文件称为流,并声明为指向已定义类型FILE的指针。fopen()函数为流创建某些描述性数据,并返回指针以在所有其他事务中指定该流。通常,在标头中声明了三个带有恒定指针的打开流,这些流与标准打开文件相关联。在程序启动时,预定义了三个流,无需显式打开它们:标准输入(用于读取常规输入),标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。打开时,标准错误流未完全缓冲;当且仅当可以确定该流不引用交互式设备时,标准输入流和标准输出流才被完全缓冲