executando um script via ssh, saída não 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 são misturadas.

No meu caso, o script executa 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 essa não é a saída real de notmuch new, o comando termina com, No new mailmas é como se a saída fosse via ssh, não linha por linha.

Por que isso aconteceu?

res1
fonte
11
Meu palpite: parte da saída é stdout, outra saída é stderr. Se não for interativo, o buffer poderá diferir, alterando a ordem.
AB

Respostas:

5

Carregando. Se procurarmos 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 é sem buffer 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 um arquivo). Esse comportamento vem da biblioteca C padrão, consulte setvbuf(3)para obter detalhes. Assim, as stderrmensagens são gravadas imediatamente, enquanto as printfchamadas para stdoutserão exibidas ... bem, depende.

O buffer geralmente é configurado por cada aplicativo individualmente, embora talvez possa ser utilizado com utilitários como stdbuf(embora alguns considerem os LD_PRELOADtruques usados stdbufbastante horríveis ...).

A diferença é fácil de reproduzir localmente; por exemplo, gravando no 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 isso, se exatamente o 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
$ 

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

agitar
fonte
Entendo seu argumento, mas por que esse comportamento é mostrado apenas executando o comando remotamente?
res1
é fácil mostrar um problema localmente, além das complicações sshadicionadas.
thrig
As coisas do PS podem ficar ainda piores se você tentar leituras / gravações simultâneas no mesmo soquete - unix.stackexchange.com/questions/364396/… - como na possível corrupção de dados
dispara em