bash `stdout` 和 `stderr` 的读取值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43949166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:08:51  来源:igfitidea点击:

Reading value of `stdout` and `stderr`

linuxbashshellsh

提问by stack4rme

I am trying to read value of stdoutand stderrusing the following commands:

我正在尝试读取stdoutstderr使用以下命令的值:

cat /dev/stderr

cat /dev/stdout 

But, the command keeps running.

但是,该命令一直在运行。

回答by Todd A. Jacobs

Use a FIFO Instead

改为使用 FIFO

Technically, /dev/stdoutand /dev/stderrare really file descriptors, not FIFOs or named pipes. On my system, they're actually just symlinks to /dev/fd/1and /dev/fd/2. Those descriptors are typically linked to your TTY or PTY. So, you can't really read from them the way you're trying to do.

从技术上讲,/dev/stdout/dev/stderr实际上是文件描述符,而不是 FIFO 或命名管道。在我的系统上,它们实际上只是指向/dev/fd/1/dev/fd/2 的符号链接。这些描述符通常链接到您的 TTY 或 PTY。因此,您无法真正按照自己的方式阅读它们。

What you probably want is the mkfifoutility. For example, to write to standard error, and then read it from another command or script:

您可能想要的是mkfifo实用程序。例如,写入标准错误,然后从另一个命令或脚本中读取它:

# Create a named pipe.
$ mkfifo error

# See what a named pipe looks like in the filesystem.
$ ls -l error
prw-r--r--  1 user  staff  0 May 13 01:47 error|

# In a subshell: echo to stdout, duplicate stdout to stderr,
# write stderr to the error FIFO. Background to avoid blocking.
# Then read from the FIFO until empty, which ends both tasks.
$ ( echo foo >&2 2> error & ); cat error
foo

As a more verbose but less contorted example, consider this:

作为一个更冗长但不那么扭曲的例子,考虑一下:

$ ruby -e 'STDERR.puts "Some error."' 2> error & cat error
[1] 32458
Some error.
[1]+  Done                    ruby -e 'STDERR.puts "Some error."' 2> error

In this example, Ruby uses standard error to write a string to the errorFIFO we created earlier. The write happens in the background, but blocks until the FIFO is emptied by the catcommand. Once the FIFO is emptied, the background job completes.

在此示例中,Ruby 使用标准错误将字符串写入我们之前创建的错误FIFO。写入发生在后台,但会阻塞直到 FIFO 被cat命令清空。一旦 FIFO 被清空,后台作业就完成了。

The FIFO is just a special type of file, so you can remove it when you're done with rm error.

FIFO 只是一种特殊类型的文件,因此您可以在使用完rm error.

回答by ilkkachu

I don't really know what you mean by reading the value of stderror stdin, but I can tell you why that cat /dev/stderrwould keep running: it's waiting for data to read from the fd.

我真的不知道读取stderror的值是什么意思stdin,但我可以告诉你为什么它cat /dev/stderr会继续运行:它正在等待从 fd 读取数据。

On the systems I can test this on, both output fd's are connected to the terminal just like stdinis, and reading from them works just fine. On Linux, we can view this with:

在我可以测试的系统上,两个输出 fd 都像stdin现在一样连接到终端,并且从它们读取工作得很好。在 Linux 上,我们可以通过以下方式查看:

$ ls -l /proc/self/fd
lrwx------ 1 nobody nogroup 64 May 13 21:47 0 -> /dev/pts/1
lrwx------ 1 nobody nogroup 64 May 13 21:47 1 -> /dev/pts/1
lrwx------ 1 nobody nogroup 64 May 13 21:47 2 -> /dev/pts/1
lr-x------ 1 nobody nogroup 64 May 13 21:47 3 -> /proc/44664/fd

The permission bits at the start of the line show that all of the fd's 0 to 2 are opened for both reading and writing.

该行开头的权限位显示所有 fd 的 0 到 2 都为读取和写入打开了。

Reading from them works in practice, too (input in italics):

阅读它们在实践中也有效(斜体输入):

$ cat /dev/stderr
foo
foo
$ read -u 2 ; echo "reply: $REPLY"
asdf
reply: asdf

Though really, it might be better to just open /dev/ttyand read from there if we want to interact on the terminal even when there are redirections in place. (That's what sshdoes to ask the password, for example.)

虽然实际上,/dev/tty如果我们想在终端上进行交互,即使有重定向,最好从那里打开并阅读。(例如,这就是ssh询问密码的作用。)