我对这三个文件的用途感到相当困惑。如果我的理解是正确的,stdin
是程序写入其在进程中运行任务的请求的文件,stdout
是内核写入其任务的文件。输出和请求它的进程从中访问信息,stderr 是输入所有异常的文件。在打开这些文件以检查这些是否确实发生时,我发现似乎没有任何迹象表明如此!
我想知道的是这些文件的确切用途是什么,完全用很少的技术术语来简单地回答!
I am rather confused with the purpose of these three files. If my understanding is correct, stdin
is the file in which a program writes into its requests to run a task in the process, stdout
is the file into which the kernel writes its output and the process requesting it accesses the information from, and stderr
is the file into which all the exceptions are entered. On opening these files to check whether these actually do occur, I found nothing seem to suggest so!
What I would want to know is what exactly is the purpose of these files, absolutely dumbed down answer with very little tech jargon!
发布评论
评论(11)
标准输入|STDIN - 这是您的进程读取以获取信息的文件句柄。
标准输出|STDOUT - 您的进程将常规输出写入此文件句柄。
标准错误|STDERR - 您的进程将诊断输出写入此文件句柄。
这已经是我所能做到的最简单的了:-)
当然,这主要是按照惯例。如果您愿意,没有什么可以阻止您将诊断信息写入标准输出。您甚至可以完全关闭三个文件句柄并打开您自己的 I/O 文件。
当您的进程启动时,它应该已经打开了这些句柄,并且只能读取和/或写入它们。
默认情况下,它们可能连接到您的终端设备(例如,
/dev/tty
),但 shell 将允许您在这些句柄与特定文件和/或设备(甚至管道)之间建立连接在进程启动之前(某些可能的操作相当聪明)。一个例子是:
它将:
my_prog
创建一个进程。inputfile
作为标准输入(文件句柄 0)。errorfile
作为标准错误(文件句柄 2)。grep
创建另一个进程。my_prog
的标准输出附加到grep
的标准输入。回复您的评论:
这是因为它们不是普通文件。虽然 UNIX 将一切都呈现为文件系统中某处的文件,但这并不意味着在最低级别上也是如此。
/dev
层次结构中的大多数文件都是字符设备或块设备,实际上是设备驱动程序。它们没有尺寸,但有主设备号和次设备号。当您打开它们时,您将连接到设备驱动程序而不是物理文件,并且设备驱动程序足够聪明,知道应该单独处理单独的进程。
Linux
/proc
文件系统也是如此。这些不是真正的文件,只是严格控制的内核信息网关。Standard input|STDIN - this is the file handle that your process reads to get information from you.
Standard output|STDOUT - your process writes conventional output to this file handle.
Standard error|STDERR - your process writes diagnostic output to this file handle.
That's about as dumbed-down as I can make it :-)
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 file handles totally and open your own files for I/O.
When your process starts, it should already have these handles open and it can just read from and/or write to them.
By default, they're probably connected to your terminal device (e.g.,
/dev/tty
) but shells will allow you to set up connections between these handles and specific files and/or devices (or even pipelines to other processes) before your process starts (some of the manipulations possible are rather clever).An example being:
which will:
my_prog
.inputfile
as your standard input (file handle 0).errorfile
as your standard error (file handle 2).grep
.my_prog
to the standard input ofgrep
.Re your comment:
It's because they're not normal files. While UNIX presents everything as a file in a file system somewhere, that doesn't make it so at the lowest levels. Most files in the
/dev
hierarchy are either character or block devices, effectively a device driver. They don't have a size but they do have a major and minor device number.When you open them, you're connected to the device driver rather than a physical file, and the device driver is smart enough to know that separate processes should be handled separately.
The same is true for the Linux
/proc
filesystem. Those aren't real files, just tightly controlled gateways to kernel information.更正确的说法是,
stdin
、stdout
和stderr
是“I/O 流”,而不是比文件。正如您所注意到的,这些实体并不存在于文件系统中。但是
就 I/O 而言,Unix 哲学是“一切皆文件”。在实践中,
这实际上意味着您可以使用相同的库函数和接口(
printf
,scanf
、read
、write
、select
等)而不用担心I/O流是否存在连接到键盘、磁盘文件、套接字、管道或其他一些 I/O 抽象。
大多数程序需要读取输入、写入输出和记录错误,因此
stdin
、stdout
、和
stderr
是为您预定义的,以方便编程。这只是一种约定,并且不是由操作系统强制执行的。
It would be more correct to say that
stdin
,stdout
, andstderr
are "I/O streams" ratherthan files. As you've noticed, these entities do not live in the filesystem. But the
Unix philosophy, as far as I/O is concerned, is "everything is a file". In practice,
that really means that you can use the same library functions and interfaces (
printf
,scanf
,read
,write
,select
, etc.) without worrying about whether the I/O streamis connected to a keyboard, a disk file, a socket, a pipe, or some other I/O abstraction.
Most programs need to read input, write output, and log errors, so
stdin
,stdout
,and
stderr
are predefined for you, as a programming convenience. This is onlya convention, and is not enforced by the operating system.
作为上述答案的补充,以下是有关重定向的总结:
编辑:该图形并不完全正确。
第一个示例根本不使用 stdin,它将“hello”作为参数传递给 echo 命令。
该图还表明 2>&1 与 &> 具有相同的效果。然而
这是因为&>需要重定向到一个文件,2>&1 只是将 stderr 发送到 stdout
As a complement of the answers above, here is a sum up about Redirections:
EDIT: This graphic is not entirely correct.
The first example does not use stdin at all, it's passing "hello" as an argument to the echo command.
The graphic also says 2>&1 has the same effect as &> however
This is because &> requires a file to redirect to, and 2>&1 is simply sending stderr into stdout
恐怕你的理解完全倒退了。 :)
从程序的角度思考“标准输入”、“标准输出”和“标准错误”,而不是从内核的角度。
当程序需要打印输出时,它通常打印到“标准输出”。程序通常使用
printf
将输出打印到标准输出,它仅打印到标准输出。当程序需要打印错误信息(不一定是例外,这些是编程语言构造,在更高级别上强加)时,它通常打印为“标准错误”。它通常使用
fprintf
来实现,它接受打印时使用的文件流。文件流可以是为写入而打开的任何文件:标准输出、标准错误或使用fopen
或fdopen
打开的任何其他文件。当文件需要使用
fread
或fgets
或getchar
读取输入时,使用“standard in”。这些文件中的任何一个都可以轻松地从 shell 重定向,如下所示:
或者,整个 enchilada:
有两个重要的警告:首先,“标准输入”、“标准输出”和“标准错误” “只是一个约定。它们是一个非常强的约定,但这只是一个协议,即能够运行这样的程序是非常好的:
grep echo /etc/services | awk '{print $2;}' | sort
并将每个程序的标准输出连接到管道中下一个程序的标准输入。其次,我给出了用于处理文件流(
FILE *
对象)的标准 ISO C 函数——在内核级别,它是所有文件描述符(int
引用)到文件表)以及低级操作(例如读取和写入),这些操作无法实现 ISO C 函数的良好缓冲。我想保持简单并使用更简单的功能,但我认为您仍然应该知道替代方案。 :)I'm afraid your understanding is completely backwards. :)
Think of "standard in", "standard out", and "standard error" from the program's perspective, not from the kernel's perspective.
When a program needs to print output, it normally prints to "standard out". A program typically prints output to standard out with
printf
, which prints ONLY to standard out.When a program needs to print error information (not necessarily exceptions, those are a programming-language construct, imposed at a much higher level), it normally prints to "standard error". It normally does so with
fprintf
, which accepts a file stream to use when printing. The file stream could be any file opened for writing: standard out, standard error, or any other file that has been opened withfopen
orfdopen
."standard in" is used when the file needs to read input, using
fread
orfgets
, orgetchar
.Any of these files can be easily redirected from the shell, like this:
Or, the whole enchilada:
There are two important caveats: First, "standard in", "standard out", and "standard error" are just a convention. They are a very strong convention, but it's all just an agreement that it is very nice to be able to run programs like this:
grep echo /etc/services | awk '{print $2;}' | sort
and have the standard outputs of each program hooked into the standard input of the next program in the pipeline.Second, I've given the standard ISO C functions for working with file streams (
FILE *
objects) -- at the kernel level, it is all file descriptors (int
references to the file table) and much lower-level operations likeread
andwrite
, which do not do the happy buffering of the ISO C functions. I figured to keep it simple and use the easier functions, but I thought all the same you should know the alternatives. :)我认为人们说
stderr
应该仅用于错误消息是误导性的。它还应该用于为运行命令的用户提供信息性消息,而不是为数据的任何潜在下游消费者提供信息(即,如果您运行链接多个命令的 shell 管道,则您不需要诸如“获取第 30 项”之类的信息性消息。 42424”出现在
stdout
上,因为它们会让消费者感到困惑,但您可能仍然希望用户看到它们。请参阅 此了解历史原理:
I think people saying
stderr
should be used only for error messages is misleading.It should also be used for informative messages that are meant for the user running the command and not for any potential downstream consumers of the data (i.e. if you run a shell pipe chaining several commands you do not want informative messages like "getting item 30 of 42424" to appear on
stdout
as they will confuse the consumer, but you might still want the user to see them.See this for historical rationale:
stdin
通过控制台读取输入(例如键盘输入)。
在 C 中与 scanf
stdout
一起使用生成到控制台的输出。
在 C 中与 printf
stderr
一起使用生成“错误”输出到控制台。
在 C 中与 fprintf 一起使用
重定向
stdin 的源可以被重定向。例如,它可以来自文件 (
echo < file.txt
) 或另一个程序 (ps | grep
),而不是来自键盘输入)。stdout、stderr 的目的地也可以重定向。例如,stdout 可以重定向到文件:
ls 。 > ls-output.txt
,在本例中,输出将写入文件ls-output.txt
。 Stderr 可以使用>2>
。stdin
Reads input through the console (e.g. Keyboard input).
Used in C with scanf
stdout
Produces output to the console.
Used in C with printf
stderr
Produces 'error' output to the console.
Used in C with fprintf
Redirection
The source for stdin can be redirected. For example, instead of coming from keyboard input, it can come from a file (
echo < file.txt
), or another program (ps | grep <userid>
).The destinations for stdout, stderr can also be redirected. For example stdout can be redirected to a file:
ls . > ls-output.txt
, in this case the output is written to the filels-output.txt
. Stderr can be redirected with2>
.使用 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 中写入了错误
Using ps -aux reveals current processes, all of which are listed in /proc/ as /proc/(pid)/, by calling cat /proc/(pid)/fd/0 it prints anything that is found in the standard output of that process I think. So perhaps,
/proc/(pid)/fd/0 - Standard Output File
/proc/(pid)/fd/1 - Standard Input File
/proc/(pid)/fd/2 - Standard Error File
for example
But only worked this well for /bin/bash other processes generally had nothing in 0 but many had errors written in 2
有关这些文件的权威信息,请查看手册页,并在终端上运行命令。
但对于一个简单的答案,每个文件都用于:
stdout 用于流输出
stdin 用于流输入
stderr 用于打印错误或日志消息。
每个 UNIX 程序都有这些流中的每一个。
For authoritative information about these files, check out the man pages, run the command on your terminal.
But for a simple answer, each file is for:
stdout for a stream out
stdin for a stream input
stderr for printing errors or log messages.
Each unix program has each one of those streams.
stderr 不会进行 IO 缓存缓冲,因此如果我们的应用程序需要将关键消息信息(一些错误、异常)打印到控制台或文件,请使用它,就像使用 stdout 打印一般日志信息一样,因为它使用 IO 缓存缓冲,有可能在将消息写入文件之前,应用程序可能会关闭,从而使调试变得复杂
stderr will not do IO Cache buffering so if our application need to print critical message info (some errors ,exceptions) to console or to file use it where as use stdout to print general log info as it use IO Cache buffering there is a chance that before writing our messages to file application may close ,leaving debugging complex
这是一篇关于 stdin 、 stdout 和 stderr 的长文:
总结一下:
具有讽刺意味的是,我在堆栈溢出和上面的文章中发现了这个问题,因为我正在搜索有关异常/非标准流的信息。所以我的搜索仍在继续。
Here is a lengthy article on
stdin
,stdout
andstderr
:To summarize:
Ironically I found this question on stack overflow and the article above because I was searching for information on abnormal / non-standard streams. So my search continues.
具有关联缓冲的文件称为流,并被声明为指向已定义类型 FILE 的指针。 fopen() 函数为流创建某些描述性数据,并返回一个指针以在所有后续事务中指定该流。通常,存在三个打开的流,其常量指针在标头中声明并与标准打开文件关联。
在程序启动时,预定义了三个流,无需显式打开:标准输入(用于读取常规输入)、标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。打开时,标准错误流未完全缓冲;当且仅当可以确定流不引用交互式设备时,标准输入和标准输出流才被完全缓冲
https://www.mkssoftware.com/docs/man5/stdio.5.asp
A file with associated buffering is called a stream and is declared to be a pointer to a defined type FILE. The fopen() function creates certain descriptive data for a stream and returns a pointer to designate the stream in all further transactions. Normally there are three open streams with constant pointers declared in the header and associated with the standard open files.
At program startup three streams are predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). When opened the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device
https://www.mkssoftware.com/docs/man5/stdio.5.asp