ksh93ma dyscypliny, które są zwykle używane do tego rodzaju rzeczy. Dzięki zsh, można porwać katalogu dynamiczny o nazwie funkcji :
Zdefiniuj na przykład:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
A następnie możesz użyć, ~[incr]aby uzyskać przyrost za $incrkażdym razem:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Twoje podejście kończy się niepowodzeniem, ponieważ w head -1 /tmp/ints, głowa otwiera fifo, czyta pełny bufor, drukuje jedną linię, a następnie ją zamyka . Po zamknięciu koniec pisania widzi zepsutą rurkę.
Zamiast tego możesz albo:
$ 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
Tam zostawiamy otwarty koniec odczytu na fd 3 i readodczytujemy jeden bajt na raz, a nie pełny bufor, aby upewnić się, że przeczytano dokładnie jedną linię (do znaku nowej linii).
Lub możesz zrobić:
$ 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
Tym razem tworzymy instancję potoku dla każdej wartości. Umożliwia to zwracanie danych zawierających dowolną liczbę wierszy.
Jednak w takim przypadku, gdy tylko catotwiera się fifo, echopętla i jest odblokowywana, aby echomożna było uruchomić więcej, zanim catodczyta zawartość i zamknie potok (powodując, że następny echoutworzy nowy potok).
Rozwiązaniem może być dodanie opóźnienia, na przykład poprzez uruchomienie zewnętrznego, echojak sugeruje @jimmij, lub dodanie go sleep, ale nadal nie byłoby to zbyt solidne, lub można odtworzyć nazwaną potok po każdym echo:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Że nadal pozostawia krótkie okna gdzie nie istnieją rura (między unlink()zrobione przez rmi mknod()wykonywane przez mkfifo) spowodowanie cat, by upaść, i bardzo krótkich okna gdzie rura została instancja ale nie proces będzie kiedykolwiek ponownie napisać do niego (między write()i close()zrobione przez echo) powodując, catże nic nie zwróci, i krótkie okna, w których nazwany potok nadal istnieje, ale nic nigdy go nie otworzy do zapisu (między close()wykonanym przez echoa unlink()wykonanym przez rm) gdzie catzawiesi się.
Możesz usunąć niektóre z tych okien , wykonując następujące czynności:
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
) &
W ten sposób jedynym problemem jest uruchomienie kilku kotów jednocześnie (wszystkie otwierają fifo, zanim nasza pętla zapisu będzie gotowa do otwarcia go do zapisu), w którym to przypadku będą dzielić dane echowyjściowe.
Odradzałbym także tworzenie stałych nazw, czytelnych na całym świecie fifos (lub jakichkolwiek innych plików w tym zakresie) w katalogach zapisywalnych na świecie, takich jak /tmpchyba, że jest to usługa dostępna dla wszystkich użytkowników w systemie.