executando um script via ssh, não saída real

2

Estou executando um script via ssh desta maneira:

 ssh user@host 'bash -s' < ./script.sh

o problema é que, às vezes, a saída que recebo não está correta, as linhas estão misturadas.

No meu caso, o script não é muito novo, a saída normal é algo como:

...
Note: Ignoring non-mail file: foobar
Note: Ignoring non-mail file: foobar
Note: Ignoring non-mail file: foobar
Processed 93 total files in almost no time.
No new mail.

mas às vezes a saída é algo como:

...
Note: Ignoring non-mail file: foobar
Note: Ignoring non-mail file: foobar
Processed 93 total files in almost no time.
No new mail.
Note: Ignoring non-mail file: foobar
Note: Ignoring non-mail file: foobar

e com certeza esta não é a saída real de notmuch new , o comando termina com No new mail mas é como se a saída via ssh não fosse linha por linha.

Por que isso acontece?

    
por res1 04.02.2018 / 16:23

1 resposta

5

Buffer. Se pesquisarmos o código-fonte para notmuch

$ find . -name \*.c -exec grep 'Ignoring non-mail file' {} +
./notmuch-new.c:    fprintf (stderr, "Note: Ignoring non-mail file: %s\n", filename);
$ find . -name \*.c -exec grep 'No new mail' {} +
./notmuch-new.c:    printf ("No new mail.");
$ 

Algumas dessas mensagens usam o erro padrão (que é unbuffered por padrão) e algumas usam saída padrão (que é buffer de linha ou bloco por padrão, dependendo se a saída padrão é para um terminal ou para um arquivo). Este comportamento vem da biblioteca padrão C, veja setvbuf(3) para detalhes. Assim, stderr mensagens são escritas imediatamente, enquanto as chamadas printf para stdout aparecerão ... bem, isso depende.

O armazenamento em buffer é tipicamente configurado por cada aplicativo individualmente, embora talvez possa ser usado com utilitários como stdbuf (embora alguns considerem os truques LD_PRELOAD usados por stdbuf como sendo bastante horríveis ...).

A diferença é fácil de reproduzir localmente; por exemplo, escrevendo para o terminal (buffer baseado em linha para stdout ):

$ perl -E 'for (1..4) { say "out"; warn "err\n" }'
out
err
out
err
out
err
out
err
$ 

enquanto, em vez disso, se esse mesmo código for redirecionado para um arquivo (buffer baseado em bloco para stdout ):

$ perl -E 'for (1..4) { say "out"; warn "err\n" }' >x 2>&1
$ cat x
err
err
err
err
out
out
out
out
$ 

ssh adiciona uma camada adicional de complicação, pois também é possível descobrir como ela está coletando, armazenando em buffer e enviando bytes, além de notmuch e, em seguida, em que ssh está conectado até sistema do cliente ...

    
por 04.02.2018 / 18:09