从我的理解有关程序IO,还有stdin
,stdout
和stderr
数据流(和返回代码)。stdout
和stderr
是两个数据输出流。因此,如果我使用 bash 重定向来关闭输出流之一,我可以缩小文本发送到的流。正确的?
我正在运行 Ubuntu 18.04.1 LTS,我遇到了 bash 重定向这个奇怪的问题。
让我解释一下这个例子。这是我的命令:
# apt-cache show php5
N: Can't select versions from package 'php5' as it is purely virtual
N: No packages found
# |
该php5
软件包在 Ubuntu 18.04 上不存在,因此apt-cache
显示错误。我假设此文本已发送到stderr
流,因此我尝试关闭该流:
# apt-cache show php5 2>&-
# |
看来这验证了文本是通过 发送的stderr
。到目前为止一切都很好!但是现在作为健全性检查,我尝试关闭stdout
(我现在应该看到错误文本):
# apt-cache show php5 1>&-
# |
什么!?stdout
这次我重定向了,但stderr
也没有出现?
根据互联网,我的文件描述符正确:https : //www.gnu.org/software/bash/manual/html_node/Redirections.html
我无法弄清楚这里会发生什么。
截图证明:
TL;DR:不是bash
,而是apt-cache
在搞乱文件描述符。
apt-cache
正在做一些非常有趣的事情 - 它往往不会写出以N:
用于标准输出的字符开头的行。
考虑一下:
$ apt-cache show nonexistent
N: Unable to locate package nonexistent
E: No packages found
我们看到两行,一行N:
以E:
. N:
行转到标准输出。在您的示例中,您有两N:
行。
# apt-cache show php5
N: Can't select versions from package 'php5' as it is purely virtual
N: No packages found
如果您通过跟踪系统调用,strace -e write -f bash -c 'apt-cache show randomtext >&-'
您将看到写入E:
行发生,但N
行不存在:
[pid 12450] write(2, "E", 1E) = 1
[pid 12450] write(2, ": ", 2: ) = 2
[pid 12450] write(2, "No packages found", 17No packages found) = 17
[pid 12450] write(2, "\n", 1
) = 1
[pid 12450] +++ exited with 100 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12450, si_uid=1000, si_status=100, si_utime=5, si_stime=2} ---
+++ exited with 100 +++
所以apt-cache
足够聪明来检查重定向的标准输出。但是呢stderr
?显然写仍然存在:如果你这样做,strace -e write,openat,dup2 -f bash -c 'apt-cache show randomtext 2>&-
你会看到apt-cache
打开/dev/null
仍然有一些东西存在stderr
:
[pid 12543] openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 2
....
[pid 12543] write(2, "N", 1) = 1
[pid 12543] write(2, ": ", 2) = 2
[pid 12543] write(2, "Unable to locate package randomt"..., 35) = 35
[pid 12543] write(2, "\n", 1) = 1
[pid 12543] write(2, "E", 1) = 1
[pid 12543] write(2, ": ", 2) = 2
[pid 12543] write(2, "No packages found", 17) = 17
[pid 12543] write(2, "\n", 1) = 1
[pid 12543] +++ exited with 100 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12543, si_uid=1000, si_status=100, si_utime=5, si_stime=3} ---
+++ exited with 100 +++
如果您在 bash 中对其他程序执行相同的操作,它会按预期工作:
# stdout closed, stderr not
$ ls -l /proc/self/fd >&-
ls: write error: Bad file descriptor
# stdout open , stderr closed, and it's number is assigned to whatever command is trying to open - in this case /proc/self/fd directory
$ ls -l /proc/self/fd 2>&-
total 0
lrwx------ 1 xie xie 64 Oct 6 11:32 0 -> /dev/pts/1
lrwx------ 1 xie xie 64 Oct 6 11:32 1 -> /dev/pts/1
lr-x------ 1 xie xie 64 Oct 6 11:32 2 -> /proc/12723/fd
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句