在bash中你可以这样做:
echo test >&1
(重定向到stdout,虽然它已经到了那里)echo test >&2
(重定向到stderr)echo test >&0
(重定向到标准输入)当我做最后一个时,我的终端仍然会像其他两个一样打印test
,但很难知道原因。首先,为什么这个有用呢?其次,重定向到stdin有什么好的用途吗?
答案 0 :(得分:9)
更准确地说,>&0
做的是重复文件描述符0作为文件描述符1.如果程序的stdin只是打开读取,那么当程序尝试写入stdout(文件描述符1)时,它会出错,因为文件描述符1也只能打开阅读。
您可以通过编写一个检查自己的文件描述符的小shell脚本来证明这一点:
10156115.sh:
#!/bin/bash
bash -c 'ls -l /proc/$$/fd' >&0
然后用可识别的stdin,stdout和stderr调用它:
$ 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
通常情况下,所有三个实际上都是开放式读取和写入,因此如果单独使用普通shell,>&0
重定向根本不起作用。
这有什么用途吗?
没有任何常见的用途,但如果您调用脚本重定向stdout
和stderr
,则可以将其用作脏黑客来获取打印到终端的方法,并且无论出于何种原因你都无法改变:
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
但我不建议实际这样做。
答案 1 :(得分:5)
由于历史原因,终端上的标准文件描述符是开放式读/写而不是只读(具体来说,它打开一次,dup()
编辑给其他人。对于想要接受管道输入但同时读取用户输入的程序(来自stdout
,或更常见的stderr
),这偶尔会有用,尽管在这种情况下使用/dev/tty
更可靠。有些系统不仅仅将这个应用于ttys:* BSD双向打开套接字对(“管道”),而一些系统实用程序(我记得ufsdump
就是一个例子)依赖于此。
将重定向到 stdin
(也就是说,仅将其打开以进行写入)通常不会有用,因为大多数程序都希望它可以打开以进行读取(或者有时是读/写,如上所述。)