Bagaimana cara mengakhiri jarak jauh yang disebut "tail -f" ketika koneksi ditutup?

24

Saya hanya memperhatikan bahwa jika saya mengeksekusi ssh user@remote_host tail -f /some/file, maka tail -f /some/fileterus berjalan di remote_host bahkan jika koneksi ssh ditutup!

Jadi, setelah beberapa terhubung dan terputus, jumlah berlari tail -f /some/filebertambah. Bagaimana cara mengakhiri tail -fsaat koneksi ssh ditutup?

Dmitry Frank
sumber

Jawaban:

33

Di

ssh host tail -f file

The sshklien terhubung ke sshdserver pada hostmelalui koneksi TCP. sshdberjalan tail -fdengan stdout diarahkan ke pipa. sshdmembaca apa yang datang dari ujung lain pipa dan merangkumnya dalam protokol sshd untuk dikirim ke sshklien. (dengan rshd, tailstdout akan menjadi soket secara langsung, tetapi sshdmenambahkan enkripsi dan mampu melipatgandakan beberapa aliran (seperti untuk pengalihan port / agen / X11 / terowongan, stderr) pada koneksi TCP tunggal sehingga harus menggunakan pipa).

Ketika Anda menekan CTRL-C, SIGINT dikirim ke sshklien. Itu menyebabkan sshmati. Setelah sekarat, koneksi TCP ditutup. Dan karena itu, pada host, sshdmati juga. tailtidak terbunuh, tetapi stdout sekarang menjadi pipa tanpa pembaca di ujung lainnya. Jadi, saat berikutnya ia menulis sesuatu pada stdout-nya, ia akan menerima SIGPIPE dan mati.

Di:

ssh -t host 'tail -f file'

Itu adalah hal yang sama kecuali bahwa alih-alih menggunakan pipa, komunikasi antara sshddan tailmelalui terminal semu. tailstdout adalah slave pseudo-terminal (seperti /dev/pts/12) dan tailtulisan apa pun yang ada readdi sisi master (mungkin dimodifikasi oleh disiplin garis tty) oleh sshddan dikirim dienkapsulasi ke sshklien.

Di sisi klien, dengan -t, sshmenempatkan terminal dalam rawmode. Khususnya, yang menonaktifkan mode kanonik terminal dan penanganan sinyal terminal.

Jadi, ketika Anda menekan Ctrl+C, alih-alih disiplin jalur terminal klien mengirimkan SIGINT ke sshpekerjaan, yang hanya mengirim ^Ckarakter melalui koneksi ke sshddan sshdmenulis itu ^Cke sisi master terminal jarak jauh. Dan garis disiplin terminal jarak jauh mengirim SIGINTke tail. tailkemudian mati, dan sshdkeluar dan menutup koneksi dan sshberakhir (jika tidak masih sibuk dengan penerusan port atau lainnya).

Juga, dengan -t, jika sshklien mati (misalnya jika Anda masuk ~.), koneksi ditutup dan sshdmati. Akibatnya, SIGHUP akan dikirim ke tail.

Berhati-hatilah karena penggunaan -tmemiliki efek samping. Misalnya, dengan pengaturan terminal default, \nkarakter dikonversi ke \r\ndan lebih banyak hal dapat terjadi tergantung pada sistem jarak jauh, sehingga Anda mungkin ingin mengeluarkan stty -opost(untuk menonaktifkan pemrosesan pasca-output) pada host jarak jauh jika output itu tidak dimaksudkan untuk terminal:

$ 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

Kelemahan lain dari menggunakan -t/ -ttadalah stdout dan stderr tidak dibedakan pada klien. Baik stdout dan stderr dari perintah remote akan ditulis ke sshstdout klien:

$ ssh localhost ls /x  | wc -l
ls: cannot access /x: No such file or directory
0
$ ssh -t localhost ls /x | wc -l
1
Stéphane Chazelas
sumber
Terima kasih banyak atas penjelasan yang terperinci! Saya berharap saya dapat menerima dua jawaban ..
Dmitry Frank
"with -t, jika sshklien mati (misalnya jika Anda masuk ~.)" Apa ~.lagi?
x-yuri
1
@ x-yuri, ~.adalah urutan keluar yang Anda masukkan untuk memutuskan koneksi klien. Lihat man sshdetailnya.
Stéphane Chazelas
11

Anda memerlukan alokasi terminal di sisi jarak jauh:

ssh -t user@remote_host tail -f /some/file

atau bahkan

ssh -tt user@remote_host tail -f /some/file
Hauke ​​Laging
sumber
1
Terima kasih, keduanya -tatau -ttberfungsi. Tetapi saya masih tidak dapat memahami alasan sebenarnya dari hal ini: katakanlah, ketika saya memanggil shell dari jarak jauh dan menutup koneksi, shell diakhiri. Tetapi tail -ftidak. Tentu saja saya sudah membaca tentang -topsi man ssh, tetapi tidak banyak membantu. Sepertinya saya tidak mengerti beberapa obat generik, dan saya akan senang jika Anda menyarankan beberapa dokumen untuk membacanya, atau mungkin menjelaskannya sendiri. Terima kasih!
Dmitry Frank
2
@ DmitryFrank Pemahaman saya adalah ini: Jika koneksi terputus maka sshdkirim a SIGHUP. Tetapi di mana tidak ada terminal, tidak ada hangup koneksi terminal ...
Hauke ​​Laging
Terima kasih, saya akan membaca tentang SIGHUPdan sinyal lainnya, masih tahu hampir tidak ada tentang itu.
Dmitry Frank
fyi: Saya baru saja mencoba lari tail -f, lalu saya sudah membuka htopdan mengirimnya SIGHUP(dengan menekan F9-> 1-> Enter), dan tail -fdiakhiri! Jadi, alasannya harus berbeda ..
Dmitry Frank
3
@DmitryFrank Anda salah paham masalah ini. Masalahnya bukan itu tailtidak mau bereaksi SIGHUP. Masalahnya adalah SIGHUP** tidak dikirim` ke tailtanpa terminal palsu. Anda dapat melihat bahwa dengan melampirkan straceke taildalam kedua kasus.
Hauke ​​Laging