Impedisci EOF automatici a una pipe denominata e invia un EOF quando lo desidero


12

Ho un programma che esce automaticamente dopo aver letto un EOF in un dato flusso (nel caso seguente, stdin).
Ora voglio fare uno script di shell, che crea una pipe denominata e collega lo stdin del programma ad esso. Quindi lo script scrive più volte sulla pipe usando echoe cat(e altri strumenti che generano automaticamente un EOF quando escono). Il problema che sto affrontando è che, quando il primo echoè terminato , invia un EOF alla pipe e fa uscire il programma. Se uso qualcosa del genere, tail -fnon posso inviare un EOF quando intendo uscire dal programma. Sto cercando una soluzione equilibrata ma senza risultati.
Ho già trovato sia come prevenire gli EOF sia come inviare manualmente un EOF ma non riesco a combinarli. C'è qualche suggerimento?

#!/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

Risposte:


13

Come altri hanno indicato, il lettore di una pipe riceve EOF quando non ci sono più scrittori. Quindi la soluzione è assicurarsi che ci sia sempre uno scrittore che lo tiene aperto. Quello scrittore non deve inviare nulla, tienilo aperto.

Dato che stai usando uno script di shell, la soluzione più semplice è dire alla shell di aprire la pipe per la scrittura. E poi chiudilo quando hai finito.

#!/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

Si noti che se si omette l'ultima riga, il descrittore di file 3 verrà automaticamente chiuso (e quindi il lettore riceverà EOF) alla chiusura dello script. A parte la comodità, ciò fornisce anche una sorta di sicurezza se lo script dovesse in qualche modo terminare in anticipo.


2
questa exec 3>Pcausa resta in sospeso, perché?
Wang,

@ Wang Non dovrebbe. In tal caso, probabilmente non stai facendo la stessa cosa del codice POC nella domanda. L'unica ragione per cui posso pensare che si bloccherebbe è se invece stai facendo qualcosa di simile exec 2>P, e hai attivato la modalità trace ( set -x), in cui bash sta per scrivere sulla pipe, ma non c'è lettore quindi blocca in attesa di qualcosa da leggere.
Patrick,

1
@Wang @Patrick Effettivamente si exec 3>Pblocca anche sulla mia macchina. Questo perché non è possibile leggere alcun processo P. Pertanto, la soluzione era di scambiare le linee exec 3>Pe program < P &(aggiungendo la e commerciale in modo che il programma venisse eseguito in background).
macieksk,

2

Una pipe riceve EOF quando l'ultimo scrittore se ne va. Per evitare ciò, assicurati che ci sia sempre uno scrittore (un processo che ha la pipe aperta per la scrittura, ma in realtà non scrive nulla). Per inviare l'EOF, fai sparire lo scrittore di riserva.

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

0

Non c'è modo per il programma di distinguere tra un EOF che significa "è ora di smettere" e un EOF che significa "uno scrittore è finito, ma potrebbe esserci più input da qualcun altro".

Se hai la possibilità di modificare il comportamento del tuo programma, esegui la lettura in un ciclo infinito (una iterazione dura fino a EOF) e inviagli una stringa di comando specifica che significa "tempo di chiusura". L'invio di quella stringa sarebbe il compito del send_eofcomando nella tua domanda.

Un'altra opzione:

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

o

{ echo some stuff; cat more_stuff.txt; } >P
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.