将程序重新附加到 stdin

将程序重新附加到 stdin

假设您想要一个程序来摄取字符串,然后stdin在完成后重新附加。

我知道可以通过以下技巧来做到这一点:

(echo id; cat) | sh

效果很好。它不会关闭,stdin因为它被 所使用cat。但输出很乱。

深入挖掘后我发现它缺少tty.

如果我的理解是正确的,sh在管道中并没有打开tty.

我发现的技巧是使用expect.

只需将其放入文件中:

spawn sh
reattach

然后当cat你重新获得控制权时,执行以下操作:

expect exp.sh

这很好,因为它让我tty可以做我需要的一切:sshtmux等等......

我唯一不明白为什么是我看到我输入的所有内容,回到我的终端。

例子:

(echo whoami; cat) | sh
moon
expect exp.sh
spawn sh
sh-3.2$ whoami
whoami
moon

请注意whoami最后一行登录之前的输出。

有人可以向我解释为什么吗?它显然不是stdoutfrom的属性,cat因为它直接附加到sh- 是的,即使它很愚蠢我尝试了以下操作:(echo id; cat > /dev/null) | sh然后什么也没有发生。

那么不显示从键盘输入的内容是tty/的属性吗?pty

答案1

{ echo 'exec <&3 3<&-; id' | sh -si; } 3<&0

似乎适用于大多数sh实现。我们要求一个交互式 shell -i(否则,某些 shell 会因为 stdin 不是终端设备而禁用它),从 shell 的 stdin 作为管道开始,然后指示exec <&3它将其更改为原始(外部)我们之前用 .stdin 保存在文件描述符 3 上3<&0

我们这样做正在运行id但仍然使用相同的命令线,以便标准输入id也被恢复。这并不重要,因为id它不读取其标准输入,但它将是交互式命令,例如编辑器或 shell。

至于为什么会看到你输入的内容(echo id | cat) | sh。看起来您的实现sh似乎是一个非常旧的版本,bash正在交互模式下运行。您可以看到它发出提示,就像-i使用过一样。

然后它确实实现了自己的行编辑器,但无法禁用 tty 设备自己的行编辑器(因为它的标准输入是管道而不是 tty 设备),因此您可以通过 tty 设备行规则获得您键入的内容的回显,并且一旦您按 Enter 键,cat就会立即看到该行缓冲区的所有内容,包括立即从管道写入的尾随换行符bash,并将bash其输出echo作为其自己的行编辑器的一部分。

我怀疑如果你这样做:

stty -icanon -echo; (echo id; cat) | sh; stty sane

您会得到更好的行为,并且可能能够使用 readline 行编辑功能,因为bash它们会直接接收您输入的每个字符。

有关在用户接管交互式 shell 之前自动运行命令的其他选项,请参阅:

相关内容