ksh93
tem disciplinas que são normalmente usadas para esse tipo de coisa. Com zsh
, você pode seqüestrar o recurso diretório nomeado dinâmico :
Defina por exemplo:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Você pode usar ~[incr]
para obter um $incr
incrementado a cada vez:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Sua abordagem falha porque, em head -1 /tmp/ints
, o head abre o fifo, lê um buffer completo, imprime uma linha, e depois a fecha . Uma vez fechado, o final da escrita vê um cano quebrado.
Em vez disso, você pode fazer:
$ 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á, deixamos o final da leitura aberto no fd 3, e read
lê um byte de cada vez, não um buffer completo para ter certeza de ler exatamente uma linha (até o caractere de nova linha).
Ou você poderia fazer:
$ 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
Naquela época, instanciamos um pipe para cada valor. Isso permite retornar dados contendo qualquer número arbitrário de linhas.
No entanto, nesse caso, assim que cat
abrir o fifo, o echo
e o loop serão desbloqueados, portanto, mais echo
poderá ser executado, quando cat
ler o conteúdo e fechar o pipe (fazendo com que o próximo echo
instancie um novo canal).
Uma solução alternativa poderia ser adicionar algum atraso, como por exemplo, executando um echo
externo como sugerido por @jimmij ou adicionando algum sleep
, mas isso ainda não seria muito robusto, ou você poderia recriar o nome canalizar após cada echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Isso ainda deixa janelas curtas em que o canal não existe (entre unlink()
feito por rm
e mknod()
feito por mkfifo
), fazendo com que cat
falhe e janelas muito curtas em que o pipe foi instanciado, mas nenhum processo será gravado novamente nele (entre write()
e close()
feito por echo
), fazendo com que cat
não retorne nada e janelas curtas em que o pipe nomeado ainda existe, mas nada será sempre abri-lo para gravação (entre o close()
feito por echo
e o unlink()
feito por rm
) onde cat
irá travar.
Você pode remover algumas dessas janelas fazendo o seguinte:
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
) &
Dessa forma, o único problema é se você executar vários cat ao mesmo tempo (todos eles abrem o fifo antes que nosso loop de gravação esteja pronto para abri-lo para gravação). Nesse caso, eles compartilharão a echo
output. / p>
Eu também aconselho contra a criação de nomes fixos, fifos legíveis para o mundo (ou qualquer arquivo para esse assunto) em diretórios graváveis mundiais como /tmp
a menos que seja um serviço a ser exposto a todos os usuários no sistema.