Ayrılmış ekrana komut gönder ve çıktıyı al


12

Müstakil bir ekran oturumuna komut göndermenin bir yolunu bulmaya çalışıyordum. Çok uzak çok iyi. Ben geldim budur:

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

Bu komut olması gerektiği gibi çalışır. Ama ben de çıktıyı istiyorum, gözlerimin önünde yankılandı (bir .logdosyaya ya da başka bir şeye gerek yok , sadece çıktıyı istiyorum).

screen -LKomutu kullanmak bir seçenek değildir.


Neden olmak zorunda screen? Çocuk süreçleri bunun için yapılmadı mı?
Anko

Yanıtlar:


10

İlk giren ilk çıkar borusunu kullanın:

mkfifo /tmp/test

Bir yönlendirme operatörü kullanın. Komutun çıktısını / tmp / test'e örneğin şöyle yönlendirin:

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

Sonra başka bir kabukta

tail -f /tmp/test.

Ayrıca 2> & 1 operatörünü kullanarak hata mesajlarını yeniden yönlendirmek isteyebilirsiniz .

Misal

Yorumlarda istendiği gibi, kullanıcı girişini kabul eden ve "status" girişine sunucu yükünü yazdıran bir php betiğimiz olduğunu varsayalım:

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

İki beşo oluşturursunuz:

 # mkfifo /tmp/fifoin /tmp/fifoout

Bir ekranı çağırıyorsunuz:

screen

Başka bir konsolda, ekranınızın adını bulacağınız konsol 2 diyelim:

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

Konsol 2'de komutu ekrana gönderirsiniz:

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

ekranda komutun göründüğünü görürsünüz. Artık konsol 2'de php işleminize komutlar gönderebilirsiniz:

echo "status" >/tmp/fifoin

ve ondan okuyun:

# cat /tmp/fifoout
load is stub

1
Üzgünüm, ama bu işe yaramıyor. Eğer cama 'command> / tmp / test' gibi bir komut gönderiyorsam, işlem> / tmp / test sözdizimini desteklemelidir ... Ve desteklemiyor.
Robin

Benim için çalışıyor, lütfen ekranınızın adı olarak "test" koyduğumu unutmayın. Ekranınızın adını -ls komut ekranı ile öğrenebilirsiniz. Ayrıca, "komut" gerçek komut ile değiştirilmesi gerekir, ben ls komutu ile test. Ayrıca, bash kabuğu ile test ettim.
Thorsten Staerk

Bunu biliyorum. Ve işe yaramıyor. Örneğin, ekran penceresinde bir PHP komut dosyası başlatın, örneğin, geçerli sunucu yükünü döndüren bir "durum" komutuna yanıt verir. Ben de bunu yapmaya çalışıyorum.
Robin

o zaman çift yönlü borulara ihtiyacınız olacak, bunu
cevabıma

6

Ben çok sayıda müstakil ekran oturumları izler ve her çıkış çıktıları ( ücretsiz, top -bn2, iostat gibi periyodik 'şeyler' yoluyla gönderilir) yakalar bir python komut dosyası var .

Bir dosyaya yönlendirme yapmak ve bu nedenle, ayrı ekran oturumu başına en az bir dosya yönetmek yerine ... Üst oturumumun kullandığı tty / pts'ye yönlendiriyorum.

Adım # 1: Ayrı modda yeni bir ekran oturumu başlatın (insan tarafından okunabilir bir adla).

$ screen -dmS chad 

Adım # 2: Komutlarınızı gönderin ('free -g' komutunu 'uname -r' ile birlikte kullanacağım). -P ile kullanmak istediğiniz pencereyi (bizim durumumuzda, ilk ve tek pencere) belirtmek önemlidir.

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

Adım # 3: Yukarıdaki adım sadece komut metnini gönderir. Kabuğun komutumuzu yürütmesi için bu ayrılmış ekran oturumuna bir satır başı göndermemiz de gerekir. ASCII karakteri 015, çoğu * nix sistemde satır başıdır.

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

Adım # 4: Ayrılmış ekran oturumumuzun çıktısını mevcut tty / puanlarımıza yeniden yönlendirin:

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

Adım # 4'ün çıktısı şöyle görünecektir:

$ 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

Bu biraz dahil gibi görünse de, süreç kolayca yazılabilir. Python ile Adım # 4'ün çıktısını ayrıştırabilir ve yalnızca önem verdiğim verileri yakalayabilirim.

IP detaylarını yakalamak gibi basit bir senaryo seçerken, yukarıdaki kavramları göstermek için örnek bir senaryo yazdım. Uygun gördüğünüz gibi değiştirin ve tamir edin.

Ayrılmış ekran oturumundan IP ayrıntılarını almak için örnek python betiği:

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

Uygulamadaki komut dosyasının üstünde:

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

Bu cevabı kabul edilenden çok daha iyi seviyorum, çünkü ekrana "kabuk istemi" durumunda olmuyor, ancak o ekranda çalışanlarla da çalışıyor.
Guntram Blohm,

Ancak, çıktıyı ekrana sığması için gerektirir. Buldum screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offbu senaryoda daha iyi çalışmak.
Guntram Blohm,

-1
screen -S myscreen

screen -R myscreen -X exec command

Misal:

screen -R myscreen -X exec top
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.