前言
我本地是一台 Windows 11 的 ThinkPad T480,开发环境运行在一台 Linux 服务器上,基于 SSH 的方式进行访问和控制。我希望在 Linux 服务器的 Vim 中,通过 y
复制代码到本地 Windows 11 的剪切板内,通过 p
将本地 Windows 11 剪切板中最新的内容黏贴到服务器的 vim 内。本文将提供一种低成本的解决方案。
思路
Windows 的 WSL 支持直接运行 Linux X11 GUI 程序,并且在 Linux X11 GUI 中,是可以直接访问 Windows 本地的剪切板的。这意味着在 WSL 内,我们可以通过 SSH 的 X11Forward 将远端的 X11 转发到 WSL 内,这样 Linux 服务器上的 X11 GUI 程序就可以经 WSL 中转,访问 Windows 11 本地的剪切板了。
因此,我们只需:
- 基于 WSL 来登录 Linux 服务器
- 开启 SSH 的 X11Forward
- 将 Linux 服务器的 Vim 包用 GVim 包替换
即可。
效果如下:
参考配置
下面是我在 WSL 中的 SSH 客户端配置:
Host m7
User jinmiaoluo
HostName m7.jinmiaoluo.com
ForwardX11 yes
ForwardX11Trusted yes
RequestTTY force
RemoteCommand tmux -u new -A -s default -n default
下面是我在 Linux 服务器(也就是上面中的 m7.jinmiaoluo.com )上 X11 相关的 SSH 服务端配置:
# Part of the code has been omitted
X11Forwarding yes
X11UseLocalhost yes
AllowTcpForwarding yes
下面是我在 Windows Terminal 中的 Linux 服务器相关的启动命令:
C:\Windows\system32\wsl.exe -d Ubuntu ssh m7
如下图所示:
有了上面的配置,在 Windows Terminal 内就可以通过:ctrl+alt+<number>
这类快捷键快速的打开这台远程服务器。
当然,你也可以直接跟我一样,把这台服务器作为默认的 terminal profile,这样,一打开 Windows Terminal 就会自动连接这台服务器(或者通过 ctrl+shift+t
快速创建新的会话时也会基于默认的 profile)。
我将 Vim 作为 man 的分页器,配置如下(添加到 ~/.bashrc
):
# 通过 vim 来查看 man 文档
export MANPAGER="vim +MANPAGER --not-a-term -"
这样我就可以在 Vim 内浏览 man docs,并将 man 中的示例代码,通过 vim 的远程剪切板复制到 Windows 11 本地的剪切板内,最终的效果如下:
拓展
因为我们本质上是通过 X11Forward 打通了系统剪切板的同步,所以我们可以有很多拓展。
Tmux 整合
基于 Tmux 实现拷贝内容到本地 Windows 11 剪切板的全键盘操作。
VSCode 整合
实现 VSCode 内嵌 Terminal 拷贝内容到本地 Windows 11 剪切板的全键盘操作。
上面的解决方案,需要经过 WSL 进行中转,因此 VSCode Remote-SSH 这种不基于 WSL 的场景 X11Forward 会失效。我希望在 VSCode 内嵌的 Terminal 内,也能有 Tmux 拷贝内容的全键盘操作。
思路如下:
- 在 Windows 上单独跑一个 X11 环境,这里我选择的是 VcXsrv
- 通过 Windows 内置的 ssh.exe 将 X11 转发给本地的 VcXsrv
下面是我的 VSCode 相关的配置:
{
"terminal.integrated.profiles.linux": {
"tmux": {
"path": "tmux",
"icon": "terminal-tmux",
"args": ["-u", "new", "-A", "-s", "${workspaceFolderBasename}", "-n", "default"]
}
},
"terminal.integrated.defaultProfile.linux": "tmux"
}
VcXsrv 需要在 PowerShell 内添加一个环境变量才能实现 X11Forward:
# 通过:vim $PROFILE 来添加
$env:DISPLAY="127.0.0.1:0.0"
VSCode SSH 配置文件的配置如下:
Host m7
User jinmiaoluo
HostName m7.jinmiaoluo.com
ForwardX11 yes
ForwardX11Trusted yes
RequestTTY force
RemoteCommand tmux -u new -A -s default -n default
效果如下:
如果你遇到这样的报错:
在你的 .tmux.conf
内添加如下配置:
# 兼容 vscode integrated terminal
set -ga update-environment 'VSCODE_GIT_ASKPASS_EXTRA_ARGS'
set -ga update-environment 'VSCODE_GIT_ASKPASS_NODE'
set -ga update-environment 'VSCODE_IPC_HOOK_CLI'
set -ga update-environment 'VSCODE_GIT_ASKPASS_MAIN'
set -ga update-environment 'VSCODE_GIT_IPC_HANDLE'
set -ga update-environment 'VSCODE_SHELL_INTEGRATION'
即可。
如果你希望避免 VSCode Debug Launch 功能误操作你的 Tmux,可以添加如下 VSCode 配置:
{
// 省略了其他不相关的 VSCode 配置
"terminal.integrated.automationProfile.linux": {
"path": "/bin/bash",
"icon": "debug",
}
}
这样 Debug 操作的启动操作将会在独立的 Terminal 窗口内,而不是复用你的 Tmux 窗口。
Emacs 整合
其实就是把整个 Emacs GUI 跑在服务器上,通过 X11Forward 转发回本地。效果如下:
结束语
有段时间,我热衷于实现无图形界面的 Linux 远程开发环境(类似现在 GitPod 这类方案的完全命令行版本),当时解决远程剪切板的方案还是通过 Lemonade 配合 NeoVim 来实现。没想到几年后的今天,Windows 上已经可以不依赖任何服务即实现远程剪切板了。