Quando você faz:
cat fifo
Supondo que nenhum outro processo tenha aberto o fifo para gravação ainda, cat bloqueará a chamada do sistema open() . Quando outro processo abrir o arquivo para gravação, um canal será instanciado e open() retornará. cat chamará read() em um loop e read() bloqueará até que algum outro processo grave dados no pipe.
cat verá o final do arquivo (eof) quando todos os outros processos de escrita tiverem fechado seu descritor de arquivo para o fifo . Em que pontos cat termina e o tubo é destruído¹.
Você precisaria executar cat novamente para ler o que será gravado depois disso no fifo (mas por meio de uma instância de pipe diferente).
Em:
tail -f file
Como cat , tail aguardará um processo para abrir um arquivo para gravação. Mas aqui, como você não especificou -n +1 para copiar desde o início, tail precisará aguardar até eof para descobrir quais foram as últimas 10 linhas, para que você não veja nada até que o fim da escrita seja fechado.
Depois disso, tail não irá fechar seu fd para o pipe, o que significa que a instância do pipe não será destruída, e ainda tentará ler o pipe a cada segundo (no Linux, essa pesquisa pode ser evitada via uso de inotify e algumas versões do GNU tail fazem isso lá. Esse read() retornará com eof (imediatamente, e é por isso que você vê 100% da CPU com -s 0 (que com GNU tail significa não esperar entre read() s em vez de esperar por um segundo)) até que outro processo abre o arquivo novamente para gravação.
Aqui, em vez disso, você pode querer usar cat , mas certifique-se de que a instância do pipe permaneça sempre após ser instanciada. Para isso, na maioria dos sistemas, você poderia fazer:
cat 0<> fifo # the 0 is needed for recent versions of ksh93 where the
# default fd changed from 0 to 1 for the <> operator
O stdin de cat estará aberto para leitura e escrita, o que significa que cat nunca verá eof sobre ele (também instancia o pipe imediatamente mesmo se não houver outro processo abrindo fifo para escrita) .
Em sistemas onde isso não funciona, você pode fazer isso:
cat < fifo 3> fifo
Dessa forma, assim que algum outro processo abrir o fifo para gravação, o primeiro percentual somente de leituraopen() retornará, ponto no qual o shell fará o% somente gravaçãoopen() antes de iniciar cat , o que impedirá que o cano seja novamente destruído.
Então, para resumir:
- comparado a
cat file, não pararia após a primeira rodada. - comparado a
tail -n +1 -f file: ele não usariaread()inútil a cada segundo após a primeira rodada, nunca haveria eof na única instância da tubulação, não haveria esse atraso de até um segundo quando segundo processo abre o pipe para escrever depois que o primeiro fechou. - comparado a
tail -f file. Além do acima, ele não teria que esperar que a primeira rodada terminasse antes de produzir algo (apenas as últimas 10 linhas). - comparado a
cat fileem um loop, haveria apenas uma instância de pipe. As janelas de corrida mencionadas em ¹ seriam evitadas.
¹ neste ponto, entre o último read() que indica eof e cat terminando e fechando o final de leitura do pipe, há realmente uma pequena janela durante a qual um processo poderia abrir o fifo para gravação novamente (e não ser bloqueado, pois ainda há um final de leitura). Então, se ele escrever algo depois que cat tenha saído e antes que outro processo abra o fifo para leitura, ele será morto com um SIGPIPE.