ส่งคำสั่งไปที่หน้าจอเดี่ยวออกและรับเอาต์พุต


12

ฉันค้นหาเพื่อหาวิธีส่งคำสั่งไปยังหน้าจอที่แยกออก จนถึงตอนนี้ดีมาก นี่คือสิ่งที่ฉันเกิดขึ้นกับ:

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

คำสั่งนี้ทำงานตามที่ควรจะเป็น แต่ฉันก็ต้องการเอาท์พุทจากมันด้วยเช่นกันสะท้อนต่อหน้าต่อตาของฉัน (ไม่ต้องการ.logไฟล์หรืออะไรสักอย่างฉันแค่ต้องการเอาท์พุท)

การใช้screen -Lคำสั่งไม่ใช่ตัวเลือก


ทำไมถึงต้องเป็นscreen? นี่ไม่ใช่สิ่งที่กระบวนการลูกทำขึ้นมาเพื่อ?
Anko

คำตอบ:


10

ใช้ท่อเข้าก่อนออกก่อน:

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

คุณสร้างสอง fifos:

 # 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

1
ขออภัย แต่มันใช้ไม่ได้ หากฉันกำลังส่งคำสั่งไปยัง creen เช่น 'command> / tmp / test' กระบวนการจะต้องสนับสนุนไวยากรณ์> / tmp / test ... และมันก็ไม่ได้
Robin

สำหรับฉันมันใช้งานได้โปรดทราบว่าฉันใส่ "ทดสอบ" เป็นชื่อหน้าจอของคุณ คุณสามารถค้นหาชื่อของหน้าจอของคุณด้วยหน้าจอคำสั่ง -ls นอกจากนี้ "command" ควรถูกแทนที่ด้วยคำสั่งจริงของคุณฉันทดสอบกับคำสั่ง ls นอกจากนี้ฉันทดสอบด้วยเปลือกทุบตี
Thorsten Staerk

ฉันรู้แล้ว. และมันไม่ทำงาน ตัวอย่างเช่นเริ่มสคริปต์ PHP ในหน้าต่างหน้าจอซึ่งตัวอย่างเช่นตอบกลับไปยังคำสั่ง "สถานะ" ซึ่งจะส่งคืนโหลดเซิร์ฟเวอร์ปัจจุบันตัวอย่างเช่น นั่นคือสิ่งที่ฉันพยายามจะทำ
Robin

จากนั้นคุณจะต้องใช้ท่อแบบสองทิศทางฉันเพิ่มคำตอบของฉัน
Thorsten Staerk

6

ฉันมีสคริปต์ไพ ธ อนที่ติดตามเซสชันหน้าจอที่แยกออกมาจำนวนมากและจับเอาท์พุทจากแต่ละรายการ (เมื่อคำสั่งการใช้ประโยชน์เช่นฟรี, -bn2 ด้านบน, iostatจะถูกส่งเป็นระยะ ๆ ผ่าน 'เนื้อหา')

แทนที่จะเปลี่ยนเส้นทางไปยังไฟล์และดังนั้นการจัดการอย่างน้อยหนึ่งไฟล์ต่อเซสชันหน้าจอที่แยกออก ... ฉันเพียงแค่เปลี่ยนเส้นทางไปยังสิ่งที่ tty / pts เซสชันแม่ของฉันใช้

ขั้นตอนที่ 1:เริ่มเซสชันหน้าจอใหม่ (ด้วยชื่อที่มนุษย์สามารถอ่านได้) ในโหมดเดี่ยว

$ screen -dmS chad 

ขั้นตอนที่ # 2:ส่งคำสั่งของคุณ (ฉันจะใช้คำสั่ง 'free -g' พร้อมกับ 'uname -r') ผ่านทางสิ่งต่าง ๆ เป็นสิ่งสำคัญที่จะต้องระบุหน้าต่างที่คุณต้องการใช้ (ในกรณีของเราหน้าต่างแรกและหน้าต่างเดียว) ด้วย -p

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

ขั้นตอนที่ # 3:ขั้นตอนข้างต้นส่งข้อความคำสั่งเท่านั้น เราต้องส่ง carriage return ไปยังเซสชันหน้าจอที่แยกออกนี้เพื่อให้เชลล์ดำเนินการคำสั่งของเรา อักขระ ASCII 015 คือ carriage return บนระบบ * 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

แม้ว่านี่จะดูค่อนข้างเกี่ยวข้องกับกระบวนการ แต่ก็สามารถสคริปต์ได้อย่างง่ายดาย ด้วยไพ ธ อนฉันสามารถแยกวิเคราะห์ผลลัพธ์ของขั้นตอนที่ # 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

ฉันชอบคำตอบนี้ดีกว่าที่ยอมรับเพราะมันไม่ได้ขึ้นอยู่กับหน้าจอที่อยู่ในสถานะ "shell prompt" แต่ทำงานกับสิ่งที่กำลังทำงานในหน้าจอนั้นได้เช่นกัน
Guntram Blohm สนับสนุน Monica

อย่างไรก็ตามมันต้องการการแสดงผลเพื่อให้พอดีกับหน้าจอ ฉันพบscreen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offทำงานได้ดียิ่งขึ้นในสถานการณ์นั้น
Guntram Blohm สนับสนุนโมนิก้า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.