在远程桌面中,中文输入可以分为两个问题:终端如何显示中文,以及 图形程序如何连接输入法。本文记录一次实际排查:从桌面节点打开 Terminal,再通过 SSH 连接计算节点,并在远程节点启动 VS Code。
环境和目标
| 节点 | 用途 |
|---|---|
172.31.0.122 |
Xfce 桌面,运行 Terminal 和桌面 IBus |
172.31.0.132 |
SSH 目标节点,运行远程 shell 和 VS Code |
两台机器的用户家目录通过 NFS 共享。因此,在一台机器修改的 ~/.cshrc 和 ~/bin 脚本,在另一台机器也能看到;修改启动配置时必须考虑机器差异。
目标是:
- 在
122的桌面 Terminal 输入、显示中文。 - SSH 到
132后,在 shell 中输入、显示中文。 - 从
132的 shell 启动 VS Code,在编辑器中输入、显示中文,并尽量让候选框靠近输入光标。
本文使用 IBus 和 Intelligent Pinyin(
libpinyin),桌面为 X11 环境。下文的候选框位置是相对于文本插入光标,不是保证跟随鼠标指针。
一、先配置桌面的中文输入法
在 122 的桌面打开 IBus Preferences,进入 Input Method,点击 Add,添加中文输入法,例如 Chinese → Intelligent Pinyin。
使用桌面配置的输入法切换快捷键,切换到中文输入法后,在桌面应用中试输中文。具体快捷键可以在 IBus Preferences 中查看或调整。
二、解决本机 Terminal 中中文显示为问号
添加中文输入法后,最初在 Terminal 中输入中文仍显示为问号。将 Terminal 菜单中的 Encoding 设置为 UTF-8 后,中文输入和显示正常。
终端编码和输入法是不同的设置:输入法负责把拼音转换为汉字,终端编码决定终端如何解释和显示字符。应先确认:
- Terminal 的 Encoding 为 UTF-8。
- 桌面输入法已经切换为中文。
- shell 的 locale 支持 UTF-8。可以运行
locale查看;具体应使用系统实际安装的 UTF-8 locale。
三、SSH 后在远程 shell 中输入中文
从 122 的 Terminal 连接 132:
1
ssh 172.31.0.132
连接后可检查远端 locale,并试输中文:
1
2
locale
printf '中文测试\n'
这里的 Terminal 窗口仍运行在 122,中文输入也是在本地 Terminal 完成后,通过 SSH 传给 132 的 shell。远端 shell 不需要仅为了接收中文而单独启动一个 IBus;终端编码、远端 locale 和远端应用的字符处理仍需匹配 UTF-8。
四、远程启动 VS Code:能输入但候选框位置不理想
VS Code 是从 132 启动并显示在 122 桌面上的图形程序,输入法连接方式与终端不同。首先尝试过:
1
env GTK_IM_MODULE=ibus QT_IM_MODULE=ibus XMODIFIERS=@im=ibus code
在当时的环境中,这种方式无法输入中文。将输入法模块改为 XIM 后,中文输入得到验证,但候选框位置不理想,离编辑器内的文本光标较远:
1
env GTK_IM_MODULE=xim QT_IM_MODULE=xim XMODIFIERS=@im=ibus code
这种方式适合只要求能够输入中文、可以接受候选框位置的情况。它依赖可访问的 X11 显示和相应 IBus/XIM 服务;如果 VS Code 复用了已经运行的进程,新设置未必会被该进程采用。
五、让 VS Code 候选框靠近输入光标
进一步测试发现,在 132 上为 VS Code 使用 D-Bus 会话和 IBus,再以 IBus 模块启动 VS Code,可以让候选框出现在输入光标附近。
先确认从 132 可以打开图形程序,且 $DISPLAY 指向 122 的桌面。如果使用 SSH X11 转发,连接时可按站点配置使用 ssh -X 或 ssh -Y;不要在未确认显示连接可用时继续排查输入法。
手动测试示例:
1
2
3
4
5
6
7
dbus-run-session -- sh -c '
ibus-daemon -d
sleep 1
ibus engine libpinyin
env GTK_IM_MODULE=ibus QT_IM_MODULE=ibus XMODIFIERS=@im=ibus \
code --user-data-dir=/tmp/vscode-native-ibus --new-window --wait
'
在打开的编辑器中输入拼音,检查候选框是否靠近文本插入光标,以及汉字是否能正常提交。--user-data-dir 使用独立的 VS Code 用户数据目录,避免复用其他 VS Code 实例;因此这个实例的设置、扩展等可能与平时使用的实例不同。--wait 让启动命令等待窗口关闭。
综上,解决方案:Wrapper自动识别与启动
以下 Wrapper 是本环境使用的启动方式。它优先尝试使用当前环境中的 D-Bus 和 IBus;否则为 VS Code 创建一个新的 D-Bus 会话。
将其保存在与 code 命令相同的目录(本环境以 /tools/OSS/VSCode/1.129.1/bin 为例),命名为 code-ibus,并赋予执行权限,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/sh
# VSCode launcher with ibus/libpinyin. Reuses an existing dbus+ibus, else starts its own.
# wanlinwang, 20261030
export GTK_IM_MODULE=ibus QT_IM_MODULE=ibus XMODIFIERS=@im=ibus
# Real VSCode = sibling `code` next to this script (no PATH lookup, so no alias/recursion issues).
HERE=$(dirname "$(readlink -f "$0")")
CODE_BIN=$HERE/code
if [ ! -x "$CODE_BIN" ]; then
echo "ERROR: $CODE_BIN not found. Load a VSCode version first, e.g.: ml VSCode/1.129.1" >&2
exit 1
fi
if [ -z "$DISPLAY" ]; then
echo "ERROR: DISPLAY is not set (use ssh -X/-Y, or bsub -XF / -Is with X forwarding)." >&2
exit 1
fi
UDD=/tmp/vscode-ibus-$USER # per-user, so users on a shared host don't collide
have() { pgrep -u "$USER" -x "$1" >/dev/null 2>&1; }
if [ -n "$DBUS_SESSION_BUS_ADDRESS" ] && have dbus-daemon; then
# Reuse the existing session bus; start ibus only if it isn't running.
have ibus-daemon || { ibus-daemon -drx; sleep 1; }
ibus engine libpinyin
exec "$CODE_BIN" --user-data-dir="$UDD" --new-window --wait "$@"
else
# No usable bus: start a private one.
exec dbus-run-session -- sh -c '
CODE_BIN=$1; UDD=$2; shift 2
ibus-daemon -drx
sleep 1
ibus engine libpinyin
exec "$CODE_BIN" --user-data-dir="$UDD" --new-window --wait "$@"
' sh "$CODE_BIN" "$UDD" "$@"
fi
在 Modulefile 中设置 code 指向 code-ibus
1
2
3
4
5
6
7
8
[wanlin.wang@rd-172-31-0-132 ~]$ ml show VSCode/1.129.1
-------------------------------------------------------------------
/tools/modulefiles/OSS/VSCode/1.129.1:
module-whatis {Modulefile for OSS/VSCode/1.129.1}
prepend-path PATH /tools/OSS/VSCode/1.129.1/bin
set-alias code code-ibus
-------------------------------------------------------------------
此后,无论是在桌面启动的 shell 环境还是在 从桌面环境 ssh 过去后的 shell 环境,加载该 VSCode 均能使用配置好的 中文输入法。
六、排查时的记录
| 场景 | 处理方式 | 本次观察 |
|---|---|---|
122 本机 Terminal |
添加 IBus 中文输入法,Terminal 设为 UTF-8 | 能输入、显示中文 |
SSH 到 132 的 shell |
保持 Terminal 和 locale 使用 UTF-8 | 能输入、显示中文 |
132 的 VS Code,XIM |
设置 GTK_IM_MODULE=xim 等环境变量 |
能输入,但候选框离文本光标较远 |
132 的 VS Code,IBus |
在远端 D-Bus 会话中启动 IBus 和 VS Code | 测试时候选框靠近文本光标 |