yujiro's blog

「インターネット上で正しい答えを得る最善の方法は、質問することではない。間違った答えを投稿することだ」by ウォード・カニンガム。 辛辣なコメントお待ちしております。

Clipper を使って、ゲストOS [Ubuntu]とホストOS [Mac] 間でクリップボードを共有する

はじめに

私がWeb開発する上で欠かせないclipper をご紹介したいと思います。

GitHub - wincent/clipper: Clipboard access for local and remote tmux sessions

結構これ教えると喜ばれる事が多かったので需要があるのかなと思いました。

これを使うと、ゲストOS上で作業をしている際、tmux や vimでヤンクしたものや、何かコマンドの標準出力をホストOS側のクリップボードにコピーすることができます。

イメージとしては以下の感じです。

f:id:bambookun:20171119142421g:plain

仕組みとしては、ホスト 上で clipper プロセスを起動させ、ゲスト上でホスト上のクリップボードにコピーしたい内容を netcat (ncコマンド)で送信させます。(これは .vimrc や .tmuxconf に仕込んでおきます。後ほど紹介します) ホストはゲストとssh ポートフォワードで繋がれていて、clipper がその内容をホストのclipboard に挿入する、と言った感じです(おそらく)。このあたり、後ほど詳しく原理を説明します。

前提ですが、ホストOSは Mac です。

ゲストOSは Ubuntu でも (試してないけど)CentOS でもイケるかと思います。

一応、ここでは

ホストOS : Mac

VM : virtualbox

ツール : vagrant

ゲストOS : Ubuntu

といった環境で説明します。

導入

インストールは

$ brew install clipper

で終了です。

終わったら

$ clipper &

で起動させてみましょう。

多分、.clipper.json がないぞってでるので、空で作っておきます。つまり中身を

{}

でファイルを作ってください。

こちらのファイルですが、ログのディレクトリ等指定することができます。

それでもう一回 $ clipper & で起動させます。

僕はターミナルの起動シェルに自動で立ち上がるスクリプトを仕込んでいます。

f:id:bambookun:20171119142443p:plain

#!/bin/sh
c=$(ps ax | grep clipper | wc -l)
if [ $c -ne 2 ]; then
  clipper &
fi

さて、ゲストOS上の vim や tmux, zsh の設定です。

vim ですが、clipper のREADMEにも載っているように、

"send to clipboard"
vnoremap <silent>y y :call system('nc localhost 8377', @0)<CR>
vnoremap <silent>d d :call system('nc localhost 8377', @1)<CR>

でOKです。

これはヤンクされた際、もしくはdで削除された際にその内容をnc コマンドでホスト上に送信するってことです。

次に .tmux.conf ですが、

bind-key -t vi-copy Enter copy-pipe "nc localhost 8377"

の行をどこかに挿入してください。

あとは、.zshrc に

alias clip="nc localhost 8377" 

をいれています。こうすることで簡単に cat した内容だったり、curl したものをクリップボードに送信することができます。

$ cat hoge.txt | clip

って感じです。

ゲストOS側はこれでOKです。

最後にホストOS側で1つコマンドを実行しておく必要があります。

$ ssh -f -N -R 8377:localhost:8377 vagrant@[host or ip]

これで全部OKです。

原理

先程の最後のコマンドですが、これはリモートフォワードです。

ポートフォワーディングについては

https://qiita.com/mechamogera/items/b1bb9130273deb9426f5

こちらが大変わかりやすいです。

remoteの8081番にアクセスするとlocalからアクセスできるtarget:80に繋げる例 ssh -R 8081:target:80 remote

これをここでの例に当てはめると

=> remote(ゲスト[ubuntu])の8377番にアクセスするとlocal(ホスト[mac])からアクセスできるtarget(ホスト[mac]):8377に繋げる例

となります。

ここで target が紛らわしいのですが、ここで言えばmac からアクセスできるサーバーであれば、さらにそっちに繋ぐことができるということです。ここでは自分の8377に対して繋いでいます。

これがバックグラウンドで動いている、ということになるので、remote(ゲスト[ubuntu])のポート8377に対して、常にlocal(ホスト[mac])からアクセスしていて、local(ホスト[mac])がアクセス可能なtarget(ホスト[mac]):8377に繋げている、ということになります。

なので、ゲスト側では nc localhost 8377 という風にゲスト自身に対してリクエストを送っていて、それをホスト側からアクセスしにいき(常にしている)、かつホストの8377 ポートに繋いでいる、といった前提があって

clipper がそれを mac のclipboard に挿入する、と言った感じでしょうか。

多分そんな感じです!

以上です。