使用bash进程替换出现文件描述符权限被拒绝?

5

我有一个Bash脚本,想要通过标准输出与用户通信,同时通过文件描述符发送指令给子进程,类似这样:

# ...
# ...

echo "Hello user, behold a cleared gnuplot window"

# pass the string "clear" to gnuplot via file descriptor 3
echo "clear" >&3  

所以我想我可以通过以下方式首先启动子进程来“设置这个”:

#!/bin/bash

# Initiate(?) file descriptor 3, and let it direct to a newly 
# started gnuplot process:
exec >3 >( gnuplot )

但是这会产生一个错误:
/dev/fd/63: Permission denied

这是否符合预期?

我不明白发生了什么。(我做错了什么吗?我的系统可能有特殊的安全设置,禁止我正在尝试的操作吗?(运行Ubuntu Linux 12.10。))

"解决方法" - 下面的方法似乎与我正在尝试的操作等效,并且可以正常工作:

#!/bin/bash

# open fd 3 and direct to where fd 1 directs to, i.e. std-out 
exec 3>&1 

# let fd 1 direct to a newly opened gnuplot process
exec 1> >( gnuplot ) 

# fd 1 now directs to the gnuplot process, and fd 3 directs to std-out.
# I would like it the other way around. So we'll just swap fd 1 and 3 
# (using an extra file descriptor, fd 4, as an intermediary)

exec 4>&1 # let fd 4 direct to wherever fd 1 directs to (the gnuplot process)
exec 1>&3 # let fd 1 direct to std-out 
exec 3>&4 # let fd 3 direct to the gnuplot process
exec 4>&- # close fd 4

或者,作为一行代码:
#!/bin/bash
exec 3>&1 1> >( gnuplot ) 4>&1 1>&3 3>&4 4>&- 

为什么这个版本能正常工作,而初始版本不能呢?非常感谢您的帮助。
$ bash --version
GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu)
[...]
2个回答

1
我遇到了这个问题:

/dev/fd/63: 权限不足

由于使用sudo,使用进程替换导致了这个问题,详情参见此处
所以不要这样做:
$ sudo ruby <(echo "puts 'foo'")
ruby: Bad file descriptor -- /dev/fd/63 (LoadError)

man sudo... “-C(close from)选项允许用户指定一个起始点,该起始点在标准错误(文件描述符三)之上。”那么我应该如何在上下文中使用它? - AXE Labs

1

您有一个错别字,请使用exec 3> >( gnuplot )而不是exec >3 >( gnuplot )

顺便说一下,是的,这是预期的。 exec >3 >( gnuplot )将stdout重定向到名为3的文件,然后尝试将>( gnuplot )(转换为/dev/fd/63)作为程序执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接