เขียนถึง stdin ของกระบวนการพื้นหลัง


25

ฉันอยู่ในกล่อง Ubuntu 10.04 และเริ่มเซิร์ฟเวอร์ในพื้นหลัง (myserver &) บน ssh มันทำงานได้ดี แต่ฉันต้องการวิธีที่จะได้รับที่ stdin ของเซิร์ฟเวอร์เป็นวิธีเดียวที่จะควบคุมเซิร์ฟเวอร์คือผ่านวิธีนี้

มีวิธีที่จะได้รับ stdin ของกระบวนการทำงานอยู่แล้วเพื่อให้ฉันสามารถเขียนถึงมัน (และหวังว่าจะอ่าน stdout) เห็นได้ชัดว่าถ้าฉันกำลังจะทำเช่นนี้ตอนนี้ฉันจะเริ่มต้นด้วย FIFO ที่เปลี่ยนเส้นทางไปยัง stdin แต่น่าเสียดายที่ตอนนี้ช้าไปหน่อย

ความคิดใด ๆ


คุณไม่สามารถนำมันกลับมาที่พื้นหน้าได้หรือไม่ ('งาน' จะแสดงรายการกระบวนการพื้นหลังปัจจุบันของคุณ 'fg $ X' จะนำงานกลับมาที่ส่วนหน้า ctrl + b จะหยุดงานชั่วคราวและกลับสู่เชลล์ของคุณในขณะที่ 'bg' จะดำเนินการกระบวนการที่หยุดชั่วคราวใน พื้นหลัง)
symcbean

คำตอบ:


10

คุณสามารถลองเขียนไปที่มันเป็น / proc pid ไดเรกทอรี สมมติว่า pem daemons ของคุณคือ 2000 ลองเขียนถึง / proc / 2000 / fd / 0


ขอบคุณ ... ฉันพบว่าหลังจากฉันโพสต์ข้อความนี้ (หลังจากผ่านไปหนึ่งวันโดยทั่วไป) ดูเหมือนว่าจะใช้งานได้ (เท่าการส่งข้อมูลไปยังโปรแกรม) น่าเสียดายที่โปรแกรมไม่ยอมรับคำสั่ง ฉันทดสอบว่าใช้เซิร์ฟเวอร์ในคอมพิวเตอร์ของฉันและเห็นว่าข้อมูลปรากฏ แต่โปรแกรมไม่รู้จักคำสั่ง ฉันต้องกด enter บนเทอร์มินัลเซิร์ฟเวอร์ด้วยตนเองแล้วมันก็แค่บอกว่าคำสั่งที่ไม่รู้จัก อาจจะมีความแปลกประหลาดของจาวาบ้างไหม? ฉันติดอยู่ ...
tajmorton

1
echo -e "something \ n"> / proc / 2000 / fd / 0 อย่างไร?
katriel

ที่จริงแล้วมันไม่ได้เป็นแบบ sworking เป็น / proc / <pid> / fd / 0 ชี้ไปที่ / dev / pts <บางหมายเลข> อย่างน้อยบางระบบ ...
bk138

คำตอบแรกสำหรับserverfault.com/questions/178457/…โปรดทราบว่าวิธีนี้ใช้ไม่ได้ผล
barrycarter

2
สิ่งนี้ใช้ไม่ได้จริง เชลล์ของคุณตามปกติ (เมื่อไม่มีการใช้ท่อหรือการเปลี่ยนเส้นทาง) เริ่มคำสั่งด้วยไฟล์ descriptors 0ผ่านการ2ตั้งค่าเป็นไฟล์เดียวกันซึ่งโดยปกติจะเป็นเทอร์มินัลเสมือน (คล้าย ๆ/dev/pty/...) คำสั่งจะอ่านจาก FD 0และเขียนไปยัง FD 1และ2สื่อสารกับเทอร์มินัลเสมือน (เช่นผ่าน SSH หรือโดยตรงกับเทอร์มินัลอีมูเลเตอร์ของคุณ) หากกระบวนการอื่นใดเข้าถึงไฟล์นั้น (เช่นผ่าน/proc) สิ่งเดียวกันจะเกิดขึ้นเช่นการเขียนลงไปยังเทอร์มินัลและไม่ใช่คำสั่ง
Feuermurmel

29

คุณสามารถเริ่มเซิร์ฟเวอร์ด้วยไพพ์ที่มีชื่อ (fifo) เป็นอินพุต:

mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &

cat > /tmp/srv-input &เป็นสิ่งสำคัญที่จะหลีกเลี่ยงเซิร์ฟเวอร์ของคุณจะได้รับ EOF อย่างน้อยหนึ่งกระบวนการต้องเปิดฟีเจอร์เป็นลายลักษณ์อักษรเพื่อให้เซิร์ฟเวอร์ของคุณไม่ได้รับ EOF PID ของคำสั่งนี้ถูกบันทึกไว้ใน/tmp/srv-input-cat-pidไฟล์เพื่อการฆ่าครั้งหลัง

ในกรณีของคุณที่คุณเริ่มเซิร์ฟเวอร์แล้วคุณต้องใช้ดีบักเกอร์เช่นgdbเพื่อแนบกับกระบวนการของคุณเพื่อเปลี่ยนเส้นทางstdinไปยัง Fifo:

gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)

จากนั้นทำบางสิ่งเช่นร้องเพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ของคุณ (ในหน้าต่างเทอร์มินัลอื่นหากจำเป็น):

echo "command" > /tmp/srv-input

เพื่อส่ง EOF ไปยังเซิร์ฟเวอร์ของคุณคุณจะต้องฆ่าcat > /tmp/srv-inputกระบวนการที่ PID /tmp/srv-input-cat-pid fileได้รับการบันทึกไว้ใน

ในกรณีของ GDB เพียงออกจาก GDB และ EOF จะถูกส่งไป


1
นี่เป็นวิธีการพกพาที่ดีกว่า @katriel เนื่องจาก / proc / 2000 / fd / 0 ไม่ใช่ stdin ในทุกระบบ
Prior99 99

เคล็ดลับด้วย "cat> / tmp / srv-input &" ช่วยให้ฉันปวดหัว ขอขอบคุณ!
Prior99 99

เกี่ยวกับ mkfifo /tmp/srv-input; tail -f /tmp/srv-input | myserver &อะไร นี้จะทำให้ท่อเปิดเช่นกัน ...
bk138

@ bk138: ดูเหมือนว่าฉันควรใช้หาง แต่มีวิธีเดียวเท่านั้นที่จะรู้แน่นอน: ทดสอบ
jfg956

tailใช้งานไม่ได้ แต่ต่อท้ายสิ่งนี้เพื่อให้งานเสร็จสิ้น: cat /tmp/srv-input | myserver; kill -9 cat / tmp / srv-input-cat-pid` &&rm / tmp / srv-input-cat * `
Thiago Macedo

4

เช่นเดียวกับข้างต้น แต่ 'cat' ไม่ได้ผลสำหรับฉัน ไฟล์มี EOF และสิ้นสุดลงหลังจากส่งคำสั่งเดียว

สิ่งนี้ใช้ได้กับฉัน:

#!/bin/bash

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