防止终端提示被程序输出覆盖

Bla*_*ori 3 prompt terminal ncurses

假设我在终端中运行这样的命令:

~$ echo 'sleep 2; echo "hello!"' | sh
Run Code Online (Sandbox Code Playgroud)

然后开始输入下一行。两秒钟后,“你好!\n”这个词将被插入到我正在写的任何内容中。我知道有一个解决方法(按上然后下刷新提示),但是在其他没有历史记录的系统上——例如,通过 telnet 使用 MUD——这是不可能的。

有人知道将标准输入与标准输出分开的 ncurses 应用程序或终端模拟器吗?这在 ncurses 中似乎很容易制作,您只需要使用一些聪明的 dup2s,但在我制作之前,我想知道是否有人以前做过。

也欢迎针对主要问题的任何其他解决方案。

Cel*_*ada 5

这并不像听起来那么容易改变。它与终端煮熟与原始模式以及是否启用回声有关。

当终端处于熟模式(默认)时,内核读取输入的所有内容并使用基本的行编辑功能处理它,包括立即回显正常文本,处理擦除和删除单个字符和整个字符的删除字符分别是当前行的,以及其他一些东西。当您按下 Enter 键时,文本行只会出现在终端的输入上。在按下 Enter 键之前的整个过程中,一切都完全在内核内部进行,并且在终端上运行的任何进程都不会收到单个字节,因此前台应用程序甚至不知道用户正在键入任何内容。运行在 tty 上的进程不能抑制这个回声,即使它想要仅仅因为回声会在不合时宜的时间出现(例如与输出混合),因为这样的进程甚至不知道输入正在发生。

您可以将终端设置为原始模式而不是使用 echo 来抑制这种情况(stty raw或使用 termios ),但随后您将完全失去内核的行编辑功能 - 例如,这意味着您无法通过按Ctrl-u并重新开始来纠正拼写错误。更重要的是,使用任何依赖于内核成熟处理的程序(基本上是任何不使用 readline 或 ncurses 的程序)都会遇到很多麻烦,因为您将在这些程序中完全盲目地键入!?哦,还有:没有终端熟处理你失去了内核对中断和暂停的作业控制快捷方式的拦截(默认情况下Ctrl-cCtrl-z分别)。