我遇到了一个我不确定如何调试的行为。
基本设置
在编辑 python 文件时,我有一个 vim 脚本可以与 IPython 交互。基本上它会运行我在光标处选择的任何命令。它工作得很好,大大提高了我的工作效率。但是,有一个问题。当 IPython 终端在 SSH 窗口中时,速度非常慢。这可能是一个非常小众的问题,所以我会尽力解释它,并尽可能提供 MWE,但这里有很多组件在起作用。
我在客户端和服务器系统上运行带有 Gnome 3 前端的 Ubuntu Linux 16.04。IPython 是 5.2.2 版。我的终端是终结者。
初步实验
当 vim 收到一个 is 时执行这个基本脚本:
- 将当前行复制到系统剪贴板。
- 预处理文本以修复任何缩进问题。
- 用于
wmctrl
查找并记住我的 gvim 窗口的窗口 ID。 - 用于
wmctrl
查找最近选择的终端窗口的窗口 ID(这通常是运行 IPython 的窗口)。 - 用于
wmctrl
专注于 IPython 窗口 - 用于
xdotool
发送 ctrl+shift+v 键序列。这会将文本粘贴到 IPython 提示符中。 - 用于
xdotool
发送 KP_Enter,它将在 IPython 提示符下执行代码。 - 用于
wmctrl
将焦点重新回到 gvim 窗口,这使得交互看起来很流畅(通常情况下,但在这种情况下不会)。
在脚本的后半部分,它等待 0.01 秒让每个命令执行。
我写了一些调试文本和时间戳,看看我是否能查明是什么花了这么长时间。
1496591696.3065512
----
CopyGVimToTerminalDev
1496591696.3065684 mode = 'n'
1496591696.3065758 return_to_vim = '1'
1496591696.3065836 grabbing text at current line
1496591696.3066013 preparing text
1496591696.3066237 copying text to clipboard
1496591696.3157291 copied text to clipboard
1496591696.315782 Running script
Executing x do: (
('remember_window_id', 'ACTIVE_GVIM'),
('focus', 'x-terminal-emulator.X-terminal-emulator'),
('key', 'ctrl+shift+v'),
('key', 'KP_Enter'),
('focus_id', '$ACTIVE_GVIM'),
)
# Step 0
[]
# Step 1
['wmctrl', '-ia', '0x2400004'] wmctrl -ia 0x2400004
# Step 2
['xdotool', 'key', 'ctrl+shift+v'] xdotool key ctrl+shift+v
# Step 3
['xdotool', 'key', 'KP_Enter'] xdotool key KP_Enter
# Step 4
['wmctrl', '-ia', '0x3400003'] wmctrl -ia 0x3400003
1496591696.550773 Finished script
您可以看到脚本从时间 1496591696.3065684 开始,然后很快通过第一部分,在 1496591696.315782 结束,到目前为止只有 ~.01 秒并且不明显。然后它执行wmctrl
andxdotool
命令。这些是使用 python 的子处理模块调用的。总的来说,整个脚本在 1496591696.550773 处结束,总共只有 ~.2 秒,这也不是很明显。
因此,脚本本身很快。但是当我查看 IPython 终端时,至少 1 或 2 秒内没有任何反应。我相信这是因为当 xdotool 执行时它会很快返回,但是发送的密钥序列被卡在某个缓冲区的某个地方并且永远存在。
最小的例子
所以,我确定问题不在我的脚本中。它要么与 ipython、ssh 和/或 xdotool 的某种组合有关。这是重现该问题的 MWE:
- 打开一个终端窗口。
- 使用 查找终端窗口的 ID
wmctrl -lx
。 - SSH 进入远程机器并启动
ipython
. - 打开第二个终端窗口。
- 将任何虚拟文本复制到剪贴板。
执行这个测试命令(使用正确的窗口 ID):
wmctrl -ia 0x2400004 && xdotool key ctrl+shift+v && xdotool key KP_Enter
当我这样做时,会发生同样的缓慢。它很快切换到终端窗口,我可以看到测试命令在我的第二个终端中完成,但粘贴的文本在 IPython 中没有出现大约 4 秒(手动计数)。
最小示例的变体
这些变化导致行为消失:
直接粘贴
如果您只是选择 IPython 窗口并按 ctrl+shift+v,则文本会立即粘贴。关于被聚焦的窗口wmctrl
或发送的 ctrl+shift+v 命令的某些东西xdotool
一定是造成问题的原因。
粘贴到 bash 提示符有效 如果您不启动 IPython,并执行测试命令,复制的文本会很快粘贴到 SSH bash 提示符中。所以 IPython 正在为这个问题做出贡献。
tmux 使行为消失
最后一个变化真的很奇怪,但可能表明潜在的问题。如果不是open terminal -> ssh -> start ipython
,我会open terminal -> ssh -> start tmux -> start ipython
,然后运行测试脚本也会快速复制文本。我猜 tmux 在替换输入缓冲区方面做了一些事情,但我真的对 I/O 细节知之甚少,无法知道那是什么。
所以,我想我已经能够确定当 IPython 直接通过 SSH 接收 IO 以及何时xdotool
发送 IO 时,这是一些奇怪的 I/O 缓冲区问题。但现在我不知道如何继续解决这个问题,或者是否有可能解决。
很好,我找到了 tmux 解决方法,但是强迫自己进入 tmux 进行这些交互式会话可能会限制输出滚动/从终端输出复制回我的客户端机器。它还阻止我做一些需要 X11 转发的事情。我希望能够直接在 ssh 中工作。
因此,如果有人有任何想法,我将非常感谢您对此的帮助。