ssh先のUbuntuのtmuxでコピーしたテキストをローカルのMacOSのクリップボードに転送する

提供: Eospedia
移動: 案内検索

この記事について

表題の通りのことをやってみる。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セッションが切れるとコピペできなくなる...

(MacOS)> echo hogefuga | nc localhost 8377
(MacOS)> pbpaste
hogefuga

ローカルでポート8377番に文字列流し込んだら、pbpaste(クリップボードにある文字列を出力するコマンド)で文字列取り出せたので、Clipperは生きている。

(MacOS)> ssh -fN DL-Box-Clipper-tunnel 
Warning: remote port forwarding failed for listen port 8377

トンネル切れてんのかと思って再度通そうとするもなんか警告出るし、リモートのtmuxとのコピペもできない。


リモートの側でsshd再起動してみた。

(Ubuntu)> sudo systemctl restart sshd


それから再度ローカルでトンネルつなぎ直し。

(MacOS)> ssh -fN DL-Box-Clipper-tunnel 

今度は警告が出ずにコマンド実行できた。

で、tmuxとのコピペにも成功した。

よくわからないが、とりあえずリモートでsshd再起動して、ローカルでリモートフォワードし直せば、なんか復旧する。