Wyślij polecenie na odłączony ekran i uzyskaj wynik

12

Szukałem sposobu na wysłanie polecenia do odłączonej sesji ekranowej. Jak na razie dobrze. Oto co wymyśliłem:

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

To polecenie działa tak, jak powinno. Ale chciałbym też, żeby wynik był z niego odbity echem prosto przed moimi oczami (nie potrzebuję .logpliku ani czegoś takiego, chcę tylko wynik).

Użycie screen -Lpolecenia nie jest opcją.

Rudzik
źródło
Dlaczego tak musi być screen? Czy nie po to są tworzone procesy potomne?
Anko

Odpowiedzi:

10

Użyj rury „pierwszy na wejściu”:

mkfifo /tmp/test

Użyj operatora przekierowania. Przekieruj dane wyjściowe polecenia do / tmp / test, na przykład w następujący sposób:

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

Następnie w innej powłoce

tail -f /tmp/test.

Pamiętaj, że możesz również przekierowywać komunikaty o błędach za pomocą operatora 2> i 1 .

Przykład

Zgodnie z żądaniem w komentarzach, załóżmy, że mamy skrypt php akceptujący dane wejściowe użytkownika i drukujący obciążenie serwera na wejściu „status”:

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

Tworzysz dwa fifos:

 # mkfifo /tmp/fifoin /tmp/fifoout

Dzwonisz na ekran:

screen

W innej konsoli nazwijmy ją konsolą 2, w której znajdziesz nazwę swojego ekranu:

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

W konsoli 2 wysyłasz polecenie na ekran:

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

polecenie pojawi się na ekranie. Teraz w konsoli 2 możesz wysyłać polecenia do procesu php:

echo "status" >/tmp/fifoin

i czytaj z niego:

# cat /tmp/fifoout
load is stub
Thorsten Staerk
źródło
1
Przepraszam, ale to nie działa. Jeśli wysyłam polecenie na ekran, takie jak „polecenie> / tmp / test”, proces musi obsługiwać składnię> / tmp / test ... I tak nie jest.
Robin
Dla mnie to działa, pamiętaj, że jako nazwę twojego ekranu wpisuję „test”. Możesz sprawdzić nazwę swojego ekranu za pomocą polecenia screen -ls. Także „polecenie” powinno zostać zastąpione przez twoje aktualne polecenie, przetestowałem poleceniem ls. Testowałem również z powłoką bash.
Thorsten Staerk
Wiem to. I to nie działa. Na przykład uruchom skrypt PHP w oknie ekranowym, które na przykład odpowiada na polecenie „status”, które zwraca na przykład bieżące obciążenie serwera. Właśnie to próbuję zrobić.
Robin
wtedy będziesz potrzebował rur dwukierunkowych, dodaję to do mojej odpowiedzi
Thorsten Staerk
6

Mam skrypt w języku Python, który śledzi wiele odłączonych sesji ekranowych i przechwytuje dane wyjściowe z każdej z nich (gdy polecenia użycia, takie jak free, top -bn2, iostat, są okresowo wysyłane przez „rzeczy”).

Zamiast przekierowywać do pliku, a tym samym zarządzać co najmniej jednym plikiem dla każdej odłączonej sesji ekranowej ... Po prostu przekierowuję do dowolnego tty / pts, którego używa moja sesja nadrzędna.

Krok # 1: Rozpocznij nową sesję ekranu (z czytelną dla człowieka nazwą) w trybie odłączonym.

$ screen -dmS chad 

Krok # 2: Wyślij swoje polecenia (użyję polecenia „free -g” wraz z „uname -r”) za pośrednictwem różnych rzeczy. Ważne jest, aby określić okno, którego chcesz użyć (w naszym przypadku pierwsze i jedyne okno) za pomocą -p.

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

Krok # 3: Powyższy krok wysyła tylko tekst polecenia. Musimy również wysłać powrót karetki do tej odłączonej sesji ekranu, aby powłoka wykonała nasze polecenie. Znak ASCII 015 jest znakiem powrotu karetki w większości systemów * nix.

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

Krok # 4: Przekieruj wyjście z naszej odłączonej sesji ekranu do naszego obecnego tty / pts:

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

Wynik kroku 4 będzie wyglądał mniej więcej tak:

$ 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

Chociaż wydaje się to trochę skomplikowane, proces ten można łatwo wykonać za pomocą skryptów. Za pomocą Pythona mogę analizować dane wyjściowe z kroku 4 i przechwytywać tylko te dane, na których mi zależy.

Wybierając prosty scenariusz, na przykład zbieranie szczegółów adresu IP, napisałem przykładowy skrypt, aby zademonstrować powyższe pojęcia. Zapraszam do wymiany i majsterkowania, kiedy uznasz to za stosowne.

Przykładowy skrypt Pythona, aby uzyskać szczegóły IP z odłączonej sesji ekranu:

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

Powyższy skrypt w akcji:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
chad_walker
źródło
Podoba mi się ta odpowiedź o wiele lepiej niż zaakceptowana, ponieważ nie polega ona na tym, że ekran jest w stanie „powłoki zachęty”, ale działa z wszystkim, co działa na tym ekranie.
Guntram Blohm obsługuje Monikę
Wymaga to jednak dopasowania obrazu na ekranie. Znalazłem screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offpracować jeszcze lepiej w tym scenariuszu.
Guntram Blohm obsługuje Monikę
-1
screen -S myscreen

screen -R myscreen -X exec command

Przykład:

screen -R myscreen -X exec top
aod
źródło