Secara otomatis mematikan proses jika melebihi jumlah RAM yang diberikan

12

Saya bekerja pada dataset skala besar. Saat menguji perangkat lunak baru, sebuah skrip terkadang akan menyelinap ke saya, dengan cepat mengambil semua RAM yang tersedia, dan menjadikan desktop saya tidak dapat digunakan. Saya ingin cara menetapkan batas RAM untuk suatu proses sehingga jika melebihi jumlah itu, ia akan mati secara otomatis. Solusi khusus bahasa mungkin tidak akan berfungsi, karena saya menggunakan semua jenis alat yang berbeda (R, Perl, Python, Bash, dll).

Jadi apakah ada semacam proses-monitor yang akan membiarkan saya menetapkan jumlah ambang batas RAM dan secara otomatis mematikan proses jika menggunakan lebih banyak?

chrisamiller
sumber
@ Uri: Pada utas itu saya hanya mendapat sebagian (hanya untuk bagian cpu dari pertanyaan saya) - dan tidak optimal - jawaban. Dia bertanya tentang penggunaan RAM.
Chriskin
1
Uri, ada sangat sedikit ide berguna di utas itu. Memposting tautan ke situ tidak terlalu membantu.
chrisamiller
1
Hrmm - utas superuser ini tampaknya memiliki saran yang masuk akal menggunakan ulimit: superuser.com/questions/66383/restrict-ram-for-user-or-process
chrisamiller

Jawaban:

11

Saya benci menjadi orang yang menjawab pertanyaannya sendiri, tetapi pagi ini saya menemukan metode alternatif, yang dibungkus dengan utilitas kecil yang menyenangkan. Ini akan membatasi waktu CPU atau konsumsi memori:

https://github.com/pshved/timeout

Saya memberikan yang ini tembakan pertama tetapi upvotes ke Amey Jah untuk jawaban yang bagus. Saya akan memeriksanya jika ini gagal.

chrisamiller
sumber
5
+1 Menjawab pertanyaan Anda sendiri tidak apa-apa !
Tom Brossman
10

Saya sangat menyarankan untuk tidak melakukannya . Seperti yang disarankan oleh @chrisamiller, pengaturan ulimit akan membatasi RAM yang tersedia dengan proses.

Tetapi tetap jika Anda bersikeras maka ikuti prosedur ini.

  1. Simpan skrip berikut sebagai killif.sh:

    #!/bin/sh
    
    if [ $# -ne 2 ];
    then
        echo "Invalid number of arguments"
        exit 0
    fi
    
    while true;
    do
        SIZE=$(pmap $1|grep total|grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id =$1 Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$1"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    
        sleep 10
    done
  2. Sekarang buat itu bisa dieksekusi.

    chmod +x killif.sh
    
  3. Sekarang jalankan skrip ini di terminal. Ganti PROCIDdengan id proses aktual dan SIZEdengan ukuran dalam MB.

    ./killif.sh PROCID SIZE
    

    Sebagai contoh:

    ./killif.sh 132451 100
    

    Jika SIZE100 maka proses akan mati jika penggunaan RAM-nya melampaui 100 MB.

Perhatian: Anda tahu apa yang Anda coba lakukan. Proses membunuh bukanlah ide yang baik. Jika proses itu memiliki perintah shutdown atau stop maka edit skrip dan ganti kill -9perintah dengan shutdownperintah itu.

Amey Jah
sumber
saya akan mempertimbangkan sedikit tidur di sana, misalnya tidur 0,5 ...
Denwerko
@ George Edison Bagaimana Anda melakukan itu. Ketika saya mencoba menempel, itu memberi saya teks yang diformat aneh. Denwerko: Di mana Anda ingin tidur. Saya sudah tidur 10 detik dalam loop sementara
Amey Jah
2
Terima kasih atas solusinya, seperti disebutkan di bawah ini, saya dapat memeriksanya. Tapi mengapa semua peringatan mengerikan tentang proses pembunuhan? Perangkat lunak manajemen Cluster (LSF, PBS, et al) melakukan ini sepanjang waktu ketika suatu proses melebihi jumlah sumber daya yang diminta, tanpa konsekuensi yang mengerikan. Saya setuju bahwa ini bukan solusi yang baik untuk pengguna baru yang cenderung salah menggunakannya, tetapi dalam keadaan yang tepat, ini bisa sangat berguna.
chrisamiller
@ chrisamiller Saya telah memasang peringatan untuk pembaca di masa mendatang. Dalam kasus Anda, Anda tahu implikasinya tetapi pembaca posting ini di masa depan mungkin tidak menyadari implikasi seperti itu.
Amey Jah
2
Bisakah Anda menjelaskan mengapa tidak melakukannya?
jterm
2

Coba prlimitalat ini, dari util-linuxpaket. Ini menjalankan program dengan batas sumber daya. Ini menggunakanprlimit system call untuk mengatur batasan, yang kemudian ditegakkan sepenuhnya oleh kernel.

Anda dapat mengonfigurasi 16 batas, termasuk:

  • jumlah waktu CPU maksimum dalam detik
  • jumlah maksimum proses pengguna
  • ukuran set residen maksimum ("memori bekas")
  • ukuran maksimum suatu proses dapat mengunci ke dalam memori
  • ukuran memori virtual
  • jumlah maksimum file terbuka
  • jumlah maksimum kunci file
  • jumlah maksimum sinyal yang tertunda
  • byte maksimum dalam antrian pesan POSIX
Bram Geron
sumber
0

Ini terlalu besar untuk dikomentari. Saya memodifikasi skrip asli Amey untuk menyertakan a pgrep, jadi alih-alih harus secara manual memasukkan id proses, Anda bisa mengecualikan berdasarkan nama. Misalnya, ./killIf.sh chrome 4000membunuh semua proses chrome yang melebihi 4GB dalam penggunaan memori.

#!/bin/sh

# $1 is process name
# $2 is memory limit in MB

if [ $# -ne 2 ];
then
    echo "Invalid number of arguments"
    exit 0
fi

while true;
do
    pgrep "$1" | while read -r procId;
    do
        SIZE=$(pmap $procId | grep total | grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id = $procId Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$procId"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    done

    sleep 1
done

Hati-hati untuk memilih string grep yang sempit dan batas memori yang cukup besar untuk tidak membunuh proses yang tidak diinginkan.

Gaurang Tandon
sumber