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

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

Estou executando um script via ssh desta forma:

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

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

No meu caso, o script não é executado de forma muito nova, 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 mailmas é como se obtivesse a saída via ssh, não linha por linha.

Por que isso aconteceu?

Responder1

Carregando. Se pesquisarmos o código-fonte pornotmuch

$ 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 erro padrão (que não tem buffer por padrão) e algumas usam saída padrão (que tem 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 C padrão, consultesetvbuf(3)para detalhes. Assim, stderras mensagens são escritas imediatamente, enquanto as printfchamadas stdoutaparecerão... bem, depende.

O buffer normalmente é configurado por cada aplicativo individualmente, embora talvez possa ser manipulado com o uso de utilitários como stdbuf(embora alguns considerem os LD_PRELOADtruques usados ​​​​por stdbufbastante horríveis ...).

A diferença é fácil de reproduzir localmente; por exemplo, escrevendo no terminal (buffering 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 exatamente o mesmo código for redirecionado para um arquivo (buffering 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
$ 

sshadiciona uma camada adicional de complicação, pois também pode ser necessário descobrir como ele está coletando, armazenando em buffer e enviando bytes, além do notmuchque sshestá conectado no sistema do cliente...

informação relacionada