ksh93
hat Disziplinen, die typischerweise für solche Dinge verwendet werden. Mit zsh
könnten Sie die kapern dynamische genannte Verzeichnis - Funktion :
Definieren Sie zum Beispiel:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Und dann können Sie verwenden ~[incr]
, um $incr
jedes Mal ein Inkrement zu erhalten :
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Ihr Ansatz schlägt fehl, weil in head -1 /tmp/ints
, head das FIFO öffnet, einen vollständigen Puffer liest, eine Zeile druckt und sie dann schließt . Nach dem Schließen sieht das Schreibende ein gebrochenes Rohr.
Stattdessen können Sie entweder Folgendes tun:
$ 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
Dort lassen wir read
das Leseende auf fd 3 offen und lesen jeweils ein Byte, nicht einen vollen Puffer, um sicherzugehen, dass genau eine Zeile (bis zum Zeilenumbruchzeichen) gelesen wird.
Oder Sie könnten tun:
$ 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
Dieses Mal instanziieren wir für jeden Wert eine Pipe. Dies ermöglicht die Rückgabe von Daten, die eine beliebige Anzahl von Zeilen enthalten.
In diesem Fall wird jedoch cat
die echo
und die Schleife entsperrt, sobald das FIFO geöffnet wird, sodass mehr ausgeführt echo
werden kann, wenn cat
der Inhalt gelesen und die Pipe geschlossen wird (wodurch die nächste echo
eine neue Pipe instanziiert).
Eine echo
Problemumgehung könnte darin bestehen, eine Verzögerung hinzuzufügen, z. B. indem Sie eine externe Datei ausführen , wie von @jimmij vorgeschlagen, oder eine hinzufügen sleep
, aber das wäre immer noch nicht sehr robust, oder Sie könnten die benannte Pipe nach jeder neu erstellen echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Dadurch bleiben immer noch kurze Fenster, in denen die Pipe nicht vorhanden ist (zwischen " unlink()
erledigt von" rm
und " mknod()
erledigt von" mkfifo
), was cat
zu einem Fehler führt, und sehr kurze Fenster, in denen die Pipe instanziiert wurde, aber kein Prozess jemals wieder darauf schreibt (zwischen " write()
und") close()
erledigt durch echo
) bewirkt cat
, dass nichts zurückgegeben wird, und kurze Fenster, in denen die benannte Pipe noch vorhanden ist, aber nichts wird sie jemals zum Schreiben öffnen (zwischen close()
erledigt von echo
und unlink()
erledigt von rm
), wo cat
hängen bleibt.
Sie können einige dieser Fenster folgendermaßen entfernen :
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
) &
Auf diese Weise besteht das einzige Problem darin, dass Sie mehrere Katzen gleichzeitig ausführen (alle öffnen das FIFO, bevor unsere Schreibschleife zum Schreiben bereit ist). In diesem Fall teilen sie die echo
Ausgabe.
Ich würde auch davon abraten, einen festen Namen, weltweit lesbare Fifos (oder eine andere Datei für diese Angelegenheit) in weltweit beschreibbaren Verzeichnissen /tmp
zu erstellen, es sei denn, es handelt sich um einen Dienst, der allen Benutzern im System zugänglich gemacht wird.