ssh先のUbuntuのtmuxでコピーしたテキストをローカルのMacOSのクリップボードに転送する
目次
この記事について
表題の通りのことをやってみる。Clipperというプログラムを活用する。参考にしたのはClipperのREADMEと、こちらのページ → https://blog.freedom-man.com/tmux
2019年8月26日実施。
実行環境
リモート
- Ubuntu 16.04.6 LTS
- tmux 2.9a
ローカル
- MacOS Mojave 10.14.6
ローカル(MacOS)側準備
Clipperのインストール
まずはMacOSにClipperをインストールする。Homebrew(パッケージマネージャ)を使う。
clipperのインストールはtmuxセッション内で実行してはいけないらしい。まるで理由がわからないが。
(MacOS)> brew install clipper
ユーザーログイン後に自動でClipperが動くようにする
Clipperはネットワークポートに送られてくる情報を受け取ってクリップボードに転送してくれるデーモンプロセス的なものらしい。
起動するには、多分、ログイン後に毎回手動でターミナルに "clipper" とか打てば済むのだとは思うが、めんどいのでログインしたら自動で起動するようにする。
お好みのコマンドを自動実行するためには、launchctlを使う。plistというフォーマットの設定ファイルを書き、それを~/Library/LaunchAgents/に格納して、launchctlにロードさせれば、plistで設定した通りコマンドが実行されるようになる。らしい。
plistとか何をどう書けばいいのかわかんないので、とりあえずClipperのGithubリポジトリから取ってきて使うことにする。
# Clipperリポジトリをダウンロード (MacOS)> git clone https://github.com/wincent/clipper.git # plistを~/Library/LaunchAgents/ にコピーする (MacOS)> cp clipper/contrib/darwin/tcp-port/com.wincent.clipper.plist ~/Library/LaunchAgents/
で、Clipper のREADMEに書いてある方法でロードする。
(MacOS)> launchctl load -w -S Aqua ~/Library/LaunchAgents/com.wincent.clipper.plist
-wとか-S Aquaとかman読んでも全く意味がわからないが気にしないことにする。
launchctl list でlaunchctlで管理されているプログラムの一覧が見れるらしいので、確認してみる。
(MacOS)> launchctl list | grep clipper 69505 0 com.wincent.clipper
PID(1列目の数字)が割り当てられているので、loadしただけで起動している様である。
sshリモートフォワードの設定
sshリモートフォワードを使って、リモート(Ubuntu)の特定のポートに飛んできた情報を、ローカル(MacOS)の特定のポートに転送することが可能である(トンネルを掘る、とか表現される)。この仕組みを使って、リモートのtmuxでコピーしたテキストをリモートのポート8377番に飛ばし、それをリモートフォワードでローカルのポート8377番(※Clipperがlistenするポート)に転送して、Clipperにテキストを流し込み、Clipperがそれをクリップボードに貼り付ける、みたいな流れを作れる。
sshのコンフィグ書く
簡単のため、まずは~/.ssh/config に以下の様に設定を書く。DL-Boxはリモート(Ubuntu)のホスト名。
# DL-BoxにClipper用のsshトンネル掘るための設定 Host DL-Box-Clipper-tunnel # リモートのIPアドレス HostName <IPアドレス> # sshログインのユーザー名 User <ユーザー名> # リモートのポート8377番(第一引数)をローカルのポート8377番にリモートフォワードする RemoteForward 8377 localhost:8377 # RSA鍵交換でログイン IdentityFile ~/.ssh/id_rsa
トンネル掘る
上記コンフィグを設定した後なら、
(MacOS)> ssh -fN DL-Box-Clipper-tunnel
と叩けばトンネルは開通する(-fはバックグラウンド実行の指定、-Nはsshログイン後に何もコマンドを実行しないことを指定)。これもplist書いてlaunchdにやらせるようにしたいが、とりあえず先へ進む。
Clipperの動作確認
tmux云々の前に、適当な文字列がリモートからローカルのClipboardへ送れるかをチェックする。ncコマンド(netcat)を使う。ncコマンドは標準入力を特定のホストの特定のポートへ転送するためのコマンドである。
(Ubuntu)> echo 'hoge' | nc localhost 8377
上記で、hogeという文字列を、リモート(リモートマシンから見ればローカルなのでlocalhostと書いている)のポート8377番へ送り込んでいる。DL-Box:8377→MacOS:8377へのトンネルは開通済みで、かつClipperも起動しているので、上記によりローカルのMacOSのクリップボードに'hoge'という文字列が貼り付けられているはずである。
実際 Command + v で貼り付けてみた結果、'hoge'という文字列が貼り付けられた。つまり成功。
リモート(Ubuntu)のtmuxの設定
tmuxの設定ファイルは ~/.tmux.conf である。ここに表題のことをするための設定を記載する。
設定はお好みなのでいろんなやり方があるが、私は以下のようにした。
ベースにした.tmux.confはこちら → https://qiita.com/komiya_5467/items/ab57eae767b98a765465
.tmux.conf全体
# tmuxを256色表示できるようにする set-option -g default-terminal screen-256color set -g terminal-overrides 'xterm:colors=256' # ステータスバーをトップに配置する set-option -g status-position top # 左右のステータスバーの長さを決定する set-option -g status-left-length 90 set-option -g status-right-length 90 # #P => ペイン番号 # 最左に表示 set-option -g status-left '#H:[#P]' # Wi-Fi、バッテリー残量、現在時刻 # 最右に表示 set-option -g status-right '[%Y-%m-%d(%a) %H:%M]' # ステータスバーを1秒毎に描画し直す set-option -g status-interval 1 # センタライズ(主にウィンドウ番号など) set-option -g status-justify centre # ステータスバーの色を設定する set-option -g status-bg "colour238" # status line の文字色を指定する。 set-option -g status-fg "colour255" # vimのキーバインドでペインを移動する bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # vimのキーバインドでペインをリサイズする bind -r H resize-pane -L 5 bind -r J resize-pane -D 5 bind -r K resize-pane -U 5 bind -r L resize-pane -R 5 # | でペインを縦分割する bind | split-window -h # - でペインを縦分割する bind - split-window -v # 番号基準値を変更 set-option -g base-index 1 # マウス操作を有効にする set-option -g mouse on bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'copy-mode -e'" # コピーモードを設定する # コピーモードでvimキーバインドを使う setw -g mode-keys vi # 'v' で選択を始める bind -T copy-mode-vi v send -X begin-selection # 'V' で行選択 bind -T copy-mode-vi V send -X select-line # 'C-v' で矩形選択 bind -T copy-mode-vi C-v send -X rectangle-toggle # 'y' でヤンク bind -T copy-mode-vi y send -X copy-selection # 'Y' で行ヤンク bind -T copy-mode-vi Y send -X copy-line # 'C-p'でペースト bind-key C-p paste-buffer bind-key -T copy-mode-vi v send -X begin-selection bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "nc localhost 8377" bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "nc localhost 8377" bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc localhost 8377"
ポイント
.tmux.confの以下の部分。
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "nc localhost 8377" bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "nc localhost 8377" bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc localhost 8377"
MacOSローカルのtmuxの場合は "nc localhost 8377" が "pbcopy" なんじゃないかと思う。pbcopyは標準入力をクリップボードに送るためのコマンド。今回はその代わりに、Clipperの動作チェックでも使用したncコマンドを使って、ポート8377番にコピー内容を転送している。
実際に上記のconfでテストしたところ表題の件には成功した。リモートかローカルか区別・意識すること無く、MacOSの Command + c, Command + v でコピペできるようになった。
追記
一度sshセッションが切れると(timeoutとかで)、もうコピペできなくなる。がちゃがちゃ色々やってみたけど対処策不明。