Menghentikan output dari program yang dijalankan dalam sesi SSH SEKARANG

18

Masalah

Saya menjalankan perintah yang menghasilkan BANYAK informasi melalui SSH. Sebagai contoh, saya dengan bodohnya menambahkan informasi debug di dalam sebuah loop yang mengeksekusi jutaan kali, atau hanya menjalankan cat /dev/urandomuntuk tendangan.

Terminal dibanjiri informasi.

Contoh apa yang saya bicarakan

Saya ingin mengakhiri perintah ASAP dan memperbaiki program saya. Saya tidak peduli apa yang dicetaknya. Sekarang, masalahnya adalah saya menekan Ctrl+ CASAP (dalam contoh di atas saya menekannya segera setelah menjalankan perintah), tetapi masih butuh waktu untuk mencetak semua informasi yang bahkan tidak saya butuhkan .

Apa yang saya coba

Saya mencoba menekan Ctrl+ Csangat keras sehingga hasilnya lucu ketika terminal akhirnya menyusul:

OUTPUT HERE^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
^C^C

^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C

Saya juga membaca tentang Ctrl+ Syang tampaknya digunakan untuk memberitahu terminal "hentikan output, saya perlu mengejar" tetapi ternyata tidak melakukan apa-apa.

Detail lain-lain

Saya ingin tidak mengubah perintah yang saya jalankan sehingga saya dapat menyelamatkan diri saya dalam situasi apa pun, bahkan jika saya tidak ingat bahwa program yang saya jalankan dapat berakhir seperti itu.

Klien SSH saya berjalan pada Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) di MinTTY dengan tipe terminal diatur ke xterm-256color.

Server SSH berjalan pada Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux).

rr-
sumber
Di sistem mana Anda menjalankan program aktual yang menghasilkan output? Linux, Unix, atau Windows? Linux dan UNIX harus menerima Ctrl-O, yang berarti "membuang semua output yang ditulis ke terminal ini".
Mark Plotnick
Server berjalan pada Debian. Mengedit pertanyaan. Ctrl-O tampaknya tidak melakukan apa-apa juga. Mungkin itu masalah klien?
rr-
Anda dapat mencoba memulai xterm Anda dengan -jopsi, untuk mengaktifkan scroll scrolling. Masalah mendasarnya adalah bahwa kendali jarak jauh dapat mengirim data lebih cepat daripada yang dapat ditampilkan oleh jendela terminal - secara default, ia harus menggertak isi jendela setiap kali baris baru dicetak. Seluruh banyak data dapat di-buffered pada saat Ctrl-C Anda diterima oleh sistem jarak jauh, dan program terminal Anda akan mencoba menampilkan semuanya.
Mark Plotnick
Hanya sebuah ide: jika Anda memiliki beberapa perintah persis yang biasanya Anda jalankan secara tidak sengaja dan mereka menghasilkan banyak output, mengapa tidak menambahkan beberapa alias saja .bashrc?
psimon
Anda bisa menggunakan mosh alih-alih ssh: mosh.mit.edu
gmatht

Jawaban:

5

Sebagian dari output itu akan di-buffer. Anda mengirim Ctrl+ Anda Cke ujung jarak jauh yang mengganggu program yang sedang berjalan. Program tersebut ada dan shell mengirim karakter untuk menunjukkan kepada Anda prompt lagi. Sebelum prompt ditampilkan, layar Anda akan terlebih dahulu menampilkan semua data yang disangga dan sudah ada di dekat Anda.

Yang Anda minta adalah agar program berhenti dan data dalam perjalanan entah bagaimana menghilang. Itu tidak bisa terjadi karena sudah dalam perjalanan.

Satu-satunya cara Anda dapat memastikan bahwa Anda tidak melihat data ini adalah keluar dari terminal di ujung Anda dan kemudian menyambung kembali ke remote Anda - tetapi itu mungkin jauh lebih banyak upaya daripada menunggu data buffered untuk ditampilkan.

garethTheRed
sumber
10

Saya biasanya menjalankan output lesssehingga saya dapat membunuhnya melalui lessmenggunakan qkunci.

$ cmd | less

Contoh

$ cat /dev/urandom | less

   ss # 2

Setelah menekan q+, Enteria akan berhenti dan kembali ke terminal normal Anda, membiarkannya bagus dan bersih.

Mengapa itu terjadi?

Masalah yang Anda temui adalah bahwa ada buffer (untuk STDOUT) yang sedang antri dengan output tampilan Anda. Buffer ini diisi dengan begitu cepat sehingga Anda tidak dapat menghentikannya dengan cukup cepat untuk menghentikannya.

                                    ss # 1

Untuk menonaktifkan / membatasi efek ini, Anda dapat menonaktifkan buffer STDOUT yang seharusnya membuat hal-hal menjadi sedikit lebih responsif digunakan stdbuf, tetapi Anda mungkin harus bermain dengan pengaturan ini untuk mendapatkan hal-hal seperti yang Anda inginkan. Untuk membatalkan STDOUT Anda dapat menggunakan perintah ini:

$ stdbuf -o0 <cmd>

Halaman manual untuk stdbufperincian opsi yang Anda inginkan:

    If MODE is 'L' the corresponding stream will be line buffered.  This 
    option is invalid with standard input.

    If MODE is '0' the corresponding stream will be unbuffered.

    Otherwise MODE is a number which may be followed by one of the 
    following: KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so
    on for G, T, P, E, Z, Y.  In this case the corresponding stream will be 
    fully buffered with the  buffer  size  set  to  MODE
    bytes.

Untuk latar belakang yang bagus tentang cara kerja buffering, saya sangat menyarankan untuk melihat pada Beat Pixel yang diartikulasikan berjudul: buffering dalam stream standar . Itu bahkan termasuk gambar yang bagus.

Referensi

slm
sumber
Itu wajar selama Anda ingat untuk menambahkan |lesske cmd, yang sayangnya saya sering tidak. Jika Anda menjalankan cmd, Anda masih harus menunggu sampai selesai hasil pencetakan dihitung sebelum menerima ^C.
rr-
1
Itu tidak benar-benar menjelaskan apa yang terjadi. Lagi pula, tidak ada pipa yang terlibat, jadi buffer apa yang Anda maksud?
Gilles 'SO- berhenti bersikap jahat'
@Gilles - maaf, buffer akan menjadi buffer ke layar.
slm
Buffer apa? Di dalam kernel? Dalam xterm?
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles - beri saya waktu sebentar, saya mencari detailnya 8-)
slm
3

Ada beberapa level buffering. Ketika Anda menekan Ctrl+ C, ini menghentikan program dari memancarkan data ke terminal. Ini tidak memengaruhi data yang belum ditampilkan oleh emulator terminal.

Saat Anda menampilkan data dengan kecepatan sangat tinggi, terminal tidak dapat mengikuti dan akan tertinggal. Itulah yang terjadi di sini: menampilkan teks jauh lebih mahal daripada menghasilkan angka acak ini. Ya, bahkan dengan font bitmap - menghasilkan angka acak berkualitas kriptografis sangat murah dibandingkan. (Saya baru saja mencoba pada mesin saya dan proses X menjenuhkan CPU, dengan xtermmengambil beberapa% dan cat(dimana generasi angka acak dihitung) hampir tidak mencapai 1%. Dan itu dengan font bitmap.)

Jika Anda ingin ini berhenti sekarang, bunuh terminal emulator. Jika Anda tidak ingin melakukan itu, setidaknya perkecil jendela; emulator terminal cerdas (seperti xterm) tidak akan memetakan jendela, yang menghemat waktu CPU X, sehingga sampah akan selesai menampilkan lebih cepat. Server X memiliki prioritas tinggi, jadi ini akan membuat perbedaan besar pada respons mesin Anda saat xterm memproses data di latar belakang.

Ketika semua ini terjadi di shell jauh, lag bahkan lebih buruk, karena data yang dihasilkan catharus terlebih dahulu melalui koneksi SSH. Pers Anda Ctrl+ Cjuga harus melalui koneksi SSH; itu mendapat prioritas yang agak lebih tinggi (itu dikirim keluar dari band), tetapi itu masih membutuhkan waktu di mana lebih banyak output menumpuk. Tidak ada cara untuk menekan data dalam perjalanan sebelum menutup koneksi SSH (yang dapat Anda lakukan dengan menekan Enteritu ~.).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Masalahnya terkait dengan SSH bersama. Buffer STDOUT tidak boleh digunakan dalam mode interaktif tetapi SSH tidak dapat menangani mode interaktif dengan benar. Meskipun banyak output mungkin hang dalam transaksi, itu adalah proses SSH yang menerima Ctrl + C jadi itu adalah tanggung jawabnya untuk membunuh output ketika tidak mungkin untuk melewatkan Ctrl + C ke remote.
user4674453
@ user4674453 Eh? Ctrl + C tidak seharusnya mematikan output lokal. Itu bukan tugasnya sama sekali. Seharusnya diteruskan ke sisi jarak jauh, yang mungkin atau mungkin tidak membunuh proses jarak jauh.
Gilles 'SO- stop being evil'
"Seharusnya diteruskan ke sisi jarak jauh, yang mungkin atau mungkin tidak membunuh proses jarak jauh." - tidak seharusnya melakukan itu juga. Sinyal KILL, Ctrl + C mengeluarkan salah satunya, hanya untuk proses lokal. Jika tidak digunakan untuk proses lokal, gagasan "seharusnya" tidak berlaku sama sekali.
user4674453
@ user4674453 Tidak. Ctrl + C bukan sinyal mematikan. Itu sinyal interupsi. Perannya adalah untuk kembali ke prompt interaktif. Ini hanya membunuh program yang tidak memiliki prompt interaktif untuk kembali.
Gilles 'SO- stop being evil'
"Itu sinyal interupsi." Ini adalah argumen untuk membunuh perintah, maka itu adalah sinyal bunuh. Kadang-kadang itu disebut sebagai sinyal POSIX jika Anda suka. "Perannya adalah untuk kembali ke prompt interaktif. Ini hanya membunuh program yang tidak memiliki prompt interaktif untuk kembali." Persis!!! Dan SSH tidak melakukan itu seperti yang diharapkan.
user4674453
1

Ini harus cukup untuk menemukan cara untuk killyang catperintah.
Untuk proposal berikut, Anda mungkin perlu koneksi ssh kedua terbuka.

  • Jarang CTRL+zbisa lebih efektif daripada CTRL+c: ia bisa menjawab lebih cepat. Setelah itu Anda menangguhkan perintah Anda dapat membunuhnya dengan kill %1atau apa pun nomor pekerjaannya.
    Ini dengan harapan bahwa Anda masih dapat membaca apa pun dari layar (teks biner acak flooding dapat dengan mudah mengacaukan set karakter Anda).
    Seperti yang diingat oleh Gilles jika Anda meminimalkan jendela, mungkin sistem akan lebih cepat membaca permintaan interupsi daripada mematikan prosesnya. Jadi menangguhkan / mematahkan, memperkecil, menunggu sebentar, memaksimalkan lagi, bisa menjadi solusi juga.
    Tentu saja melalui koneksi ssh, saya berharap Anda perlu menunggu beberapa saat.

  • Di terminal / sesi lain Anda dapat bertanya pgrep cat(apakah cat adalah perintah yang dipanggil) dan mengidentifikasi proses cat menggunakan lebih banyak cpu Anda. Anda dapat mengidentifikasinya dengan lebih presisi dengan pstree:

    pgrep cat | awk '{print "pstree -sp" $ 1}' | sh | grep sshd

    jawab dengan output seperti

    init (1) ───sshd (1062) ───sshd (22884) ───sshd (22951) ───bash (22957) ───cat (23131)

    Dalam hal ini, setelah Anda hanya perlu membunuh PID kucing: bunuh 23131

catatan:

Cepat
sumber
1

Saya memiliki masalah yang sama dan tidak puas dengan jawaban di sini jadi saya menggali lebih dalam. Orang lain telah menyebutkan bahwa perintah Anda adalah mengeluarkan data lebih cepat dari yang dapat diambil ssh, sehingga buffer data, dan buffer tidak dapat dihentikan.

Untuk memperbaiki ini, hindari buffering dengan membatasi output perintah Anda ke tingkat maksimum yang bisa diambil oleh sesi ssh Anda, perintah sudah ada untuk melakukan ini.

Pengaturan, pertama cari tahu tingkat maksimum sesi Anda:

# Get transfer <TIME> of a large file (>10MB preferable)
/usr/bin/time -f "%e" cat <FILENAME>

# Get file <SIZE> in bytes
stat --printf="%s\n" <FILENAME>

# Calculate <RATE>
echo "<SIZE> / <TIME>" | bc

Akhirnya, tetapkan sesuai perintah Anda yang sebenarnya.

<YOUR_COMMAND> | pv -qL <RATE>

Contoh:

/usr/bin/time -f "%e" cat large_reference_file.txt
31.26

stat --printf="%s\n" cat large_reference_file.txt
17302734

echo "17302734 / 31.26" | bc
553510

# Throttle my command to 553510B/s
cat some_other_file.txt | pv -qL 553510

Anda mungkin ingin mengurangi RATE sedikit jika kecepatan koneksi Anda sedikit menurun dari waktu ke waktu. Jika menurun, perilaku akan kembali ke masalah, ctrl-c yang tidak responsif.

Alias ​​kucing tercekik opsional:

# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'

# tcsh
alias tcat 'cat \!* | pv -qL 400k'

# usage: tcat <FILENAME>

Sekarang ctrl-c berfungsi seperti yang diharapkan, segera mematikan output karena sangat sedikit jika ada buffer.

Eric
sumber
catoutput jarang menjadi masalah, tidak seperti perangkat lunak lain. Penulis hanya menggunakannya sebagai contoh. Masalahnya biasanya karena perangkat lunak lain yang mungkin tidak jelas jika bersedia menghasilkan banyak output. Menggunakan segala macam perintah awalan atau postfix bukanlah solusi, karena butuh waktu untuk mengetiknya. Tidak akan ada keuntungan apa pun dalam hasil.
user4674453
0

Ada perangkat lunak di Linux yang memecahkan masalah ini (beberapa hal lainnya juga). Anda juga dapat memintanya dari terminal emulator di Windows (Anda tampaknya menggunakan Windows?).

Coba mosh , pengganti biner SSH. Ia bekerja persis seperti SSH (Anda dapat melakukan mosh user@hostnamealih - alih ssh user@hostnamedan itu akan bekerja persis seperti yang Anda harapkan, bahkan akan melakukan otentikasi kunci pribadi dll.

Ini pada dasarnya menjalankan proses terpisah pada server yang mendukung paket. Jadi ketika Anda menekan Ctrl + C pada mosh, itu akan menyampaikan ini ke server jauh, yang kemudian akan berhenti mengirim informasi tambahan. Selain itu, itu juga akan memprediksi hasil penekanan tombol, menghemat beberapa milidetik setiap kali Anda menekan tombol.

Kelemahan: Saat ini tidak mungkin untuk menggulir ke atas dalam riwayat saat menggunakan mosh.

Saksham Sharma
sumber