箭头键在终端的 OS X 上的 htop 中不起作用

Dan*_*tep 6 osx-snow-leopard terminal.app macos

不知道它什么时候发生,或者我做了什么(如果有的话),但是我的箭头键在 htop 中不能再滚动了。他们曾经虽然。

您应该能够上下按来上下滚动进程列表,但它们不起作用。一些键往往相当于“返回”或其他东西。如果我在设置屏幕上,向左、向上和向下都返回主屏幕。

htop 似乎是唯一受影响的程序。

  • TERM 是 xterm 颜色
  • less 不受影响(可以上下滚动)
  • htop 来自homebrew,它使用github 上的htop-osx repo,自 2009 年年中以来没有改变
  • TERMINFO 为空

我的 cat -v 输出

% cat -v
^[[A^[[B^[[C^[[D
^[[A^[[B^[[C^[[D
%
Run Code Online (Sandbox Code Playgroud)
  • less 和 htop 都使用系统(因此相同)ncurses
  • root用户同样的问题

sh 脚本的输出

Type <Up> <Down> <Right> <Left> <Control-D> <Control-D>
(no output until after the first <Control-D>, please type "blindly")
    ^[OA^[OB^[OC^[OD
Expected:
    ^[OA^[OB^[OC^[OD
Run Code Online (Sandbox Code Playgroud)

我也试过使用iTerm,它给出了相同的结果,所以它不是专门的 Terminal.app

第 6 集:绝地归来

它想链接到 libncurses,但是自制的 ncurses 使用宽字符模式编译,因此您获得的所有库都是 libncursesw。我删除了在 brew 中使用宽字符编译的标志,安装了自制软件 ncurses,并从 ncurses 安装了 htop,现在它可以工作了。

Chr*_*sen 12

附录:显然 10.6.3 中的 ncurses 已损坏

SO 上的答案链接到一个博客条目,该条目描述了对该问题的其他一些调查。一种已报告的解决方法是从 10.6.2 复制 ncurses 库,但这可能会产生意想不到的副作用。


ESC 通常是终端(或终端仿真程序如Terminal)为特殊键(如箭头键F1HomePage Up、 等)发送的“控制序列”的第一个字符。

ESC还用作htop 中的“返回”键(通常仅在延迟之后,以便慢速连接有足够的时间发送恰好以 ESC 开始的完整控制序列)。

请使用以下问题的答案更新您的问题:

什么是术语?

也许您的 TERM 环境变量具有奇数值?echo $TERMhtop行为如您所描述的那样的窗口中报告什么?TERM应该是xterm-color,或类似的东西。

你从哪里得到的htop?麦克波特?芬克?其他?

使用系统提供的 ncurses 编译的应用程序将使用来自/usr/share/terminfo/. MacPorts 通常/opt/local/用作其前缀,因此使用来自 MacPorts 的 ncurses 的应用程序将使用来自/opt/local/share/terminfo/. Fink 通常使用/sw/作为其前缀,因此使用 Fink 中的 ncurses 的应用程序将使用来自/sw/share/terminfo/.

请问TERMINFO环境变量有一个值?如果是这样,ncurses(无论来源如何)将在其中指定的目录中查找。

可能是您对 TERM 中指定的终端的 terminfo 定义部分损坏(“部分损坏”,因为输出控制序列必须正常,否则您会看到明显的显示异常)。

哪些程序不受影响?

如果您有基于 ncurses 的程序来处理箭头键 OK(可能使用不同的 ncurses 安装),您可以尝试将其他 terminfo 条目与htop 一起使用,反之亦然(通过设置TERMINFO为来自其他 ncurses 安装的条目的位置)。

您的终端实际发送什么代码?

使用cat -v检查哪些代码,当您使用箭头键发送。下面是我看到的时候我按UpDownRightLeftEnterControl-D启动后cat -v

% cat -v
^[[A^[[B^[[D^[[C
^[[A^[[B^[[D^[[C
% 
Run Code Online (Sandbox Code Playgroud)

第一组代码是 tty 设备产生的回声。第二组由cat 生成,可能与发送的第一组不同,具体取决于存在的确切代码。

这些代码可以在终端中配置,但通常没有必要,因为有特殊模式可以更改代码(有时向上发送ESC [ A,有时发送ESC O A.

最终的问题是htop无法识别正在发送的任何代码作为箭头键的代码,因此了解实际正在发送的代码可能会很有用。


附录:来自 Homebrew 的htop就OK

htop与哪些 ncurses相关联?

看来,HTOP “公式”在2009年底改为不依赖于ncurses的的家酿版本。据推测,这意味着从这个新公式构建的htop版本将使用系统 ncurses。那么,您的htop二进制文件使用了哪些 ncurses ?

ls -l "$(which htop)"
otool -L "$(which htop)"
Run Code Online (Sandbox Code Playgroud)

如果您的htop早于 2009-12-18 或者它与您的 Homebrew ncurses(可能/usr/local/lib/libncurses.5.dylib)相关联,那么您可能会考虑重建htop公式(brew remove htop; brew install htop?)。或者,如果您现有的htop二进制文件使用的是 ncurses 的 Homebrew 版本(或者重建版本也仍然使用 Homebrew ncurses),那么您可以尝试重建 ncurses 公式。

你提到less工作正常。似乎没有针对less 的Homebrew 公式,因此您可能正在使用系统提供的less。值得注意的是,您的less使用哪个 ncurses与htop进行比较。

otool -L "$(which less)"
Run Code Online (Sandbox Code Playgroud)

附录:htop较少使用系统 ncurses

如果问题是由每个用户的一些配置引起的,那么如果您创建一个全新的用户并在以他们的身份登录时尝试它,它应该会消失。如果问题在全新用户下仍然存在,您就知道这是一个系统范围的问题(或者问题出在为所有新用户提供的基本初始配置中!)。完成测试后,只需删除用户即可避免登录选择器等混乱。

终端和其他 VT100 型终端和终端仿真器具有“应用程序光标键”模式,其中光标键向应用程序发送不同的控制序列。在“应用程序”模式下,终端发送^[OA^[OB^[OC^[OD而不是^[[A^[[B^[[C^[[D(分别为向上、向下、向右、向左)。终端发送的非“应用程序”模式序列与终端期望作为光标控制代码接收的代码相同。

您的终端可能没有发送正确的应用程序光标键代码。这似乎不太可能,因为您说less有效(它也使用“应用程序”模式)。大概你的意思是箭头键可以在less 中导航。由于“肌肉记忆”,我几乎总是使用vi风格的键 ( kjlh) 在less 中导航。

终端发送什么“应用程序光标键”代码?

您可以检查终端是否正在发送预期的“应用程序光标键”序列,如下所示:

sh -c "$(cat <<\EOF
noecho_appmode() {
  stty -echo
  printf '\033[?1h'
}
modes="$(stty -g)"
restore_echo_and_appmode() {
  stty "$modes"
  printf '\033[?1l'
}
printf '\nType <Up> <Down> <Right> <Left> <Control-D> <Control-D>\n'
printf '(no output until after the first <Control-D>, please type "blindly")\n\t'
noecho_appmode             ; trap 'restore_echo_and_appmode' 0
cat -v
restore_echo_and_appmode   ; trap ''                         0
printf '\nExpected:\n\t'
printf 'kcu%c1\n' u d f b | /usr/bin/tput -S | cat -v
printf '\n\n'
EOF
)"
Run Code Online (Sandbox Code Playgroud)

标记为“预期:”的输出基于您的 系统 terminfo 条目TERM,因此它应该是基于 ncurses 的程序期望看到的。

如果实际代码与预期代码不同,那么您应该调查终端的配置以找出错误代码配置的位置。

如果这并不表示任何问题(来自终端的代码与预期代码匹配),我将在ktrace(或者可能是一些 DTrace?)下运行htop的非 setuid 副本以查看原位 I/O。I/O 的性质可能会给某些人提供问题原因的线索。由于报告了加载共享库和支持数据文件的详细信息,kdump的完整输出将非常大,但即使去掉这些内容,我仍然从kdump获得近 2000 行和 100kB 的输出。这可能太多了,无法在这里发布。