Bunun üstesinden gelebileceğinizi sanmıyorum.
İle -tt
, sshd
bir sözde terminal oluşturur ve köle kısmını uzak komutu yürüten kabuğun stdin, stdout ve stderr'ı yapar.
sshd
(tekli) fd'den sözde terminalin ana kısmına gelenleri okur ve bunu (tek bir kanal aracılığıyla) ssh
istemciye gönderir . Stderr için olduğu gibi ikinci bir kanal yoktur -t
.
Ayrıca, sözde terminalin terminal hattı disiplininin çıkışı değiştirebileceğini (ve varsayılan olarak değiştireceğini) unutmayın. Örneğin, LF yerel terminalde değil orada CRLF'ye dönüştürülecektir, bu nedenle çıktı sonrası işlemeyi devre dışı bırakmak isteyebilirsiniz.
$ ssh localhost 'echo x' | hd
00000000 78 0a |x.|
00000002
$ ssh -t localhost 'echo x' | hd
00000000 78 0d 0a |x..|
00000003
$ ssh -t localhost 'stty -opost; echo x' | hd
00000000 78 0a |x.|
00000002
Giriş tarafında çok daha fazla şey olacak ( ^C
SIGINT'e neden olacak karakter gibi , aynı zamanda diğer sinyaller, yankı ve kanonik mod satırı düzenleyicisine dahil olan tüm işlemler ).
Stderr'ı bir fifo'ya yönlendirebilir ve bir saniye kullanarak alabilirsiniz ssh
:
ssh -tt host 'mkfifo fifo && cmd 2> fifo' &
ssh host 'cat fifo' >&2
Ancak en iyi IMO, -t
tamamen kullanmaktan kaçınmak olacaktır . Bu gerçekten sadece gerçek bir terminalden etkileşimli kullanım içindir.
Uzak ucun bağlantının kapanmasına izin vermek için ^ C'nin iletimine güvenmek yerine poll()
, öldürülen ssh
veya kapalı bağlantıyı algılamak için a yapan bir sargı kullanabilirsiniz .
Belki şöyle bir şey (basitleştirilmiş, bazı hata kontrolü eklemek isteyeceksiniz):
LC_HUP_DETECTOR='
use IO::Poll;
$SIG{CHLD} = sub {$done = 1};
$p = IO::Poll->new;
$p->mask(STDOUT, POLLIN);
$pid=fork; unless($pid) {setpgrp; exec @ARGV; die "exec: $!\n"}
$p->poll;
kill SIGHUP, -$pid unless $done;
wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8)
' ssh host 'perl -e "$LC_HUP_DETECTOR" some cmd'
$p->mask(STDOUT, POLLIN)
Yukarıdaki saçma görünebilir, ama fikir (kapalı olması stdout'ta borunun okuma sonda) bir asmak hup olay için beklemektir. İstenen maske olarak POLLHUP yoksayılır. POLLHUP yalnızca döndürülen olay olarak anlamlıdır ( yazma sonunun kapalı olduğunu söylemek için ).
Olay maskesi için sıfırdan farklı bir değer vermeliyiz. Eğer kullanırsak 0
, perl
aramaz bile poll
. Burada POLLIN kullanıyoruz.
Linux'ta, ne istersen, boru bozulursa, anket () POLLERR döndürür.
Borunun okuma ucu (ayrıca bir yazı sonudur orada) kapalıdır borular çift yönlüdür Solaris ve FreeBSD, üzerinde, bu Pollin istemek zorunda FreeBSD üzerinde POLLHUP (ve Pollin ile döner veya başka $p->poll()
yok dönüş).
Bu üç işletim sisteminin dışında ne kadar taşınabilir olduğunu söyleyemem.
parallel --tag -j1 'ssh -tt localhost perl/catch_wrap perl/catch_all_signals & sleep 1; killall -{} ssh' ::: {1..31}
ancak '-tt' öğesini kaldırın ve sonra çalışmaz.