跳到主要内容
版本:0.17.0+

ssh 跨系统共享 vims 剪切板的最佳解决方案

本篇文章详细地记录整理了如何跨系统共享VIM剪切板的问题,具体地说来,就是如何在 sshvim (in or not in tmux)里快捷地复制到本地系统剪切板,主要用到了 X11 共享剪切板的特性,以及基于 socket 实现地传输。

picture 2

0. before you start

  • premise your socket port for sharing clipboard is 19988
  • premise your server connected to is $YOUR_SERVER
  • I just implemented from MacOS(local) to Ubuntu(remote), and the logic is no different on other platforms.
  • mark is my nickname

1. ensure the installed vim supports X11

ensure +X11 (instead of -X11) in vim --version

if not, install another version of vim, otherwise the * | + registries would not work (with a sound of beam for warning):

# ref: sudo apt install vim-gtk3
sudo apt install vim-gtk3

2. enable X11 on remote ubuntu via ssh

警告

to fix Error: Can't open display: (null) when using echo "xx" | xclip on remote ubuntu, I found we should config ForwardX11 yes in both local and remote ssh config, see: https://askubuntu.com/a/305681/1629991

1. config

## -- local ---
# /etc/ssh/ssh_config
Host *
ForwardX11 yes

## -- remote ---
# /etc/ssh/sshd_config
X11Forwarding yes

2. connect on client

# the `-X` is to enable the `X11-forward` feature
ssh -X mark$YOUR_SERVER

3. test on remote

➜  ~ echo 'clip on air' | xclip
➜ ~ xclip -o
clip on air
➜ ~ xclip -selection clipboard -o
zzz2
➜ ~ echo 'clip on clipboard' | xclip -selection clipboard
➜ ~ xclip -o
clip on air
➜ ~ xclip -selection clipboard -o
clip on clipboard
➜ ~ xclip -sel clipboard -o
clip on clipboard
➜ ~ xclip -sel clip -o
clip on clipboard

3. enable access to clipboard on remote ubuntu at local (part 1: basic)

首先可以看一下这篇Forward your clipboard via SSH reverse tunnels,它给出了最简单的基于无限循环监听端口(nc -l)并复制(pbcopy)的方案。

1. enable listen on one shell

while (true); do nc -l 19988 | pbcopy; done

2. connect using reverse tunnelling

solution 1

ssh mark@$YOUR_SERVER -R 19988:localhost:19988

solution 2

  1. config on local
# ~/.ssh/config
RemoteForward 19988 localhost:19988
  1. (possibly necessary) reload ssh
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
  1. connect without -R
ssh mark@$YOUR_SERVER

3. test on remote

echo "test 1" | nc -q0 localhost 19988

then we can access the test 1 in the local clipboard.

4. enable access to clipboard on remote ubuntu at local (part 2: socket)

see more at: tmux in practice: copy text from remote session using SSH remote tunnel and systemd service | by Alexey Samoshkin | HackerNoon.com | Medium

1. config plist

PLIST_PBCOPY_SSH=`~/.pbcopy_ssh.plist`
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>pbcopy-ssh</string>

<key>UserName</key>
<string>mark</string>

<key>Program</key>
<string>/usr/bin/pbcopy</string>

<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockNodeName</key>
<string>localhost</string>
<key>SockServiceName</key>
<string>19988</string>
</dict>
</dict>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<false/>
</dict>
</dict>
</plist>

2. chmod (necessary)

chmod 755 $PLIST_PBCOPY_SSH

see https://developer.apple.com/forums/thread/665661?answerId=695171022#695171022, otherwise would have the following error if we load or unload the plist file:

Load failed: 5: Input/output error
Try running `launchctl bootstrap` as root for richer errors.

3. start plist

launchctl load $PLIST_PBCOPY_SSH
launchctl start pbcopy-ssh

we can also check the running state of plist via launchctl print gui/501/pbcopy-ssh | grep state to only get state = not running, but it have worked actually.

4. test plist

ssh mark@$YOUR_SERVER -R 19988:localhost:19988

echo 'test 2' | nc -q0 localhost 19988

then we can access the test 2 in the local clipboard.

TODO: 5. auto-start plist after login

5. enable vim copy to registry

see more at: How to copy to clipboard in Vim? - Stack Overflow

1. map Y to copy selected content into register +

vnoremap Y "+y

2. usage

  1. shift + V to switch to Visual Mode and select the current line, then use the Arrow key of UP | DOWN to select more lines.
  2. press Y to copy the selected lines into the clipboard

6. enable vim copy to local clipboard

see more at: [ssh - How to use X11 forwarding to copy from vim to local machine - Stack Overflow](https://stackoverflow.com/questions/47822357/how-to-use-x11-forwarding-to-copy-fro m-vim-to-local-machine)

Based on section of 4. enable vim copy to registry, we can manually run a system command that send the registered content into system clipboard (local via xclip or pbcopy or remote via nc and xclip or pbcopy).

For example, we can use : call system('nc -q0 localhost 19988', @+) to send the content in register + to the local port at 19988.

警告

we should add -q0 for nc if necessary, otherwise I found that the command just won't stop input (since it would has verbose output).

So, for convenience, we can directly use the following vim script to map the sequences into one key of Y:

" -- enable Y to copy to clipboard, ref: https://stackoverflow.com/a/67890119/9422455
" how to map two commands with only one key, ref: https://vi.stackexchange.com/a/3886
" what's the meaning of <CR> (which can be omitted in bottom command), ref: https://stackoverflow.com/a/22143208/9422455

vnoremap Y "+y :call system('nc -q0 localhost 19988', @+)<CR>

7. enable tmux copy to local clipboard

see more at: vim与系统剪切板之间的复制粘贴 - 广漠飘羽 - 博客园

after vim configured, the tmux copy paste would runs well if we use the oh-my-tmux config at https://github.com/gpakosz/.tmux

picture 1

core reference