Como corretamente unbuffer um pipeline?

1

Estou tentando seguir várias respostas em este , este e este tópicos, mas meu pipeline ainda aparece em buffer. Aqui está uma tentativa de exemplo:

unbuffer sh -c 'echo -n test; sleep 1; echo; sleep 1; echo -n hello; sleep 1; echo' | grep .

O comando acima deve imprimir imediatamente test , depois da segunda impressão hello e depois de mais uma segunda extremidade. Em vez disso, recebo um atraso de um segundo, só então test , depois de um atraso de dois -segundos, hello com a saída de comando.

Note que aqui estou tentando eliminar completamente o buffer e a opção --line-buffered de grep não ajuda. Então, como eu realmente desabafar este gasoduto?

    
por Ruslan 18.08.2017 / 16:35

1 resposta

3

grep produzirá as linhas que correspondem a um padrão, não podendo produzir nada até uma linha completa (ou fim de arquivo no qual, se a última linha não foi terminada , o comportamento varia dependendo da implementação) foi lido.

Então, em:

(echo -n foo; sleep 1; echo bar) | grep .

Não é porque echo armazena em buffer sua saída . Não faz. Como poderia, uma vez terminado? É porque grep está aguardando o fim da linha (que virá, imediatamente seguido pelo fim do arquivo com o segundo echo ).

Para fazer o que você parece querer, você precisa ler as linhas com um tempo limite para cada linha como (com bash ):

(echo -n foo; sleep 1; echo bar) |
  while true; do
    TMOUT=0.1 IFS= read -r line; ret=$?
    if [ "$(kill -l "$ret")" = ALRM ]; then
      [ -n "$line" ] || continue
      ors=
    elif [ "$ret" -eq 0 ]; then
      ors=$'\n'
    elif [ -z "$line" ]; then
      break
    fi
    [[ $line =~ . ]] && printf %s "$line$ors"
  done

(você recebe um passe no loop pelo menos a cada 0,1 segundo).

    
por 18.08.2017 / 16:44