ksh93ha 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 $incrogni 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 readlegge 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 catapre il fifo, il echociclo e viene sbloccato, quindi è possibile eseguirne di più echo, nel momento in cui catlegge il contenuto e chiude la pipe (facendo sì che la prossima echoistanze di una nuova pipe).
Una soluzione potrebbe essere quella di aggiungere un po 'di ritardo, come ad esempio eseguendo un esterno echocome 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 rme il mknod()fatto da mkfifo) causando il catfallimento, 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 catdi 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 echoe il unlink()fatto da rm) dove si catbloccherà.
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' echooutput.
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 /tmpmeno che non sia un servizio da esporre a tutti gli utenti del sistema.