为什么在使用 heredoc 作为 shell 的输入时关闭标准输入
Why is stdin closed when using a heredoc as input to shell
我对此有点困惑
$ 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
)
每个进程不能同时有多个 stdin
,因此作为输入传递给 bash
的此处文档不能包含 read -p
.
对于 bash script
,运行 script
是 Bash shell 的子进程,并且没有并发的 stdin
到 read
,所以它将按预期工作。
在这两种情况下,read
命令从执行它的 bash
进程继承其标准输入。
在第一个示例中,这意味着此处文档实际上包含 read
命令。根据 bash
已经阅读了多少文档(通常是全部),read
没有任何内容可供阅读,因此它以非零退出状态退出。
在第二个示例中,bash
在 不同的 文件描述符上打开命名文件。 read
仍然从 bash
进程继承其标准输入,但是这次 bash
根本没有读取它,因此 read
命令获取下一个可用行。这里的标准输入是终端,所以 read
阻塞直到用户输入一行。
由于 read
是一个 bash 内置函数,它从 bash
继承标准输入,如上所述。在第一种情况下,bash
有一个 here 文档作为 stdin(或更专业地说,文件描述符 0)并且没有任何内容可供 read
读取。
read
仅从标准输入 (fd0
) 读取,而在第二种情况下,bash
打开另一个文件描述符而不是标准输入来从 script
读取脚本,这 NOT 与传递给 read
的标准输入冲突,因此 read
可以按预期工作。
你可以试试这个来测试一下。
$ bash << EOF
ls -l /proc/$$/fd
EOF
和
$ cat script.sh
ls -l /proc/$$/fd
$ bash script.sh
如果您比较上述示例的输出,差异就会很明显。
最简单的解决方案是将交互式命令写入临时文件,然后获取临时文件:
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'"
我对此有点困惑
$ 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
)
每个进程不能同时有多个 stdin
,因此作为输入传递给 bash
的此处文档不能包含 read -p
.
对于 bash script
,运行 script
是 Bash shell 的子进程,并且没有并发的 stdin
到 read
,所以它将按预期工作。
在这两种情况下,read
命令从执行它的 bash
进程继承其标准输入。
在第一个示例中,这意味着此处文档实际上包含 read
命令。根据 bash
已经阅读了多少文档(通常是全部),read
没有任何内容可供阅读,因此它以非零退出状态退出。
在第二个示例中,bash
在 不同的 文件描述符上打开命名文件。 read
仍然从 bash
进程继承其标准输入,但是这次 bash
根本没有读取它,因此 read
命令获取下一个可用行。这里的标准输入是终端,所以 read
阻塞直到用户输入一行。
由于 read
是一个 bash 内置函数,它从 bash
继承标准输入,如上所述。在第一种情况下,bash
有一个 here 文档作为 stdin(或更专业地说,文件描述符 0)并且没有任何内容可供 read
读取。
read
仅从标准输入 (fd0
) 读取,而在第二种情况下,bash
打开另一个文件描述符而不是标准输入来从 script
读取脚本,这 NOT 与传递给 read
的标准输入冲突,因此 read
可以按预期工作。
你可以试试这个来测试一下。
$ bash << EOF ls -l /proc/$$/fd EOF
和
$ cat script.sh ls -l /proc/$$/fd $ bash script.sh如果您比较上述示例的输出,差异就会很明显。
最简单的解决方案是将交互式命令写入临时文件,然后获取临时文件:
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'"