GNU Screen の数ある魅力のひとつとして、端末に表示されている文字列をマウスによる操作を必要とせずにコピー/ペーストできる、ということが挙げられます。同じようなコマンドを別のウィンドウで実行したいときや、文字列の一部を再利用したいときなどに大変便利です。しかし当然ながら、コピーした文字列は screen プロセスのメモリ領域(ペーストバッファ)に格納さるため、ssh 接続した先で実行している screen のペーストバッファを手元に欲した場合、やむなくマウスで端末を選択(=クリップボードにコピー)することになり、いつも歯がゆい思いをしていました。つい先日までは。
ファイルに出力できるということは、つまり繋がるということ
ペーストバッファの内容は writebuf
コマンドでファイルに出力できます。その出力ファイルをクリップボードに取り込むコマンドと連携させることで手元の端末でペーストバッファを活用できます。
そんな小さな幸せに満足していたある日、次の記事を見かけました。
なるほどなるほど。Netcat でファイルの中身を送信して ssh のリモートフォワード経由で受信すると。その手がありましたか。この記事では Mac OS X の pbcopy コマンドを launchd でデーモン化する方法を紹介していますが、仕組みとしてはソケット通信とクリップボードへのアクセスができれば OS は問いませんね。繋ぐための道具を用意する
長い間渇望していた事が実現できそうなことは分かりましたが、要望がシンプルすぎるためか、なかなか手頃なツールを見つけられませんでした。
- TCP で受信したテキストデータを
- クリップボードに書き込む
ClipboardTextListenerについて
このツールは以下の機能を提供します。
- 任意のポートを TCP で Listen し、
- 受信したデータを(テキストと見なして)クリップボードに書き込みます。
- 可能であれば Win32::Clipboard を利用します。
- それ以外は OS コマンドを利用します。
- Mac OS X: pbcopy
- Linux: xsel, xclip
- Cygwin: putclip
- Windows: clip.exe
次のような設定を起動時に指定できます。
オプション | 初期値 | 説明 |
---|---|---|
-addr address | localhost | リスニングアドレス |
-port port | 52224 | リスニングポート |
-encoding encoding | shiftjis | 出力エンコーディング |
-key accept_key | change_on_install | 事前共有キー |
-verbose level_num | 0 | 端末出力レベル
|
基本的に localhost で待ち受けることを想定していますが、誰でもクリップボードに書き込めてしまうと困るので、送信データの 1行目を事前共有キーとして認識します。その文字列がツールに設定したものと一致しない場合は書き込みません。
以下に注意点や認識している点を挙げます。
- 自分ひとりしかアクセスしない前提なのでシングルスレッドで動作します。多重アクセスしないでください。
- オプションとして指定する値の妥当性チェックはしていません。あまり変な値を設定しないでください。
- 停止する方法は用意していません。
Ctrl-C
するかプロセスを kill してください。 - 受信したデータの文字コード変換に Encode.pm を使用していますが、出力エンコーディングを shiftjis にしたままでも Windows(Cygwin、ActivePerl) はもとより、Mac OS X や Linux でもとくに化けることなく OS で使用しているコードに変換されています。この辺の理解はあいまいですが、内部表現に変換されることで上手く処理されているものだと思っています。
- 自分がよく使う環境をはじめとして、以下の OS、Perl 実行環境で動作を確認しています。
- Mac OS X 10.6 / MacPorts perl5.12 / pbcopy
- Windows XP、7 / Cygwin perl5.10、ActivePerl perl5.12 / Win32::Clipboard、putclip
- Ubuntu 10.10 / perl 5.10 / xsel、xclip
ssh先screenのペーストバッファをクリップボードに貼り付ける方法
前置きが長くなりましたが、ようやく本題です。ツールを実行する端末と GNU Screen を実行している端末でそれぞれ設定が必要です。
- ツールを実行する端末
- ツールの設定と起動
- sshリモートフォワードの設定
- screenを実行している端末
- (Netcatの導入)
- 事前共有キーファイルを作成
- .screenrcの設定
ツールを実行する端末の設定
先に紹介したツールを github から取得して pl ファイルを適当な場所に置きます。実行権限の付与は任意ですが、つけてあるものとして説明します。はじめにツールの事前共有キーを変更します。これは自分だけが分かるものに変更してください。その他の設定は必要に応じて変更してください。設定の変更は直接ファイル中の値を書き換えるか、引数で任意の値を指定します。
設定の変更を終えたら、確認のため引数に -verbose 2 をつけてツールを起動します。
% ~/git/ClipboardTextListener/clipboard_text_listener.pl -verbose 2 2011/04/03 16:37:44 ClipboardTextListener[16216]: listening localhost:52224 (-verbose 2)別のシェルから Netcat を用いて動作を確認します。まずは事前共有キーなしの場合。
% date | nc -w1 localhost 52224
2011/04/03 16:39:31 ClipboardTextListener[16216]: (127.0.0.1:50782) *** NOT ACCEPTED ***つぎに事前共有キーありの場合。
% (echo change_on_install; echo $LANG; date) | nc -w1 localhost 52224
2011/04/03 16:45:12 ClipboardTextListener[16216]: (127.0.0.1:50918) *** RECEIVE TEXT *** 48 (Encoding: utf8 -> shiftjis) ja_JP.UTF-8 2011年 4月 3日 日曜日 16時45分12秒 JSTツールの出力で受信を確認できたら、別途エディタなどで送信したデータ(この場合は echo $LANG と date コマンドの出力)がクリップボードから貼り付けできることを確認します。
ここまでの動作に問題がなければ ssh クライアントの設定ファイル(デフォルトでは $HOME/.ssh/config
)にリモートフォワードの設定を記述します。コマンドラインでも指定できますが面倒なのでファイルに書いておきます。ポート番号を変更している場合は適宜読み替えてください。
Host example.com ... RemoteForward 52224 localhost:52224この設定により ssh 接続先(example.com)の 52224 ポートが localhost:52224 に転送されるようになります。ツールを実行する端末の設定は以上です。
screenを実行している端末の設定
ここからは screen を実行している端末の設定です。ファイルの転送には Netcat を使用しますが、screen を実行しているサーバに導入されていない場合は別途導入するか別のコマンドを用意してください。ネットワーク転送コマンドの準備ができたら、リモートフォワードの確認として対象サーバに ssh 接続して「事前共有キーありの場合」で実行したコマンドを実行します。
example.com % (echo change_on_install; echo $LANG; date) | nc -w1 localhost 52224
2011/04/03 16:48:45 ClipboardTextListener[16216]: (127.0.0.1:52106) *** RECEIVE TEXT *** 50 (Encoding: euc-jp -> shiftjis) ja_JP.EUC-JP 2011ǯ 4?? 3?? ?????? 16:48:42 JSTこのツール出力例では日本語文字列が化けていますが、Mac OS X で Carbon Emacs の scratch バッファに貼り付けたデータは次のように変換されています。
ja_JP.EUC-JP 2011年 4月 3日 日曜日 16:48:42 JST
つぎに事前共有キーを記述したファイルを用意します。サーバ上の他人が読めないように適切な場所、パーミッションを設定してください。
example.com % echo change_on_install > ~/.exchange.key example.com % chmod 0600 !$ chmod 0600 ~/.exchange.key最後に .screenrc の設定です。ここまでコマンドラインで実行していたことを GNU Screen で行えるようにします。折り返して表示されているかもしれませんが、実際は
bufferfile
と bind
で始まる 2行です。
bufferfile 'exchange-file' bind ^] eval 'writebuf' 'exec sh -c "cat .exchange.key exchange-file | nc -w1 localhost 52224"' 'echo "paste to remote"'
- ペーストバッファの入出力ファイルを(screen を起動したディレクトリ配下の)exchange-file と定義
Ctrl-]
をリモート貼り付けコマンドとして次の処理を実行するよう定義- ペーストバッファの内容を
bufferfile
で指定したファイルに出力(writebuf
) - 事前共有キーファイルと
bufferfile
を cat して nc するコマンドを実行(exec
) - 実行したことが分かるようにステータスラインにメッセージを出力(
echo
)
- ペーストバッファの内容を
bufferfile
の場所、Netcat で使用するポート番号などは使用する環境に合わせて変更してください。設定の変更を反映させるため source
コマンドで .screenrc を再読み込みさせるか、screen を再起動してください。
長くなりましたが、ここまでの設定を終えると ssh 接続先 screen のペーストバッファを Ctrl-a
Ctrl-]
で nc コマンドと ssh トンネルを通じてクリップボードに貼り付け出来るようになります。
おわりに
.screenrc に定義するリモート貼り付けコマンドは、あえてデフォルトのペーストバッファ貼り付けコマンド ]
に類似した Ctrl-]
に割り当てています。これによりローカル、リモートをそれほど意識することなく GNU Screen のペーストバッファを利用できるようになりました。そしてツールの動作を通じて、久しぶりにパイプと ssh 転送の便利さを実感しました。
私は Mac OS X、Windows、Linux 問わずローカルでも GNU Screen を利用していますので、今回用意したツールを backtick
コマンドとして実行しています。とはいえ、このためだけにツール実行環境を用意するのが難しい場面もあるかもしれません。その場合の代案は今のところありません。とりあえず私の環境ではこうすることで出来ましたよということで参考情報として受け取っていただければ幸いです。
いまのところそこまでの欲求がないので試していませんが、この考え方を screen の zmodem
などと組み合わせれば、ssh 先 screen で操作しているサーバ上の任意のバイナリもローカルに転送できるはずです。以下の記事は大変参考になります。
2011/04/24追記
先に紹介したツールを使用していると、クリップボードへの書き込みが完了するよりも前に OS 上のペーストコマンドを実行してしまい悲しい思いをすることが多くなりました。それからは backtick
で動作させるのではなく、ひとつのウィンドウで動かしてその画面出力を見てコピーの完了を確認するという面倒なことをしていました。それもどうかなぁと思っていたところ、以下の記事を見かけました。
0 件のコメント:
コメントを投稿