man bash
我发现交互式 shell 的定义如下:
交互式 shell 是指不使用非选项参数(除非指定了 -s)和 -c 选项启动的 shell,其标准输入和错误均连接到终端(由 isatty(3) 确定),或使用 -i 选项启动的 shell。如果 bash 是交互式的,则设置 PS1 并且 $- 包含 i,从而允许 shell 脚本或启动文件测试此状态。
因此,交互式 shell 是这样的:
- 没有非选项参数(除非
-s
指定),没有-c
选项并且其标准输入和错误都连接到终端;或者 - 有
-i
选择
我写了下面的例子:
bash << EOF
echo '$-'
EOF
输出结果如下:
himBHs
因此,它看起来像是一个交互式 shell(它有i
)。但是,我不清楚当标准输入不是终端时它如何能够交互... 此类重定向的文档中写了以下内容(here documents
):
这种类型的重定向指示 shell 从当前源读取输入,直到看到仅包含分隔符(没有尾随空格)的行。 然后将读取到该点的所有行用作命令的标准输入(或文件描述符 n,如果指定了 n)。
它表示标准输入是读取到分隔符的所有行(我假设它们随后通过将命令的标准输入重定向到管道或类似的东西传递给命令)。因此,标准输入不是(连接到)终端。
为什么会发生这种情况?为什么在这种情况下 bash 是交互式的?
事实并非如此。
外部交互式 shell 正在扩展
$-
(引号在此上下文中并不特殊 - 比较bash -c "echo '$-'"
)并传递echo 'himBHs'
到内部 shell。您可以通过替换以下内容来验证这bash
一点bash -v
:您可以使用反斜杠字符来引用来防止这种情况
$
或者引用 heredoc 分隔符