Saya tidak berpikir Anda bisa mengatasi itu.
Dengan -tt
, sshd
memunculkan terminal pseudo dan menjadikan slave sebagai stdin, stdout dan stderr dari shell yang mengeksekusi perintah remote.
sshd
membaca apa yang datang dari (tunggal) fd ke bagian master dari pseudo-terminal dan mengirimkannya (melalui satu saluran tunggal) ke ssh
klien. Tidak ada saluran kedua untuk stderr karena tidak ada -t
.
Selain itu perhatikan bahwa disiplin garis terminal pseudo-terminal dapat (dan akan secara default) mengubah output. Misalnya LF akan dikonversi ke CRLF di sana dan tidak di terminal lokal, jadi Anda mungkin ingin menonaktifkan output pasca-pemrosesan.
$ 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
Lebih banyak hal akan terjadi pada sisi input (seperti ^C
karakter yang akan menyebabkan SIGINT, tetapi juga sinyal lain, gema dan semua penanganan yang terlibat dalam editor baris mode kanonik ).
Anda mungkin bisa mengarahkan stderr ke fifo dan mengambilnya menggunakan yang kedua ssh
:
ssh -tt host 'mkfifo fifo && cmd 2> fifo' &
ssh host 'cat fifo' >&2
Tetapi IMO terbaik adalah untuk menghindari menggunakan -t
sama sekali. Itu benar-benar hanya dimaksudkan untuk penggunaan interaktif dari terminal nyata.
Alih-alih mengandalkan transmisi ^ C untuk membiarkan remote control koneksi ditutup, Anda bisa menggunakan pembungkus yang berfungsi poll()
untuk mendeteksi ssh
koneksi yang terbunuh atau tertutup.
Mungkin sesuatu seperti (disederhanakan, Anda ingin menambahkan beberapa pengecekan kesalahan):
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'
Hal di $p->mask(STDOUT, POLLIN)
atas mungkin terlihat konyol, tetapi idenya adalah menunggu acara hang-hup (agar ujung pipa pembacaan pada stdout ditutup). POLLHUP sebagai topeng yang diminta diabaikan. POLLHUP hanya bermakna sebagai acara yang dikembalikan (untuk mengatakan bahwa akhir penulisan telah ditutup).
Kami harus memberikan nilai bukan nol untuk masker acara. Jika kita menggunakan 0
, perl
bahkan tidak menelepon poll
. Jadi di sini kita menggunakan POLLIN.
Di Linux, apa pun yang Anda minta, jika pipa menjadi rusak, poll () mengembalikan POLLERR.
Pada Solaris dan FreeBSD, di mana pipa dua arah, ketika ujung pembacaan pipa (yang juga merupakan akhir tulisan) ditutup, ia kembali dengan POLLHUP (dan POLLIN di FreeBSD, di mana Anda harus meminta POLLIN atau yang lain $p->poll()
tidak kembali).
Saya tidak bisa mengatakan seberapa portabelnya di luar ketiga sistem operasi itu.
parallel --tag -j1 'ssh -tt localhost perl/catch_wrap perl/catch_all_signals & sleep 1; killall -{} ssh' ::: {1..31}
:, tetapi hapus '-tt' dan kemudian tidak berfungsi.-tt
setelah diedit. Harap diingat jika Anda tidak menjalankan perintah melalui paralel, ssh akan mewarisi terminal tempat Anda menjalankannya.-t
, saya berharap itu tidak berhasil.Untuk membuatnya bekerja pada platform lain, ini menjadi solusi terakhir. Ia memeriksa apakah klien ssh terputus dan dengan demikian orang tua menjadi pid 1:
sumber