web-dev-qa-db-ja.com

切り離された画面にコマンドを送信して出力を取得する

私は、切り離された画面セッションにコマンドを送信する方法を見つけるために検索してきました。ここまでは順調ですね。これは私が思いついたものです:

$ screen -S test -p 0 -X stuff 'command\n'

このコマンドは正常に機能します。しかし、私もそこからの出力を望んでいます。目の前に直接エコーします(.logファイルなどは必要ありません。出力が必要です)。

screen -Lコマンドの使用はオプションではありません。

12
Robin

先入れ先出しのパイプを使用します。

mkfifo /tmp/test

リダイレクト演算子を使用します。たとえば次のように、コマンドの出力を/ tmp/testにリダイレクトします。

screen -S test -p 0 -X stuff 'command >/tmp/test\n'

その後、別のシェルで

tail -f /tmp/test.

2>&1演算子 を使用してエラーメッセージをリダイレクトすることもできます。

コメントで要求されているように、ユーザー入力を受け入れ、「ステータス」の入力にサーバー負荷を出力するphpスクリプトがあるとします。

# cat test.php
<?php
  $fp=fopen("php://stdin","r");
  while($line=stream_get_line($fp,65535,"\n")) 
  {
    if ($line=="status") {echo "load is stub";} 
  } 
  fclose($fp);
?>

2つのfifoを作成します。

 # mkfifo /tmp/fifoin /tmp/fifoout

画面を呼び出す:

screen

別のコンソールで、画面の名前がわかるコンソール2と呼びましょう。

# screen -ls
There is a screen on:
        8023.pts-3.tweedleburg  (Attached)
1 Socket in /var/run/screens/S-root.

コンソール2で、コマンドを画面に送信します。

 # screen -S 8023.pts-3.tweedleburg -p 0 -X stuff 'php test.php </tmp/fifoin >/tmp/fifoout\n'

画面にコマンドが表示されます。コンソール2で、phpプロセスにコマンドを送信できます。

echo "status" >/tmp/fifoin

そしてそれから読んでください:

# cat /tmp/fifoout
load is stub
10
Thorsten Staerk

私はpythonスクリプトを使用して、多数の切り離されたスクリーンセッションを追跡し、それぞれからの出力をキャプチャします(freeのような使用率コマンドを使用した場合、free、top -bn2、iostat 'stuff'を介して定期的に送信されます)。

ファイルにリダイレクトする代わりに、切り離されたスクリーンセッションごとに少なくとも1つのファイルを管理する代わりに...親のtty/ptsにリダイレクトするだけですセッションが使用しています。

ステップ#1:デタッチモードで新しい画面セッションを(人間が読める名前で)開始します。

$ screen -dmS chad 

ステップ#2:コマンドを介してコマンドを送信します( 'free -g'コマンドと 'uname -r'を併用します)。 -pを使用して、使用するウィンドウ(この場合は、最初で唯一のウィンドウ)を指定することが重要です。

$ screen -r chad -p0 -X stuff "free -g; uname -r" 

ステップ#3:上記のステップでは、コマンドテキストのみが送信されます。また、シェルにコマンドを実行させるには、この切り離されたスクリーンセッションにキャリッジリターンを送信する必要があります。 ASCII文字015は、ほとんどの* nixシステムではキャリッジリターンです。

$ screen -r chad -p0 -X eval "stuff \015"

ステップ#4:デタッチされたスクリーンセッションの出力を現在のtty/ptsにリダイレクトします。

$ screen -r chad -p0 -X hardcopy $(tty)

ステップ#4の出力は次のようになります:

$ free -g; uname -r
             total       used       free     shared    buffers     cached
Mem:             7          1          6          0          0          0
-/+ buffers/cache:          0          7
Swap:            1          0          1
2.6.32-358.el6.x86_64

これは少し複雑に見えますが、プロセスは簡単にスクリプト化できます。 Pythonを使用すると、ステップ4の出力を解析して、気になるデータのみをキャプチャできます。

IPの詳細を取得するような単純なシナリオを選択して、上記の概念を説明するためのサンプルスクリプトを書きました。必要に応じて、交換したり、いじったりしてください。

例pythonデタッチスクリーンセッションからIP詳細を取得するスクリプト:

#!/usr/bin/python

import pexpect, time

#spawn a new bash session
session = pexpect.spawn('/bin/bash')
#send screen commands
session.sendline('screen -dmS netIP')
session.sendline('screen -r netIP -p0 -X stuff "ifconfig eth0 | grep -v eth0 | head -1"')
session.sendline('screen -r netIP -p0 -X eval "stuff \\015"')
#give the command a chance to execute before reading the output of our detached screen
time.sleep(0.1)

#use the output of the uname command as our string to expect
session.sendline('screen -r netIP -p0 -X hardcopy $(tty); $(uname)')
session.expect('Linux')

#parse the output - only concerned with the 'inet' line
output = session.before.split('\n')
for o in output:
    if 'inet' in o:
        print o

#kill the screen
session.sendline('screen -r netIP -p0 -X quit')
time.sleep(0.1)

session.close()

上記のスクリプトを実行中:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
6
chad_walker