14

在 bash 中,您可以执行以下操作:

  • echo test >&1(重定向到标准输出,虽然它已经在那里了)
  • echo test >&2(重定向到标准错误)
  • echo test >&0(重定向到标准输入)

当我做最后一个时,我的终端仍然test像其他两个一样打印,但很难知道为什么。所以首先,为什么这会起作用?其次,重定向到标准输入有什么好的用途吗?

4

2 回答 2

9

更准确地说,>&0将文件描述符 0 复制为文件描述符 1。如果程序的 stdin 仅打开以供读取,那么当您的程序尝试写入 stdout(文件描述符 1)时,它会得到一个错误,因为文件描述符1也只开放阅读。

您可以通过编写一个检查其自己的文件描述符的小型 shell 脚本来证明这一点:

10156115.sh:

#!/bin/bash
bash -c 'ls -l /proc/$$/fd' >&0

然后用可识别的标准输入、标准输出和标准错误调用它:

$ touch stdin
$ ./10156115.sh < stdin > stdout 2> stderr

结果是您得到以下内容stderr

ls: write error: Bad file descriptor

但是,默认情况下,这三个都是终端:(输出简化)

$ ls -l /proc/$$/fd
lrwx------ 0 -> /dev/pts/14
lrwx------ 1 -> /dev/pts/14
lrwx------ 2 -> /dev/pts/14
lrwx------ 255 -> /dev/pts/14

通常,这三个实际上都是开放式读写的,因此>&0如果在普通 shell 中单独使用重定向,则根本没有效果。


这有什么用途吗?

这没有任何常见用途,但是如果调用您的脚本的人重定向stdoutandstderr并且无论出于何种原因您无法更改它,您可能会将其用作肮脏的黑客来获得一种打印到终端的方法:

if [ ! -t /dev/fd/1 -a ! -t /dev/fd/2 -a -t /dev/fd/0 ]; then
    echo "My message that I really, really want to go to a terminal" >&0
fi

但我不建议实际这样做。

于 2012-04-14T18:37:04.500 回答
6

由于历史原因,终端上的标准文件描述符是打开读/写而不是只读的(具体来说,它打开一次并dup()编辑给其他人)。这对于想要获取管道输入但也从用户(从stdout,或更常见的stderr)读取输入的程序来说有时很有用,尽管/dev/tty在这种情况下使用更可靠。一些系统不仅将它应用于 ttys:*BSD 双向打开套接字对(“管道”),并且一些系统实用程序(我记得ufsdump是一个例子)依赖于此。

重定向 stdin(即,只为写入而打开)通常没有用,因为大多数程序都希望它以读取方式打开(或有时读/写,如上所述)。

于 2012-04-14T18:24:49.943 回答