ฉันจะแนบเทอร์มินัลเข้ากับกระบวนการที่แยกออกได้อย่างไร


99

ฉันได้แยกกระบวนการออกจากเทอร์มินัลของฉันเช่นนี้

$ process &

เทอร์มินัลนั้นปิดตัวไปนาน แต่processยังคงทำงานอยู่และฉันต้องการส่งคำสั่งบางอย่างไปยัง stdin ของกระบวนการนั้น เป็นไปได้ไหม



1
ค้นหาretty, neercsฯลฯ และยังเห็นserverfault.com/questions/24425 , serverfault.com/questions/115998
กิลส์

คำตอบ:


112

ใช่แล้ว. mkfifo /tmp/fifoขั้นแรกให้สร้างท่อ: ใช้ gdb เพื่อแนบกับกระบวนการ: gdb -p PID

แล้วปิด stdin: call close (0); และเปิดอีกครั้ง:call open ("/tmp/fifo", 0600)

ในที่สุดให้เขียน (จากเทอร์มินัลอื่นเนื่องจาก gdb อาจค้าง):

echo blah > /tmp/fifo


6
ที่น่าประทับใจมาก!
Samuel Edwin Ward

1
ฉันสามารถทำสิ่งที่คล้ายกับกระบวนการเปลี่ยนเส้นทาง stdout ไปยังไฟล์ได้หรือไม่?
rustyx

@rustyx: ยังไม่ทดลอง แต่ควรทำงาน: touch /tmp/thefileสร้างไฟล์มากกว่าท่อ stdout เป็น 1 ดังนั้นcall close (1); call open ("/tmp/thefile", 0400)นอกจากนี้ยังใช้สิทธิ์ที่ถูกต้องสำหรับการเขียน: echo…มีแน่นอนไม่จำเป็น
Ansgar Esztermann

มันเยี่ยมมาก! ฉันใช้สิ่งนี้เพื่อส่งการตอบสนอง "y" หรือ "n" ไปยังกระบวนการบางอย่างที่ถูกถอดออกอย่างสมบูรณ์ กระบวนการที่แยกออกมี stdout ไปที่หน้าต่างแยกต่างหาก เมื่อฉันทำเคล็ดลับนี้ฉันจะเห็นว่ามันไม่ "รับ" ตัว 'y' หรือ 'n' ทันทีที่ฉันแสดงมันฉันต้องออกจาก gdb และถอดมันออกแล้วมันจะได้รับเสียงสะท้อนทั้งหมดดังนั้น มีวิธีการดำเนินการนี้โดยไม่ต้องออกจาก gdb ก่อนที่กระบวนการรับข้อมูลจาก Fifo หรือไม่
krb686

call open("/tmp/fifo", 0600)แต่น่าเสียดายที่มันก็ดูเหมือนจะแขวนบน ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างมาก
ขมังธนู

27

เมื่อเทอร์มินัลดั้งเดิมไม่สามารถเข้าถึงได้อีกต่อไป ...

reptyrอาจเป็นสิ่งที่คุณต้องการดูhttps://serverfault.com/a/284795/187998

อ้างจากที่นั่น:

ดูreptyrซึ่งทำอย่างนั้น หน้า GitHub มีข้อมูลทั้งหมด

reptyr - เครื่องมือสำหรับโปรแกรม "re-ptying"

reptyr เป็นยูทิลิตี้สำหรับการเรียกใช้โปรแกรมที่มีอยู่และแนบไปกับเทอร์มินัลใหม่ เริ่มกระบวนการที่ใช้เวลานานกว่า ssh แต่ต้องออกและไม่ต้องการขัดจังหวะหรือไม่ เพียงแค่เริ่มต้นหน้าจอใช้ reptyr เพื่อคว้ามันแล้วฆ่าเซสชัน ssh และมุ่งหน้ากลับบ้าน

การใช้งาน

reptyr PID

"reptyr PID" จะจับกระบวนการด้วย id PID และแนบกับเทอร์มินัลปัจจุบันของคุณ

หลังจากติดตั้งแล้วกระบวนการจะรับอินพุตจากและเขียนเอาต์พุตไปยังเทอร์มินัลใหม่รวมถึง ^ C และ ^ Z (น่าเสียดายถ้าคุณใช้มันคุณจะต้องเรียกใช้ "bg" หรือ "fg" ในเทอร์มินัลเก่าซึ่งเป็นไปไม่ได้ที่จะแก้ไขด้วยวิธีที่เหมาะสมโดยไม่ต้องทำการแก้ไขเชลล์)


12

ฉันค่อนข้างแน่ใจว่าคุณไม่สามารถ

ps xตรวจสอบการใช้ หากกระบวนการที่มีความ?เป็นควบคุม TTYคุณไม่สามารถส่งเข้ากับมันมาก ๆ

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

ในตัวอย่างนี้คุณสามารถส่งป้อนข้อมูลเพื่อทำสิ่งที่ต้องการ9947 echo "test" > /dev/pts/1กระบวนการอื่น ( 9942) ไม่สามารถเข้าถึงได้

ครั้งต่อไปคุณสามารถใช้หน้าจอหรือtmuxเพื่อหลีกเลี่ยงสถานการณ์นี้


5
หรือถ้าคุณไม่จำเป็นต้องมีทั้งdtach screen
จัดการ

4
ไม่มีวิธีใดในมาตรฐาน (POSIX, SUS) แต่ในหลาย ๆ ระบบ (ส่วนใหญ่?) เป็นไปได้ที่จะใช้กลไกที่ debuggers ใช้ ดูคำตอบของ Ansgar ด้วยrootคุณสามารถทำสิ่งนี้กับกระบวนการของผู้ใช้คนอื่น
dmckee

3
การทำเช่นecho "test" > /dev/pts/1นั้นจะไม่ส่งอินพุตไปยังกระบวนการ9947- มันจะเอาท์พุทคำว่า "ทดสอบ" บนเทอร์มินัลของกระบวนการนั้น
psmears

6

แก้ไข : ดังที่ Stephane Gimenez กล่าวว่าไม่ใช่เรื่องง่าย มันอนุญาตให้คุณพิมพ์ไปยังเทอร์มินัลอื่นเท่านั้น

คุณสามารถพยายามที่จะเขียนถึงขั้นตอนนี้ใช้proc / มันควรจะอยู่ใน/ proc / pid / fd / 0ดังนั้นง่าย:

echo "hello" > /proc/PID/fd/0

ควรทำมัน ฉันยังไม่ได้ลอง แต่ควรใช้งานได้ตราบใดที่กระบวนการนี้ยังมีไฟล์อธิบายstdin ที่ถูกต้อง คุณสามารถตรวจสอบกับls -lใน/ proc / pid / FD /

  • ถ้ามันเป็นลิงค์ไปยัง / dev / null => มันถูกปิด
  • หากเป็นลิงก์ไปยัง / dev / pts / X หรือซ็อกเก็ต => มันเปิดอยู่

ดูnohupสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีทำให้กระบวนการทำงานต่อไป


2
มันไม่ง่ายอย่างนั้น ตัวอย่างเช่นหาก stdin เชื่อมโยงกับเทอร์มินัลการส่งข้อมูลechoบางอย่างไปยังอุปกรณ์เทอร์มินัลจะพิมพ์สิ่งที่คุณเขียนบนเทอร์มินัลมันจะไม่ถูกส่งไปยังกระบวนการ
Stéphane Gimenez

5

เพียงแค่จบบรรทัดคำสั่งด้วย&จะไม่แยกกระบวนการมันจะทำงานในพื้นหลัง (ด้วยzshคุณสามารถใช้&!เพื่อแยกออกจริงมิฉะนั้นคุณจะทำในdisownภายหลัง)

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

ไม่เช่นนั้นคุณจะไม่สามารถเปลี่ยนไฟล์ภายนอกที่บันทึกไว้ (รวมถึง stdin) หรือเชื่อมต่อสถานีควบคุมที่สูญหายไปอีกครั้ง ... เว้นแต่คุณจะใช้เครื่องมือดีบั๊ก (ดูคำตอบของ Ansgarหรือดูrettyคำสั่ง)


และมีคำถามที่เกี่ยวข้องที่นี่: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez

@Rogach ระบุว่า "เทอร์มินัลนั้นปิดแล้ว"
andcoz

1
@ andcoz: ใช่ แต่เขาโชคดีที่โปรแกรมยังไม่ได้รับ SIGHUPed ฉันแนะนำวิธีที่ปลอดภัยกว่า
Stéphane Gimenez

ที่นี่การปฏิเสธใช้งานได้จริง ๆ ถ้าฉันเปลี่ยนเส้นทาง stdout อย่างแรกเป็นอย่าง>>/dev/stderrอื่นเมื่อฉันปิดเทอร์มินัลกระบวนการ "ที่ถูกปฏิเสธ" จะสิ้นสุดเช่นกัน .. ฉันไม่เคยเข้าใจสิ่งนี้เลย ..
Aquarius Power
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.