有时我会意外地获取cat
一些二进制数据;有时一些 ncurses 程序崩溃 - 由于很多原因,终端可能会处于不良状态,需要手动操作reset
。这种情况经常发生。
这种糟糕的状态可能是没有回声,或将所有内容转换为中文垃圾,或许多其他情况。
有没有什么简单的方法可以确保当 shell 重新获得控制权时终端(无需硬重置、清洁屏幕等)设置能够恢复?
是的bash
,Terminal.app
但是我猜这个问题几乎是普遍存在的。
答案1
你提到的问题出现在不同的层面上,只有其中一部分可以通过“转义代码”解决。
终端仿真中的备用字符集
有一个常见的终端问题,可能被描述为“(一些)小写字母显示为符号或线条画字符”(参见另一个问题)。这可能与您的“中文乱码”问题无关,但这是我见过的最接近的问题。在将几乎任何 8 位数据流解释为 UTF-16 编码文本时,您也可能会遇到“中文乱码”。通常这不是需要重置的“棘手”问题,因此它可能不是您看到的问题。
“卡在画线字符”问题通常源于向终端仿真器发送了无意的控制序列(或在切换到备用字符集后在重置终端之前停止程序)。当显示某些二进制数据并且字节流包含选择备用字符集的终端控制序列时,可能会发生这种情况。
这在大多数 VT-100 式终端上很容易触发,因为它只需要一个字节(0x0e;参见我对之前链接的 SO 问题的回答)。重置此条件的控制序列也是一个字节(0x0f;通常通过echo ^V^O
(输入为++ echo
Control,或直接输入)生成。 V ControlOprintf '\017'
您可以通过让您的提示包含 0x0f 字节来解决此类问题。 ** 如果您的“中文垃圾”是由于其他问题导致的,那么它可能有不同的解决方案
。
PS1="\[\017\]… "
和\[
在\]
那里告诉狂欢有界字符是不可打印的。这允许狂欢准确了解“物理”光标位置(这对于使用命令行编辑功能时正确重新显示非常重要)。
正如 Ignacio Vazquez-Abrams 指出的那样他的回答,获取所需控制序列的另一种方法是通过输出命令:
tput rmacs
使用此方法,您可以避免修改 PS1,只需将上述命令放入 PROMPT_COMMAND 中:
PROMPT_COMMAND='tput rmacs'
TTY(termios)选项
“无回声”问题***源自基于操作系统的 tty 设备的选项的意外设置,该设备将您的终端仿真器连接到终端窗口内运行的所有程序。这通常是由交互式文本 UI 程序引起的,这些程序有错误、崩溃或被终止,因此它们无法将 tty 恢复到其原始状态。
您可以使用以下方式控制这些设置斯特蒂命令。这种问题无法通过“转义代码”解决,因为 tty 选项是通过软件 API 配置的(请参阅tcsetattr(3)和termios(4))。一般来说,stty sane
这是一个很好的重置机制。
*** 此外还有“无 ^C/^Z/^/”、“阶梯式输出”(收到 LF 时无自动 CR)以及其他一些问题。
重置
这重置命令通常可以帮助解决这两种问题。它将发送终端初始化控制序列,通常可以修复备用字符集问题,并将 tty 选项重置为合理值。
问题在于重置是它还会在某些系统上打印额外的消息(例如“擦除是...”、“中断是...”);您可能不希望在每次提示之前显示这些消息。如果您的实现重置将消息和控制序列发送到不同的地方(例如,一个发送到 stdout,而另一个发送到 stderr),那么您可能能够过滤掉消息(例如PROMPT_COMMAND='reset 2>/dev/null'
(参见下文)并跳过将 ^O 放入提示中)。
^O 和stty sane
在狂欢,你可以将参数设置PROMPT_COMMAND
为命令和狂欢将在显示主提示符之前运行 if。您可以将所有调用都放在stty sane
那里,并在提示符中输入 ^O:
PROMPT_COMMAND='stty sane'
PS1="\[\017\]… "
再次,你可以避免修改 PS1(并处理非 VT-100 风格的终端),方法是使用输出(正如 Ignacio Vazquez-Abrams 所建议的):
PROMPT_COMMAND='stty sane; tput rmacs'
答案2
放
echo -n "$(tput rmacs)"
在$PROMPT_COMMAND
。
答案3
因此我将减少命令行,您总是可以在 xterm 或任何终端中有一个“按钮”重置或硬重置,对于 terminal.app,它位于 Shell 菜单下。发送硬重置 alt-command-r。