Se não houver nada em um pipe nomeado e eu fizer:
cat my_named_pipe
ele esperará até que os dados cheguem. Existe um sinalizador que posso usar para sair imediatamente se não houver dados para serem lidos? Ou talvez um comando diferente de cat que eu possa usar?
Eu também tentei:
read val < "$my_named_pipe";
mas isso também aguarda o próximo bloco de dados - não quero esperar se o fifo estiver vazio.
Responder1
Para evitar cat
travar na ausência de algum escritor (nesse caso é a abertura do fifo, e não a leitura dele, que trava), você pode fazer:
cat 0<> "$my_named_pipe" <"$my_named_pipe"
O primeiro redirecionamento abre no modo leitura+gravação que na maioria dos sistemas não bloqueia e instancia o canal mesmo que ainda não haja gravador nem leitor. Então a segunda abertura (desta vez somente leitura) não seria bloqueada porque há pelo menos um gravador agora (ele próprio).
Isso 0
só é necessário em versões recentes do ksh93, onde o fd padrão <>
mudou de 0 para 1.
Além disso, em ksh93
, isso não funcionaria quando cat
o shell está embutido, como quando ksh93
é chamado quando está à /opt/ast/bin
frente ou depois de uma chamada para como no , (eu acho) ksh93 salva o destino anterior de stdin em um descritor de arquivo separado que seria mantenha o tubo aberto. Você pode contornar isso escrevendo:/bin
$PATH
builtin cat
<"$my_named_pipe"
cat 3<> "$my_named_pipe" <"$my_named_pipe" 3<&-
(que você também pode argumentar que transmite a intenção de forma mais clara)
Observe que isso <>
no pipe também desbloquearia outros leitores para o fifo.
Se houvesse alguns escritores, cat
ainda teria que ler toda a sua produção e esperar até que eles fechassem o fim do tubo. Você pode abrir o pipe em modo sem bloqueio, como no GNU dd
:
dd bs=64k if="$my_named_pipe" iflag=nonblock status=noxfer
Que só leria o pipe enquanto houvesse alguns dados nele e sairia com um
dd: error reading 'fifo': Resource temporarily unavailable
erro quando não há mais, e não desbloquear outros leitores, mas isso significa que você pode perder algumas das saídas dos escritores se eles forem mais lentos para escrever no canal do que você ( dd
) para lê-lo.
Outra abordagem poderia ser o tempo limite quando não houve nenhuma entrada por algum tempo, por exemplo, usando a opção socat
de -T
:
socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"
Que sairia se não houvesse nada saindo do cano em um segundo.
Responder2
Algo bastante fácil seria encerrar cat
imediatamente após a leitura do fifo, independentemente de haver dados ou não. Você poderia fazer isso com timeout
, da seguinte maneira:
timeout 2 cat my_named_pipe
Acima, timeout
espera dois segundos antes de forçar o encerramento do gato. Se houver algo armazenado em buffer no pipe nomeado quando você executar cat
, ele será impresso em stdout.
Talvez não seja a solução mais limpa, mas funciona.
Espero que ajude.