pbcopy が動かない…動かない…と呪詛のように呟きつつ連休が終わりそうです。こんな悲しい週末があって良いのか。
このような悲劇が二度と起こらないよう、調べたことをまとめておきます。
問題
pbcopy、pbpaste も含めて、tmux セッションの下で実行すると、何をしても終了コード 1 で異常終了するという憂き目に遭っています。
# tmux セッション配下。標準入力無しで実行すると… $ pbcopy $ echo $? 1 # ウワッ、終了コード 1 … # tmux セッション配下。パイプ経由で標準入力に流し込んで実行しても… $ ls | pbcopy $ echo $? 1 # ウワッ、また終了コード 1 … $ pbpaste $ # もちろん何もペーストボードに入っていない…
解決策
1. reattach-to-user-namespace をインストールする
$ brew install reattach-to-user-namespace
2. .tmux.conf の冒頭に以下の設定を記述する
# お好みのシェルを指定してください。そのシェル環境で pbcopy とかが実行されます。 set-option -g default-command "reattach-to-user-namespace -l zsh"
3. tmux サーバを殺せ!
$ tmux kill-server
4. この後 tmux を再起動させると、pbcopy, pbpaste が使用できるようになります。
$ tmux $ ls | head -2 | pbcopy $ pbpaste Desktop Documents
何が悪かったのか
namespace
pbcopy/pbpaste は、その性質上、当然ながらペーストボードへのアクセスが必要です。
Mac OS X では、このあたりのアクセスを namespace と呼ばれるものによって制御しています。namespace は階層構造を持っていて、上位にある namespace は下位にある namespace で動いているサービスにアクセスが可能です。一方、逆はできません。
階層構造はだいたいこんな感じっぽくて、ペーストボードのサービスは、per-user bootstrap namespace に所属しています。
- global bootstrap namespace (1つだけ作成される)
- per-user bootstrap namespace (システム上のユーザ毎に作成される)
- per-session bootstrap namespace (各ログインセッションで作成される)
- per-user bootstrap namespace (システム上のユーザ毎に作成される)
tmux がペーストボードにアクセスできない
tmux はクライアントサーバモデルを採るソフトウェアであり、サーバは daemon(3) によって起動されます。で、どうも Mac OS X 10.5 から daemon(3) の仕様が変わったらしく、サーバが所属する namespace を root の namespace (その語感とは逆に下位の namespace らしい) に置くようになったのだとか。
そういうわけで、tmux からは、上位の namespace に所属しているペーストボードにアクセスできなくなった、というのが問題だった模様。
解決策がやっていること
reattach-to-user-namespace
問題を解決するために、tmux 上におけるコマンド実行の度に、ラッパプログラム (reattach-to-user-namespace) を実行することで per-user namespace に再接続を行うようにしています。
誤解させたくないのですが、tmux サーバを per-user namespace に接続させているわけではなく、あくまでコマンドを実行するランタイム上で再接続を行ってます。このあたりは reattach-to-user-namespace.c のソースを見てください。
また、これが tmux に本体に取り込まれていないのは、再接続は Apple の非公開 API で実施しているので、tmux の方にマージするわけにもいかないというのが理由です。そのため、ラッパプログラムでの回避、という方針になったわけですね。
tmux.conf に以下の設定を記述することで、
set-option -g default-command "reattach-to-user-namespace -l zsh"
外部プログラムを呼び出す際に、必ず reattach-to-user-namespace で user-namespace に接続済の環境でプログラムを実行できるようになります。
ということが ここ に書いてあるので読むといいとおもいます。