ksh93
ha discipline che sono in genere utilizzate per questo tipo di cose. Con zsh
, è possibile dirottare la funzione di directory denominata dinamica :
Definire ad esempio:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
E poi puoi usare ~[incr]
per ottenere un incremento $incr
ogni volta:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Il tuo approccio fallisce perché in head -1 /tmp/ints
, head apre il fifo, legge un buffer completo, stampa una riga e quindi lo chiude . Una volta chiuso, la fine della scrittura vede un tubo rotto.
Invece, potresti fare:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ seq infinity > $fifo &
$ exec 3< $fifo
$ IFS= read -rneu3
1
$ IFS= read -rneu3
2
Lì, lasciamo aperta la fine della lettura su fd 3 e read
legge un byte alla volta, non un buffer completo per essere sicuri di leggere esattamente una riga (fino al carattere di nuova riga).
Oppure potresti fare:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ while true; do echo $((++incr)) > $fifo; done &
$ cat $fifo
1
$ cat $fifo
2
Quella volta, istanziamo una pipe per ogni valore. Ciò consente di restituire dati contenenti qualsiasi numero arbitrario di righe.
Tuttavia, in quel caso, non appena si cat
apre il fifo, il echo
ciclo e viene sbloccato, quindi è possibile eseguirne di più echo
, nel momento in cui cat
legge il contenuto e chiude la pipe (facendo sì che la prossima echo
istanze di una nuova pipe).
Una soluzione potrebbe essere quella di aggiungere un po 'di ritardo, come ad esempio eseguendo un esterno echo
come suggerito da @jimmij o aggiungerne un po' sleep
, ma ciò non sarebbe ancora molto robusto, oppure potresti ricreare la pipa denominata dopo ciascuna echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Ciò lascia ancora brevi finestre in cui la pipe non esiste (tra il unlink()
fatto da rm
e il mknod()
fatto da mkfifo
) causando il cat
fallimento, e finestre molto brevi in cui la pipe è stata istanziata ma nessun processo scriverà mai più su di esso (tra il write()
e il close()
fatto da echo
) causando cat
di non restituire nulla, e brevi finestre in cui esiste ancora la named pipe ma nulla lo aprirà mai per la scrittura (tra il close()
fatto da echo
e il unlink()
fatto da rm
) dove si cat
bloccherà.
Puoi rimuovere alcune di quelle finestre facendolo come segue:
fifo=~/.generators/incr
(
umask 077
mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo &&
while
mkfifo $fifo.new &&
{
mv $fifo.new $fifo &&
echo $((++incr))
} > $fifo
do : nothing
done
) &
In questo modo, l'unico problema è se esegui più gatti contemporaneamente (tutti aprono il quindicesimo prima che il nostro ciclo di scrittura sia pronto per aprirlo per la scrittura) nel qual caso condivideranno l' echo
output.
Vorrei anche sconsigliare la creazione di nomi fissi, file quindici leggibili in tutto il mondo (o qualsiasi file per quello che conta) in directory scrivibili in tutto il mondo come a /tmp
meno che non sia un servizio da esporre a tutti gli utenti del sistema.