当使用heredoc作为shell的输入时,为什么stdin关闭

时间:2016-10-30 06:34:13

标签: shell heredoc

我对此感到有点困惑

$ bash <<EOF
  read -p 'This will not work' input
EOF

,因为

$ cat script
read -p 'This will work fine' input
$ bash script
This will work fine

区别是什么?它似乎是一种标准行为,因为ash的行为方式完全相同。

根据目前为止提供的答案,我怀疑(然后确认)以下工作。我认为这实际上是我一直想做的事情,但<()语法总是存在的。

$ bash <( cat <<EOF
  read -p 'This works' input
EOF
)

4 个答案:

答案 0 :(得分:2)

每个进程不能同时有多个stdin,因此作为bash输入传递的here文档不能包含read -p

使用bash script,正在运行的script是Bash shell的子进程,并且stdinread没有并发,因此它将按预期工作。

答案 1 :(得分:2)

在这两种情况下,read命令都会从执行它的bash进程继承其标准输入。

在第一个示例中,这意味着实际包含 read命令的here文档。根据文档bash已经读取了多少(通常是全部),read没有任何内容可供阅读,因此它以非零退出状态退出。

在第二个示例中,bash不同的文件描述符上打开指定文件。 read仍继承bash进程的标准输入,但这次bash根本没有从中读取,因此read命令可以获得下一个线。这里的标准输入是终端,因此read会阻塞,直到用户输入一行。

答案 2 :(得分:1)

由于read是一个内置的bash,它会从bash继承stdin,如上所述。在第一种情况下,bash将此处的文档作为标准输入(或更专业的文档描述符0),并且read没有任何内容可供阅读。
read仅从stdin(fd0)读取,而在第二种情况下,bash打开另一个文件描述符而不是stdin从script读取脚本,这样做 NOT 与传递给read的标准输入的冲突,以便read可以按预期工作。

你可以试试这个来测试。

$ bash << EOF
ls -l /proc/$$/fd
EOF


$ cat script.sh
ls -l /proc/$$/fd
$ bash script.sh
如果比较样本中的输出,差异很明显。

答案 3 :(得分:0)

最简单的解决方案是将交互式命令写入一个临时文件,然后获取该临时文件:

cat <<'_EOF_' >/tmp/$$.sh
read -p 'This is an interactive command, please enter a string: ' STRING
_EOF_
# Command in temporary file get executed here
source /tmp/$$.sh
echo "STRING= '$STRING'"