Cegah EOFs otomatis ke pipa bernama, dan kirim EOF ketika saya menginginkannya

12

Saya memiliki program yang keluar secara otomatis setelah membaca EOF dalam aliran yang diberikan (dalam kasus berikut, stdin).
Sekarang saya ingin membuat skrip shell, yang membuat pipa bernama dan menghubungkan stdin program ke sana. Kemudian skrip menulis ke pipa beberapa kali menggunakan echodan cat(dan alat-alat lain yang secara otomatis menghasilkan EOF ketika mereka keluar). Masalah yang saya hadapi adalah, ketika yang pertama echodilakukan, ia mengirim EOF ke pipa dan membuat program keluar. Jika saya menggunakan sesuatu seperti itu tail -fmaka saya tidak dapat mengirim EOF ketika saya bermaksud untuk keluar dari program. Saya sedang mencari solusi yang seimbang tetapi tidak berhasil.
Saya sudah menemukan cara mencegah EOF dan cara mengirim EOF secara manual tetapi saya tidak bisa menggabungkannya. Apakah ada petunjuk?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg
iBug
sumber

Jawaban:

13

Seperti yang telah ditunjukkan orang lain, pembaca pipa menerima EOF setelah tidak ada penulis yang tersisa. Jadi solusinya adalah untuk memastikan selalu ada satu penulis memegangnya terbuka. Penulis itu tidak perlu mengirim apa pun, cukup buka saja.

Karena Anda menggunakan skrip shell, solusi paling sederhana adalah memberi tahu shell untuk membuka pipa untuk menulis. Dan kemudian tutup setelah selesai.

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

Perhatikan bahwa jika Anda menghilangkan baris terakhir, deskriptor file 3 akan ditutup secara otomatis (dan dengan demikian pembaca menerima EOF) ketika skrip keluar. Selain kenyamanan, ini juga memberikan semacam keamanan jika script itu entah bagaimana berakhir lebih awal.

Patrick
sumber
2
exec 3>Psebab ini bertahanlah, mengapa?
Wang
@ Wang Seharusnya tidak. Jika ya maka Anda mungkin tidak melakukan hal yang sama dengan kode POC dalam pertanyaan. Satu-satunya alasan saya dapat berpikir bahwa itu akan diblokir adalah jika Anda malah melakukan sesuatu seperti exec 2>P, dan Anda memiliki mode jejak dihidupkan ( set -x), di mana bash akan menulis ke pipa, tetapi tidak ada pembaca sehingga memblokir menunggu sesuatu untuk dibaca.
Patrick
1
@ Wang @ Patrick Memang exec 3>Phang bash di komputer saya juga. Ini karena tidak ada proses membaca dari P. Jadi, solusinya adalah dengan menukar garis exec 3>Pdan program < P &(menambahkan ampersand sehingga program berjalan di latar belakang).
macieksk
2

Sebuah pipa menerima EOF ketika penulis terakhir pergi. Untuk menghindarinya, pastikan selalu ada penulis (proses yang membuat pipa terbuka untuk menulis, tetapi sebenarnya tidak menulis apa pun). Untuk mengirim EOF, buat penulis cadangan itu pergi.

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}
Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Tidak ada cara bagi program untuk membedakan antara EOF yang berarti "saatnya untuk berhenti" dan EOF yang berarti "seorang penulis selesai, tetapi mungkin ada lebih banyak masukan dari orang lain".

Jika Anda memiliki kemampuan untuk mengubah perilaku program Anda, maka lakukan pembacaan dalam loop yang tak terbatas (satu iterasi berlangsung hingga EOF) dan mengirimkannya string perintah khusus yang berarti "waktu untuk berhenti". Mengirim string itu akan menjadi tugas send_eofperintah dalam pertanyaan Anda.

Pilihan lain:

( echo some stuff; cat more_stuff.txt ) >P

atau

{ echo some stuff; cat more_stuff.txt; } >P
Kusalananda
sumber