Dapatkan ssh untuk meneruskan sinyal

22

Saya ingin dapat mengirim sinyal (SIGINT adalah yang paling penting) melalui ssh.

Perintah ini:

ssh server "sleep 1000;echo f" > foo

akan mulai tidur di server dan setelah 1000 detik akan meletakkan 'f \ n' di file foo di mesin lokal saya. Jika saya menekan CTRL-C (yaitu mengirim SIGINT ke ssh) itu akan mematikan ssh, tetapi tidak akan mematikan sleep di server jauh. Saya ingin mematikan tidur di server jauh.

Jadi saya mencoba:

ssh server -t "sleep 1000;echo f" > foo

Tetapi jika stdin bukan terminal saya mendapatkan kesalahan ini:

Pseudo-terminal will not be allocated because stdin is not a terminal.

dan kemudian SIGINT masih belum diteruskan.

Jadi saya mencoba:

ssh server -t -t "sleep 1000;echo f" > output

Tapi kemudian output di foo bukan 'f \ n' tetapi sebaliknya 'f \ r \ n' yang merupakan bencana dalam situasi saya (karena output saya adalah data biner).

Di atas saya menggunakan "sleep 1000; echo f", tetapi pada kenyataannya yang disediakan oleh pengguna, sehingga dapat berisi apa saja. Namun, jika kita dapat membuatnya berfungsi untuk "sleep 1000; echo f" kita kemungkinan besar dapat membuatnya bekerja untuk semua situasi yang realistis.

Saya benar-benar tidak peduli tentang mendapatkan terminal semu di ujung lain, tetapi saya tidak dapat menemukan cara lain untuk mendapatkan ssh untuk meneruskan SIGINT saya.

Apakah ada cara lain?

Edit:

Pengguna dapat memberikan perintah yang membaca data biner dari stdin, seperti:

seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo

Pengguna dapat memberikan perintah yang intensif cpu, seperti:

ssh server "timeout 1000 burnP6"

Sunting2:

Versi yang sepertinya berfungsi untuk saya adalah:

your_preprocessing |
  uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
  uuencode a" | uudecode -o - |
your_postprocessing

Terima kasih kepada digital_infinity karena mengarahkan saya ke arah yang benar.

Ole Tange
sumber
1
Saya pikir penggunaan aktual Anda sshharus lebih rumit daripada apa yang Anda tunjukkan sebagai contoh, karena Anda bisa mendapatkan perilaku yang Anda inginkan dengan penataan ulang sederhana: sleep 1000 && ssh server "echo f" > foo(Itu harus &&, tidak ;, sehingga pembunuhan sleepmencegah sshperintah untuk menjalankan.) Jika saya Benar, tolong jadikan contoh Anda lebih representatif dari penggunaan Anda yang sebenarnya, sehingga jawaban yang lebih baik dapat diberikan.
Warren Young
Benar: sleep dan echo sebenarnya adalah skrip yang disediakan pengguna dan tidak benar-benar sleep dan echo. Jadi kita tidak tahu apa yang mereka lakukan dan harus menganggap yang terburuk.
Ole Tange
Sooo ... Anda akan datang dengan contoh perintah yang lebih baik, kan? Di mana penataan ulang sederhana tidak memperbaiki masalah? Anda mengajukan pertanyaan yang bagus, dan saya ingin jawaban itu dijawab, tetapi Anda cenderung tidak mendapatkan jawaban jika "jadi jangan lakukan itu," adalah jawaban yang masuk akal.
Warren Young
Oh, omong-omong ... Jangan lakukan itu;)
Tim
Seperti dijelaskan dalam pertanyaan: "" "Di atas saya menggunakan" sleep 1000; echo f ", tetapi pada kenyataannya yang disediakan oleh pengguna, sehingga dapat berisi apa saja" ""
Ole Tange

Jawaban:

10

Jawaban singkat:

ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo

dan hentikan program dengan CTRL + N.

Penjelasan panjang:

  1. Anda harus menggunakan sttyopsi intruntuk mengubah server atau karakter interupsi lokal agar tidak saling bertabrakan. Pada perintah di atas saya telah mengubah karakter interupsi server menjadi CTRL + N. Anda dapat mengubah karakter interupsi lokal dan membiarkan karakter server tanpa perubahan.
  2. Jika Anda tidak ingin karakter interupsi berada di output Anda (dan karakter kontrol lainnya) gunakan stty -echoctl.
  3. Anda harus memastikan bahwa karakter kontrol diaktifkan pada server bash yang dipanggil oleh sshd. Jika tidak, Anda bisa berakhir dengan proses yang masih berkeliaran setelah Anda keluar.stty isig
  4. Anda benar-benar menangkap SIGINTsinyal trap '/bin/true' SIGINTdengan pernyataan kosong. Tanpa jebakan, Anda tidak akan memiliki stdout setelah sinyal SIGINT di ujung Anda.
digital_infinity
sumber
Tampaknya tidak berurusan dengan baik dengan input biner: seq 1000 | gzip | ssh -t -t server "stty isig intr ^ N -echoctl; trap '/ bin / true' SIGINT; sleep 1; zcat | bzip2" | bzcat> foo;
Ole Tange
Anda tidak dapat menginterupsi dengan konsol jika Anda menetapkan input standar untuk ssh untuk sesuatu selain konsol. Dalam hal ini Anda harus menginterupsi oleh aliran stdin.
digital_infinity
Saya menemukan bahwa ini seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > footidak berhasil juga. Agar perintah ini berfungsi, kita perlu menghapus -tt. Jadi alokasi terminal semu mungkin mengambil beberapa input dari stdin
digital_infinity
Saya mencoba uuencode. Dalam versi ini tidak berfungsi: cat foo.gz | perl -ne 'paket cetak ("u", $ _)' | ssh -t -t server 'perl -ne "print unpack (\" u \ ", \ $ _)" | zcat | gzip | perl -ne "paket cetak (\" u \ ", \ $ _)" '| perl -ne 'print unpack ("u", $ _)'> foo2.gz
Ole Tange
1
Aku punya ini: (sleep 1; seq 1000 ) | gzip | uuencode bin | ssh -tt dell-test "stty isig intr ^N -echoctl -echo ; trap '/bin/true' SIGINT; sleep 1; uudecode -o /dev/stdout | zcat |bzip2 | uuencode bin2 " | uudecode -o /dev/stdout | bzcat >foo. Walaupun karakter interrupt tidak berfungsi - kita memerlukan beberapa metode transmisi untuk karakter interrupt ketika stdin sibuk .
digital_infinity
3

Saya mencoba semua solusi dan ini yang terbaik:

ssh host "sleep 99 < <(cat; kill -INT 0)" <&1

/programming/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610

Eric Woodruff
sumber
Itu tidak menghentikan sleepproses jika koneksi terputus.
blueyed
Ketika koneksi terputus, stdin rusak membuka blokir kucing yang akan membunuh kelompok proses. Apakah sinyal INTerrupt cukup baik untuk tugas Anda adalah pertanyaan yang berbeda.
Eric Woodruff
Itu harus cukup baik untuk itu sleep, bukan? Saya telah menambahkan beberapa date >> /tmp/killedsetelah cat, tetapi tidak dipicu. Apakah ada batas waktu? Saya menggunakan Zsh secara normal, tetapi juga mengujinya dengan bash sebagai shell login jarak jauh.
blueyed
Saya pikir Anda berada di bawah batas waktu koneksi.
Eric Woodruff
Apakah ada pengaturan untuk mengontrol ini? Untuk sisi klien -o ServerAliveInterval=3 -o ServerAliveCountMax=2memungkinkan untuk mendeteksi dengan cepat, tetapi apakah ada sesuatu untuk sisi server?
blueyed
2

Saya pikir Anda bisa menemukan PID dari proses yang Anda jalankan di server dan mengirim sinyal menggunakan sshperintah lain (seperti ini ssh server "kill -2 PID":).

Saya menggunakan metode ini untuk mengirim sinyal konfigurasi ulang ke aplikasi yang berjalan pada mesin yang berbeda (aplikasi saya menangkap SIGUSR1 dan membaca file konfigurasi). Dalam kasus saya, menemukan PID itu mudah, karena saya memiliki nama proses yang unik dan saya dapat menemukan PID dengan mengirimkan pspermintaan melalui ssh.

Saeedn
sumber
Saya tidak melihat cara bukti peluru untuk menemukan PID dari program yang dijalankan pada jarak jauh. Ingat itu diberikan oleh pengguna. Bisa jadi: ssh server 'exec $ (echo fyrrc 1000 | / usr / games / rot13)'
Ole Tange
1

Solusinya berkembang menjadi http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr

$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
    # Make own process group to be able to kill HUP it later
    setpgrp;
    exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV");
    die "exec: $!\n";
}
do {
    # Parent is not init (ppid=1), so sshd is alive
    # Exponential sleep up to 1 sec
    $s = $s < 1 ? 0.001 + $s * 1.03 : $s;
    select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)
Ole Tange
sumber
0

----- command.sh

#! /bin/sh
trap 'trap - EXIT; kill 0; exit' EXIT
(sleep 1000;echo f) &
read ans

----- di terminal lokal

sleep 864000 | ssh -T server command.sh > foo
tamu
sumber
Hai! Saya pikir Anda bisa membuat jawaban Anda jauh lebih berguna dengan menjelaskan, sedetail yang Anda anggap relevan, bagaimana cara kerjanya. Jangan ragu untuk mengeditnya untuk memasukkan informasi baru.
Dhag