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ą.


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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.