faz a saída da cauda em um cano quebrado

4

Eu quero assistir a um arquivo até aparecer um pouco de texto

Eu encontrei esta resposta: 'tail -f' até que o texto seja visto

mas quando eu tentei no Ubuntu, ele não saiu:

$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$

funciona como esperado. no entanto, quando tento seguir o arquivo

$ tail -f test.txt | sed '/w/ q'
one
two

nunca sai. a cauda não para até mesmo se o tubo estiver quebrado.

Alguém sabe como fazer tail sair quando sed sai?

    
por Alex028502 10.01.2018 / 17:40

1 resposta

6

São as mesmas coisas que em:

Em:

cmd1 | cmd2

Seu shell acaba aguardando até que cmd1 termine mesmo depois de cmd2 ter terminado. Esse não é o caso de todas as conchas. Alguns como o shell Bourne ou Korn não fazem por exemplo.

Quando cmd2 morre, o canal no stdout de cmd1 fica quebrado , mas isso não termina cmd1 instantaneamente.

cmd1 terminará na próxima vez que tentar gravar nesse pipe. Em seguida, ele receberá um SIGPIPE cuja ação padrão é encerrar o processo.

Com cmd1 == tail -f file e cmd2 == sed /w/q , tail -f lerá as últimas 10 linhas do arquivo e as gravará no stdout (o canal), normalmente em um bloco, a menos que o as linhas são realmente grandes e ficam ali esperando que mais texto seja anexado a file .

sed , que é executado simultaneamente, aguardará entrada em seu stdin, lerá, processará linha por linha e sairá se houver uma linha que contenha w .

Tão logo (ou possivelmente com um atraso de uma linha com alguma sed de implementação) quando encontra essa linha, ela sai, mas, nesse momento, tail já escreveu para o pipe tudo o que tinha para ESCREVER, então ele não receberá um SIGPIPE, a menos que algum texto adicional seja adicionado posteriormente ao arquivo (ponto no qual ele fará a% fatalwrite()).

Se você quiser que cmd1 termine assim que cmd2 termine, você precisará de algo para desativá-lo quando cmd2 terminar. Como com:

sh -c 'echo "$$"; exec tail -f test.txt' | {
  IFS= read pid
  sed /w/q
  kill -s PIPE "$pid"
}

Ou com bash :

{ sed /w/q; kill -s PIPE "$!"; } < <(exec tail -f text.txt)
    
por 10.01.2018 / 18:31

Tags