แทนที่กระบวนการปัจจุบันด้วยกระบวนการ / กระบวนการลูก


10

ฉันมีโปรแกรมPที่คาดว่าจะได้รับ "สวัสดี" และส่งออก "ทำไม" ก่อนที่จะให้คุณสมบัติ คุณลักษณะนี้ใช้งานโดยโปรแกรมอื่นที่ไม่ทราบว่ามันเป็นมารยาททั่วไปในการเริ่มการสนทนากับ "Hello" ฉันจึงต้องการเขียน wrapper สำหรับPที่ทำงานเช่นนี้ (ไวยากรณ์ zsh):

coproc P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
[[ "$line" = "Why?" ]] && Replace current process with the coprocess.
echo Could not get P's attention.

การใช้catหรือddในReplace...บางส่วน (บางอย่างเช่นcat <&p &; exec cat >&p) ส่งผลให้มีการบัฟเฟอร์ที่ไม่จำเป็น ตัวเลือกของฉันคืออะไร?


คุณต้องการzshทางออกหรือbashยอมรับวิธีแก้ปัญหาหรือไม่?
roaima

1
ฉันจะผิดหวังกับbashวิธีการแก้ปัญหาที่ไม่สามารถใช้ได้zshแต่จะยอมรับได้อย่างแน่นอนa
Michaël

เป็นที่รู้จักกันว่าโปรแกรมอื่นจะใช้สคริปต์นี้? มันเป็นรายการที่ จำกัด หรือเป็นไปได้ไหม? เห็นได้ชัดว่าโปรแกรมอื่น ๆ จำเป็นต้องรู้เกี่ยวกับสิ่งนี้เพื่อที่จะเรียกมันว่า
Lizardx

การใช้งานทั่วไปของฉันอยู่กับตัวเลือกของssh ProxyCommand
Michaël

1
catโดยทั่วไปจะไม่บัฟเฟอร์ cat -uถ้ามันไม่เกี่ยวกับระบบของคุณลอง
Stéphane Chazelas

คำตอบ:


1

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

ไม่มีทางที่จะทำสิ่งนี้โดยตรง (อย่างน้อยในเชลล์; ภายในกระบวนการการdup2โทรอาจทำงานได้) คุณจะต้องประกบลำธาร เช่น:

( echo Hello ; cat ) | P | ( read ; cat )

ใช้coprocในตัวอย่างของคุณก็โอเคเช่นกัน โปรดทราบว่าคำสั่งจะบันทึกไฟล์ descriptors ลงในอาร์เรย์และคุณสามารถใช้เพื่อเปลี่ยนเส้นทางในภายหลัง

สิ่งนี้ไม่ควรทำให้เกิดการบัฟเฟอร์เพิ่มเติม (อย่างน้อยกับ GNU cat) ยกเว้นว่า P ตรวจสอบกระแสอินพุต / เอาท์พุตที่มันเชื่อมต่ออยู่และทำการตัดสินใจที่จะบัฟเฟอร์ตามนั้น ตัวอย่างเช่นไลบรารีมาตรฐาน C จะเปิดใช้งานการบัฟเฟอร์ในstdout/ stderrหากเชื่อมต่อกับไฟล์ แต่จะทำการบัฟเฟอร์บรรทัดเฉพาะเมื่อเชื่อมต่อกับเทอร์มินัลเท่านั้น


-1

สามารถทดสอบด้วยโค้ดด้านล่างโดยใช้ Perl เพื่อหลีกเลี่ยงการบัฟเฟอร์ลองใช้งานได้ไหม

ตัวอย่างรุ่น P

$ cat /tmp/P
#!/bin/bash
read input
if [[ $input = "Hello" ]]
then
    echo "Why?"
else
    exit 1
fi
echo "Got Hello from client, working ..."
sleep 10
echo "Need to read some input"
read x
echo "Got: $x"

โปรแกรม wrapper

$ cat /tmp/wrapper 
#!/usr/bin/zsh
coproc /tmp/P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
if [[ "$line" = "Why?" ]]; then
    perl -e '$|=1;print $_ while(<>);' <& p &
    perl -e '$|=1;print $_ while(<>);' >& p
else
    echo "Could not get P's attention."
fi

ทดสอบการทำงาน

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!

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