Befehl an getrennten Bildschirm senden und Ausgabe erhalten

12

Ich habe nach einer Möglichkeit gesucht, einen Befehl an eine getrennte Bildschirmsitzung zu senden. So weit, ist es gut. Das habe ich mir ausgedacht:

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

Dieser Befehl funktioniert wie es sollte. Aber ich möchte auch die Ausgabe, die direkt vor meinen Augen wiedergegeben wird (keine .logDatei oder ähnliches, ich möchte nur die Ausgabe).

Die Verwendung des screen -LBefehls ist keine Option.

Robin
quelle
Warum muss es sein screen? Ist das nicht das, wofür untergeordnete Prozesse gemacht sind?
Anko

Antworten:

10

Verwenden Sie ein First-In-First-Out-Rohr:

mkfifo /tmp/test

Verwenden Sie einen Umleitungsoperator. Leiten Sie die Ausgabe des Befehls wie folgt nach / tmp / test um:

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

Dann in einer anderen Schale

tail -f /tmp/test.

Beachten Sie, dass Sie Fehlermeldungen möglicherweise auch mit dem Operator 2> & 1 umleiten möchten .

Beispiel

Wie in den Kommentaren gefordert, nehmen wir an, wir haben ein PHP-Skript, das Benutzereingaben akzeptiert und die Serverlast bei der Eingabe von "status" ausgibt:

# 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);
?>

Sie erstellen zwei Fifos:

 # mkfifo /tmp/fifoin /tmp/fifoout

Sie rufen einen Bildschirm auf:

screen

Nennen wir es in einer anderen Konsole Konsole 2, um den Namen Ihres Bildschirms herauszufinden:

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

In Konsole 2 senden Sie den Befehl an den Bildschirm:

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

Sie sehen den Befehl auf dem Bildschirm. Jetzt in Konsole 2 können Sie Befehle an Ihren PHP-Prozess senden:

echo "status" >/tmp/fifoin

und lies daraus:

# cat /tmp/fifoout
load is stub
Thorsten Staerk
quelle
1
Entschuldigung, aber das funktioniert nicht. Wenn ich einen Befehl wie 'command> / tmp / test' an den Bildschirm sende, muss der Prozess die Syntax> / tmp / test unterstützen ... und das tut er nicht.
Robin
Bei mir funktioniert es, bitte beachte, dass ich "test" als den Namen deines Bildschirms angegeben habe. Sie können den Namen Ihres Bildschirms mit dem Befehl screen -ls herausfinden. Außerdem sollte "Befehl" durch Ihren tatsächlichen Befehl ersetzt werden, den ich mit dem Befehl ls getestet habe. Außerdem habe ich mit der Bash-Shell getestet.
Thorsten Staerk
Ich weiß das. Und es geht nicht. Starten Sie beispielsweise ein PHP-Skript in einem Bildschirmfenster, das beispielsweise auf einen Befehl "status" reagiert, der beispielsweise die aktuelle Serverlast zurückgibt. Das ist es, was ich versuche zu tun.
Robin
dann brauchst du bidirektionale rohre, das füge ich meiner antwort hinzu
thorsten
6

Ich habe ein Python-Skript, das zahlreiche getrennte Bildschirmsitzungen verfolgt und die Ausgabe von jeder erfasst (wenn Verwendungsbefehle wie free, top -bn2, iostat regelmäßig über 'stuff' gesendet werden).

Anstatt zu einer Datei umzuleiten und somit mindestens eine Datei pro getrennter Bildschirmsitzung zu verwalten, leite ich einfach zu den von meiner übergeordneten Sitzung verwendeten tty / pts um.

Schritt 1: Starten Sie eine neue Bildschirmsitzung (mit einem für Menschen lesbaren Namen) im getrennten Modus.

$ screen -dmS chad 

Schritt 2: Senden Sie Ihre Befehle (ich verwende den Befehl 'free -g' zusammen mit 'uname -r') über Zeug. Es ist wichtig, das zu verwendende Fenster (in unserem Fall das erste und einzige Fenster) mit -p anzugeben.

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

Schritt 3: Der obige Schritt sendet nur den Befehlstext. Wir müssen auch einen Wagenrücklauf an diese getrennte Bildschirmsitzung senden, damit die Shell unseren Befehl ausführt. Das ASCII-Zeichen 015 ist auf den meisten * nix-Systemen ein Wagenrücklauf.

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

Schritt 4: Leiten Sie die Ausgabe unserer getrennten Bildschirmsitzung auf unsere aktuellen tty / pts um:

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

Die Ausgabe von Schritt 4 sieht ungefähr so ​​aus:

$ 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

Obwohl dies ein bisschen kompliziert zu sein scheint, ist der Prozess leicht skriptfähig. Mit Python kann ich die Ausgabe von Schritt 4 analysieren und nur die Daten erfassen, die mir wichtig sind.

Ich entschied mich für ein einfaches Szenario wie das Abrufen von IP-Details und schrieb ein Beispielskript, um die obigen Konzepte zu demonstrieren. Fühlen Sie sich frei zu ersetzen und zu basteln, wie Sie es für richtig halten.

Beispiel eines Python-Skripts zum Abrufen von IP-Details aus einer getrennten Bildschirmsitzung:

#!/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()

Über dem Skript in Aktion:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
chad_walker
quelle
Diese Antwort gefällt mir viel besser als die akzeptierte, da sie nicht darauf beruht, dass sich der Bildschirm im Status "Shell-Eingabeaufforderung" befindet, sondern mit allem funktioniert, was auch immer auf diesem Bildschirm ausgeführt wird.
Guntram Blohm unterstützt Monica
Die Ausgabe muss jedoch auf den Bildschirm passen. Ich fand screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offin diesem Szenario noch besser zu arbeiten.
Guntram Blohm unterstützt Monica
-1
screen -S myscreen

screen -R myscreen -X exec command

Beispiel:

screen -R myscreen -X exec top
aod
quelle