以前、GNU screenでレイアウトの整理
を作ってた時に、screen内の情報(どのlayoutが存在してるか、等)
情報を拾ってこれたらな、と思ってました。
screen -Qコマンドとかにはかなり制限があって直接上手く取れませんでしたが、
screen -Q lastmsgを使うことで簡単にとれたので、その方法について、
と使ってみての問題点について。
screen -Q
screen -Qに引き続いてscreenコマンドを打つと、
その返り値をシェル側に返してくれます。
ただ、すべてのコマンドが使えるわけではなくて、次のコマンドのみ。
echo
info
lastmsg
number
select
time
title
windows
このうち、windowsなんかは、実際にscreen内で使ってステータスラインに表示される
ものとは若干違います
1。
screen -Q windowsなどを上手く使えば何番のwindowが現在存在するのか、
等は分かりますが、layoutに関しては情報が直接取れません。
screen -Q lastmsg
そこで、lastmsgを使います。
lastmsgは最後にステータスラインに表示されたものを再表示するものですが、
これをscreen -Qからやることで
screen内でステータスラインに表示できるすべての情報を取ってくることが出来ます。
screen内には、コマンドラインからでも
screen -Xを使ってコマンドを送ることができるので
(-Xの場合は直接コマンドを送るだけなのでコマンドに制限なし)、
$ screen -X layout show
$ screen -Q lastmsg
0 only  1* 4-windows  2 4-windows_2  3 3-win_1-top  4 3-win_1-left  5 monitor(-_-) $
こんな感じでlayoutの情報を取ってくることが出来ます。
さらに、screen内のコマンドの中でもこれは有効です。
screen内ではsetenvコマンドで変数を使う事は出来るのですが、
シェルみたいにコマンド結果を収納したりは出来ないので
例えばlayout showの結果に続いて何か表示させたいとかは出来ません。
これを、一旦外のシェルコマンドを通すことで可能に出来ます。
bind a eval 'exec /bin/sh -c "screen -X echo \"$(screen -X layout show && screen -Q lastmsg), n: next, p: prev, i: init\""'
$()内のscreen -Xでステータスラインに情報を表示させてをれをscreen -Q lastmsgで返し、
さらにそれをscreen -X echoコマンドに渡すことでscreenのステータスラインに
最終的な表示をさせます。
それをexec /bin/sh -c "..."を使ってキーバインドに渡します。
追記: 2014/05/25
evalが抜けてたので加えてexec...周りを'で囲ってます。
追記ここまで
こんな感じでキーバインドを.screenrcでしてあげれば、
screen内の情報を含めた複雑なメッセージもステータスラインに表示することが可能です。
問題点
と、結構良い感じで使える様になるな、と思ってたんですが、 色々アップデートして試してたら結構な率でクラッシュする様になってしまいました。
現象としては、
- 
    連続して短い間隔で screen -Qを含むキーバインドを使うとFilter running: … /bin/bash …. みたいなメッセージがステータスラインに表示され、どうやら新しいコマンドが実行されなくなる。 (このコマンドがスタックしている。 この時、 /tmp/uscreens/S-USER/xxxxx.ttys002.yyy: connect: Connection refusedみたいにターミナルの情報に繋げられない、という様なメッセージがコマンドライン側に出ることも。 
- 
    また、 screen -Qを含むキーバインドを使った後、その時いたウィンドウで コマンドを打ってEnterを押しても実行されない(次の行に行くだけ)みたいになることも。 他のウィンドウからscreen -lsしてみると$ screen -ls There are screens on: xxxxx.ttys002.yyy (Attached) xxxxx.ttys002.yyy-queryA (Detached) 2 Sockets in /tmp/uscreens/S-USER.みたいな感じで queryAというセッションができていて(xxxxxの番号はその上のものと一緒)Detachedになっている。この時、Enterを押しても実行されない。 ウィンドウからCmd-cを送ると ウィンドウ内は動くようになりますが、上の DetachedだったものがDead???状態になる。。 この時に、ps -u$USER|grep screenとかで見てみると、screen -Q関連の コマンドが残ってたりする。 なので、単にscreen -wipeしただけではダメで変なプロセスが残っていって しまう可能性もある。
man screenを見てみると
  -Q   Some commands now can be queried from a remote session using  this
        flag,  e.g.  "screen  -Q  windows".  The  commands  will  send the
        response to the stdout of the querying process. If  there  was  an
        error  in  the command, then the querying process will exit with a
        non-zero status.
となっていて、どうも中でquerying processを新たなセッション(元の子セッション?)として立ち上げる、
みたいなことをしてるみたいです。
これが結構負荷が大きいようで繰り返し行うと詰まってしまう様です。
さらに、これがWindowsのCygwin上だと
コマンドラインからでもscreen -Qを押した瞬間に固まり、
そのディレクトリにbash.exe.stackdumpというファイルが出来てたりすることがありました。
キーバインドに入れておいた場合も、一回目でも
Filter running: … /bin/bash ….の表示が出て、
その時にbash.exe.stackdumpが出来ます。
multi_clipboard
を使ってる時もCygwinでこれが出てくることがあって、なんだろ、と思ってたんですが、
どうも中でscreen -Qを使ってたのが悪かった様です
2。
Windows Vista/7で、最新のscreenやapt-cyg
で取ってこれるCygwin用にビルドされたもの等試してみましたが、
試した限りではすべての環境でscreen -Q一発目でbsh.exe.stackdumpが出来て落ちました。
なのでCygwinではscreen -Qは全く使い物にならないです。
(どれも結構古いマシンなので、Cygwinでもスペックの高いPCで使えば使えるのかもしれませんが。。。)
いずれにしろ、手元のMacやLinuxでも、結構なスペックの中でも
連続して使うと
Filter running: … /bin/bash ….  
は出てスタックしてしまうのであまり使い勝手の良いものではありません。
ので、ここまで来てなんですが、
結論としてはscreen -X <cmd> & screen -Q lastmsg
の方法は(といよりscreen -Q自体)
使わない方が良さそうです。
- 
screen内では This is window 0 (xxx).みたいな感じで、コマンドラインから screen -Q numberとすると、0 (xxx)みたいに名前とcaptionだけが出ます。 (この表示はステータスラインにも表示される。) ↩ 
- 
Cygwin以外でも余りよろしく無い様なので、multi_clipboard に関しては screen -Qでscreen内に変数を保持しておくのをやめました。 (外部ファイルに書いて読む、みたいなことをしてちょっと不格好ですが、 こちらの方なら安定して動くので。)
