Como criar um pipe nomeado sem esperar

Como criar um pipe nomeado sem esperar

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 cattravar 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 0só é 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 cato shell está embutido, como quando ksh93é chamado quando está à /opt/ast/binfrente 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$PATHbuiltin 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, catainda 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 socatde -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 catimediatamente 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, timeoutespera 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.

informação relacionada