bir komut dosyasını ssh üzerinden çalıştırmak, gerçek çıktı değil


2

Bu şekilde ssh ile bir script çalıştırıyorum:

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

Sorun şu ki, bazen elde ettiğim çıktı doğru değil, satırlar karışık.

Benim durumumda script çok yeni değil, normal çıktı şöyle bir şey:

...
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.

ama bazen çıktı şöyle bir şeydir:

...
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

ve elbette bu gerçek çıktı değil, notmuch newkomut ile biter, No new mailancak ssh ile satır satır değil çıktı alır gibi.

Bu neden oldu?


1
Tahminim: Çıktıların bazıları stdout'a, bazıları da stderr'a. Etkileşimli olmazsa, tamponlama farklılık gösterebilir, bu nedenle sırayı değiştirebilir.
AB

Yanıtlar:


5

Tamponlama. Kaynak kodunu ararsaknotmuch

$ 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.");
$ 

Bu mesajların bazıları standart hata (varsayılan olarak arabelleksiz) kullanmakta, bazıları ise standart çıkış bir terminale mi yoksa bir dosyaya mı bağlı olduğuna bağlı olarak standart çıkış (standart olarak satır veya blok tamponlu) kullanmaktadır. Bu davranış standart C kütüphanesinden gelir, setvbuf(3)detaylar için bakınız. Böylece stderrmesajlar hemen yazılır, printfçağrılar stdoutgörünecek olsa da, buna bağlı olarak değişir.

Tamponlama tipik olarak her bir uygulama tarafından ayrı ayrı konfigüre edilir, bununla birlikte stdbuf(bazılarının oldukça korkunç olduğu düşünülen LD_PRELOADhileleri göz önünde bulundursa da stdbuf...)

Aradaki farkın yerel olarak çoğaltılması kolaydır; örneğin terminale yazmak (için satır tabanlı tamponlama stdout):

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

bunun yerine tam olarak aynı kod bir dosyaya yönlendirilirse (blok tabanlı arabellek stdout):

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

sshmüşteri sistemine notmuchneyin sshbağlı olduğunu ve sonra neyin toplandığını, arabelleğe alındığını ve gönderileceğini de bilmek zorunda kalabileceğinden, ek bir komplikasyon katmanı ekler ...


Amacınızı anlıyorum ama bu davranışın neden sadece uzaktan çalıştırıldığı gösteriliyor?
res1

Eklenen komplikasyonlara ek olarak yerel olarak bir problem göstermek kolaydır ssh.
thrig

Aynı okuyucuyu aynı anda okur / yazarsanız PS işleri daha da kötüye gidebilir - unix.stackexchange.com/questions/364396/… - olası veri bozulmalarında olduğu gibi
18:18
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.