Ganti proses saat ini dengan prosesnya / anak

10

Saya memiliki program Pyang mengharapkan untuk menerima "Halo" dan menampilkan "Mengapa?" sebelum menyediakan fitur. Fitur ini digunakan oleh program lain yang tidak menyadari bahwa adalah hal yang umum untuk memulai percakapan dengan "Halo". Jadi saya ingin menulis pembungkus untuk Pyang berfungsi seperti ini (sintaks 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.

Menggunakan catatau dddi Replace...bagian (sesuatu seperti cat <&p &; exec cat >&p) menghasilkan buffering yang tidak perlu. Apa saja pilihan saya?

Michaël
sumber
Apakah Anda menginginkan zshsolusi atau apakah bashsolusi itu dapat diterima?
roaima
1
Saya akan kecewa dengan bashsolusi yang tidak berlaku di zsh, tetapi pasti akan menerimanya ☺
Michaël
Apakah diketahui program apa yang akan menjalankan skrip ini? Apakah ini daftar terbatas, atau mungkinkah jumlahnya? Jelas program lain perlu tahu tentang ini untuk menyebutnya.
Lizardx
Penggunaan khas saya adalah dengan sshdan pilihannya ProxyCommand.
Michaël
1
catumumnya tidak buffer. Jika berhasil di sistem Anda, coba cat -u.
Stéphane Chazelas

Jawaban:

1

Masalah yang Anda nyatakan bukan tentang mengganti proses , tetapi mengganti aliran proses yang ada . Tujuannya adalah untuk berinteraksi sedikit dengan proses kemudian menyerahkan input / output ke sepasang aliran yang terhubung.

Tidak ada cara untuk melakukan ini secara langsung (setidaknya, di shell; di dalam proses, dup2panggilan mungkin bisa berfungsi). Anda perlu menyambungkan stream. Yaitu:

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

Menggunakan coprocseperti pada contoh Anda juga OK. Perhatikan bahwa perintah menyimpan deskriptor file ke array, dan nanti Anda dapat menggunakannya untuk pengalihan.

Ini seharusnya tidak menyebabkan buffering tambahan (setidaknya dengan GNU cat), kecuali P memeriksa aliran input / output yang terhubung dan membuat keputusan untuk buffer berdasarkan itu. Misalnya, pustaka standar C akan mengaktifkan buffering pada stdout/ stderrjika mereka terhubung ke file, tetapi hanya melakukan buffering baris jika mereka terhubung ke terminal.

Vladimir Panteleev
sumber
-1

Mampu menguji dengan kode di bawah ini menggunakan perl untuk menghindari buffering, coba jika ini cocok untuk Anda

Versi sampel dari 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"

Program pembungkus

$ 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

Uji coba

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!
VenkatC
sumber
Ini sama dengan menggunakan dd ibs=1, misalnya. Saya tidak setuju dengan ini. Di satu sisi, coproc memiliki buffering sendiri, dan inilah yang ingin saya gunakan.
Michaël