Bagaimana cara cepat menghentikan proses yang menyebabkan meronta-ronta (karena alokasi memori berlebih)?

19

Kita semua pernah mengalaminya - beberapa program diminta untuk melakukan sesuatu yang membutuhkan banyak memori. Itu dengan patuh mencoba mengalokasikan semua memori ini, dan sistem segera mulai meronta-ronta, bertukar tanpa henti dan menjadi lamban atau tidak responsif.

Baru-baru ini saya mengalami ini pada laptop Ubuntu saya karena skrip Matlab mencoba mengalokasikan matriks yang sangat besar. Setelah ~ 5 + menit meronta-ronta, saya bisa Ctrl-F1 ke konsol dan membunuh Matlab. Saya lebih suka memiliki beberapa hot-key yang akan memberi saya kontrol sistem segera dan memungkinkan saya untuk membunuh proses yang menyinggung; atau, mungkin, secara diam-diam menolak untuk mengalokasikan buffer sebesar itu.

  1. Apa cara tercepat untuk mendapatkan kembali kendali atas sistem Linux yang telah menjadi tidak responsif atau sangat lamban karena bertukar yang berlebihan?

  2. Adakah cara yang efektif untuk mencegah swapping terjadi di tempat pertama, misalnya dengan membatasi jumlah memori proses yang diizinkan untuk mencoba mengalokasikan?

nibot
sumber

Jawaban:

12

Tekan Alt-SysRq-F untuk mematikan proses menggunakan sebagian besar memori:

  • Kunci SysRq biasanya dipetakan ke tombol Print.
  • Jika Anda menggunakan desktop grafis, Anda mungkin perlu menekan Ctrl-Alt-SysRq-F jika menekan Alt-SysRq memicu tindakan lain (misalnya program snapshot).
  • Jika Anda menggunakan laptop, Anda mungkin perlu menekan tombol fungsi juga.
  • Untuk informasi lebih lanjut baca artikel wikipedia .
lelucon
sumber
5

Saya telah membuat skrip untuk tujuan ini - https://github.com/tobixen/thrash-protect

Saya sudah menjalankan skrip ini di server produksi, workstation dan laptop dengan kesuksesan yang baik. Skrip ini tidak mematikan proses, tetapi menunda sementara - saya memiliki beberapa situasi kemudian di mana saya cukup yakin saya akan kehilangan kendali karena meronta-ronta jika bukan karena skrip sederhana ini. Dalam kasus "terburuk" proses pelanggaran akan banyak diperlambat dan pada akhirnya akan dibunuh oleh kernel (OOM), dalam kasus "terbaik" proses pelanggaran akan benar-benar menyelesaikan ... dalam hal apa pun, server atau workstation akan tetap relatif responsif sehingga mudah untuk menyelidiki situasinya.

Tentu saja, "beli lebih banyak memori" atau "jangan gunakan swap" adalah dua alternatif, jawaban yang lebih tradisional pada pertanyaan "bagaimana menghindari meronta-ronta?", Tetapi secara umum mereka cenderung tidak bekerja dengan baik (menginstal lebih banyak memori dapat menjadi non-sepele, proses jahat dapat memakan semua memori tidak peduli berapa banyak yang telah diinstal, dan seseorang dapat masuk ke masalah-masalah bahkan tanpa swap ketika tidak ada cukup memori untuk buffering / caching). Saya merekomendasikan thrash-protect plus banyak ruang swap.

tobixen
sumber
Tentang menonaktifkan swap, menurut unix.stackexchange.com/a/24646/9108 itu mungkin bukan pilihan terbaik.
sashoalm
Memang, seseorang mengomentari hal yang sama pada saya, jadi saya telah memodifikasi doc perlindungan-thrash pada saat itu.
tobixen
4
  1. Apa cara tercepat untuk mendapatkan kembali kendali atas sistem Linux yang telah menjadi tidak responsif atau sangat lamban karena bertukar yang berlebihan?

Sudah dijawab di atas dengan Alt-SysRq-F

  1. Adakah cara yang efektif untuk mencegah swapping terjadi di tempat pertama, misalnya dengan membatasi jumlah memori proses yang diizinkan untuk mencoba mengalokasikan?

Saya menjawab bagian ke-2 ini. Ya, ulimitmasih berfungsi cukup baik untuk membatasi satu proses. Kamu bisa:

  • menetapkan batas lunak untuk suatu proses yang Anda tahu kemungkinan akan lepas kendali
  • menetapkan batas keras untuk semua proses jika Anda ingin asuransi tambahan

Juga, sebagaimana disebutkan secara singkat:

Anda dapat menggunakan CGroups untuk membatasi penggunaan sumber daya dan mencegah masalah seperti itu

Memang, cgroup menawarkan kontrol yang lebih maju, tetapi saat ini lebih rumit untuk dikonfigurasi menurut pendapat saya.

Ulimit sekolah tua

Sekali off

Inilah contoh sederhana:

$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)

Itu:

  • Menetapkan batas lunak penggunaan memori keseluruhan 1GB (ulimit mengasumsikan batas dalam satuan kB)
  • Menjalankan panggilan fungsi bash rekursif r2(){ r2 $@$@;};r2 r2yang akan secara eksponensial mengunyah CPU dan RAM dengan menggandakan dirinya secara tak terbatas sambil meminta memori tumpukan.

Seperti yang Anda lihat, itu terhenti ketika mencoba untuk meminta lebih dari 1GB.

Catatan, -vberoperasi pada alokasi memori virtual (total, yaitu fisik + swap).

Perlindungan permanen

Untuk membatasi alokasi memori virtual, asadalah setara dengan -vuntuk limits.conf.

Saya melakukan hal berikut untuk melindungi dari proses pelanggaran tunggal:

  • Tetapkan batas ruang alamat keras untuk semua proses.
  • address space limit = <physical memory> - 256MB.
  • Oleh karena itu, tidak ada proses tunggal dengan penggunaan memori serakah atau loop aktif dan kebocoran memori dapat mengkonsumsi SEMUA memori fisik.
  • Ruang kepala 256MB ada untuk pemrosesan penting dengan ssh atau konsol.

Satu liner:

$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"

Untuk memvalidasi, ini menghasilkan yang berikut (misalnya pada sistem 16GB):

$ cat /etc/security/limits.d/mem.conf
*   hard    as      16135196
$ ulimit -H -v
161351960

Catatan:

  • Hanya memitigasi terhadap satu proses tunggal yang berlebihan dengan penggunaan memori.
  • Tidak akan mencegah beban kerja multi-proses dengan tekanan memori yang besar yang menyebabkan meronta-ronta (cgroup kemudian jawabannya).
  • Jangan gunakan rssopsi dalam membatasi.conf. Ini tidak dihormati oleh kernel yang lebih baru.
  • Itu konservatif.
    • Secara teori, suatu proses dapat secara spekulatif meminta banyak memori tetapi hanya secara aktif menggunakan subset (set kerja yang lebih kecil / penggunaan memori penduduk).
    • Batas keras di atas akan menyebabkan proses tersebut dibatalkan (bahkan jika mereka mungkin telah berjalan dengan baik mengingat Linux memungkinkan ruang alamat memori virtual menjadi terlalu padat).

CGroup yang lebih baru

Menawarkan lebih banyak kontrol, tetapi saat ini lebih kompleks untuk digunakan:

  • Memperbaiki penawaran ulimit.
    • memory.max_usage_in_bytes dapat menghitung dan membatasi memori fisik secara terpisah.
    • Sedangkan ulimit -mdan / atau rssdalam limits.confdimaksudkan untuk menawarkan fungsionalitas yang serupa, tetapi itu tidak berfungsi sejak kernel Linux 2.4.30!
  • Perlu mengaktifkan beberapa bendera kernel cgroup di bootloader: cgroup_enable=memory swapaccount=1.
    • Ini tidak terjadi secara default dengan Ubuntu 16.04.
    • Mungkin karena beberapa implikasi kinerja overhead akuntansi tambahan.
  • hal-hal cgroup / systemd relatif baru dan mengubah sedikit, sehingga fluks hulu menyiratkan vendor distro Linux belum membuatnya mudah digunakan. Antara 14.04LTS dan 16.04LTS, tooling ruang pengguna untuk menggunakan cgroup telah berubah.
    • cgm sekarang tampaknya menjadi alat userspace yang didukung secara resmi.
    • file unit systemd tampaknya belum memiliki standar "vendor / distro" yang telah ditentukan sebelumnya untuk memprioritaskan layanan penting seperti ssh.

Misalnya untuk memeriksa pengaturan saat ini:

$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...

Misalnya untuk membatasi memori satu proses:

$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed

Untuk melihatnya beraksi mengunyah RAM sebagai proses latar belakang dan kemudian terbunuh:

$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
 0.0  0.0  2876
 102  0.2 44056
 103  0.5 85024
 103  1.0 166944
 ...
98.9  5.6 920552
99.1  4.3 718196
[1]+  Killed                  bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'

Perhatikan pertumbuhan permintaan memori yang eksponensial (kekuatan 2).

Di masa depan, mari kita berharap untuk melihat "distro / vendor" pra-konfigurasi prioritas dan batasan cgroup (melalui unit systemd) untuk hal-hal penting seperti SSH dan tumpukan grafis, sehingga mereka tidak pernah kehabisan memori.

JPvRiel
sumber
2

Anda mungkin dapat menekan Ctrl- zuntuk menunda program. Kemudian Anda dapat melakukan kill %1(atau apa pun nomor pekerjaan itu atau Anda dapat menggunakan PID).

Anda dapat menggunakan ulimitperintah untuk mencoba membatasi jumlah memori yang tersedia untuk suatu proses.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
Ctrl-Z itu bagus, tetapi biasanya saya menjalankan Matlab GUI dan kehilangan jejak terminal pengendali, jadi tidak ada cara mudah untuk mengeluarkan penekanan tombol Ctrl-Z. Alangkah baiknya jika GUI memiliki kunci panas untuk mengirim SIGSTOP ke aplikasi apa pun yang memiliki fokus!
nibot
Anda dapat menjalankan kill -STOP <pid>yang akan melakukan hal yang sama dengan Ctrl-Z.
hlovdal
Ya, tetapi seluruh masalahnya adalah bahwa, dalam situasi seperti itu, sistem ini sangat tidak responsif sehingga butuh waktu lama (atau selamanya) untuk sampai ke command prompt.
nibot
1

Anda dapat menggunakan CGroups untuk membatasi penggunaan sumber daya dan mencegah masalah seperti itu: https://en.wikipedia.org/wiki/Cgroups

1kenthomas
sumber
Harap sertakan informasi penting dalam jawaban Anda dan gunakan tautan hanya untuk atribusi dan bacaan lebih lanjut. Tautan itu menjelaskan apa itu CGroup, tetapi tidak jelas dari tautan bagaimana sebenarnya menggunakannya untuk menyelesaikan masalah. Bisakah Anda memperluas jawaban Anda untuk menjelaskan solusi untuk pertanyaan itu? Terima kasih.
fixer1234
0

Alangkah baiknya jika GUI memiliki kunci panas untuk mengirim SIGSTOP ke aplikasi apa pun yang memiliki fokus!

Selalu ada xkillperintah klasik (dari xorg-x11-apps-7.4-14.fc14.src.rpm di sistem saya). Saya kira seharusnya tidak terlalu sulit untuk membuat klon yang mengirim SIGSTOP daripada membunuh jendela target.

hlovdal
sumber
Bagaimana saya bisa membuat xkill memulai dengan cepat dengan menekan beberapa kombinasi tombol?
nibot
Saya tidak yakin. Saya berasumsi baik gnome dan KDE memiliki beberapa fungsionalitas pintasan global yang dapat digunakan untuk meluncurkan program.
hlovdal