ksh93hat Disziplinen, die typischerweise für solche Dinge verwendet werden. Mit zshkö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 $incrjedes 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 readdas 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 catdie echound die Schleife entsperrt, sobald das FIFO geöffnet wird, sodass mehr ausgeführt echowerden kann, wenn catder Inhalt gelesen und die Pipe geschlossen wird (wodurch die nächste echoeine neue Pipe instanziiert).
Eine echoProblemumgehung 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" rmund " mknod()erledigt von" mkfifo), was catzu 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 echound unlink()erledigt von rm), wo cathä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 echoAusgabe.
Ich würde auch davon abraten, einen festen Namen, weltweit lesbare Fifos (oder eine andere Datei für diese Angelegenheit) in weltweit beschreibbaren Verzeichnissen /tmpzu erstellen, es sei denn, es handelt sich um einen Dienst, der allen Benutzern im System zugänglich gemacht wird.