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

问题描述 投票:3回答:4

我有点困惑

$ 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
)
shell heredoc
4个回答
1
投票

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

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

$ cat script.sh
ls -l /proc/$$/fd
$ bash script.sh
The difference is apparent if you compare the outputs from samples bove.

2
投票

你不能每个进程同时有多个stdin,所以这里作为输入传递给bash的文件不能包含read -p

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


2
投票

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

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

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


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'"
© www.soinside.com 2019 - 2024. All rights reserved.