Bagaimana cara membatasi waktu suatu program berjalan di Linux?

10

Saya punya beberapa simulasi untuk dilakukan, masing-masing dipanggil python simulate.py <parameter list>. Masalah dengan simulasi ini adalah beberapa dari mereka menggantung tanpa berhenti, yang mencegah saya menjalankannya dalam batch dengan skrip sederhana.

Yang saya butuhkan, adalah beberapa bentuk perintah "run-time-constraint", yang secara otomatis akan mematikan prosesnya (lebih disukai dengan menekan Ctrl + C , tapi saya pikir kill sederhana akan melakukannya juga) setelah waktu yang ditentukan, jika prosesnya tidak berakhir dengan anggun dengan sendirinya.

Tentu saja saya dapat menulis skrip semacam itu sendiri, tetapi saya curiga bahwa seseorang telah melakukannya sebelum saya, jadi saya tidak perlu menemukan kembali jam yang dihabiskan bersama ps, timedan bash manual.

Adam Ryczkowski
sumber

Jawaban:

15

Solusi potensial # 1

Gunakan timeoutperintah:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

Anda dapat menempatkan seorang penjaga ke dalam timeoutperintah juga untuk killproses jika itu tidak berhenti setelah beberapa periode waktu juga.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

Ini akan menunggu hingga 20 detik setelah proses sleep 100seharusnya berhenti, jika masih berjalan, maka timeoutakan mengirimkan killsinyal.

Solusi potensial # 2

Cara alternatif, meskipun metode yang lebih berisiko adalah sebagai berikut:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Menemukan teknik ini pada Stack Overflow dalam sebuah pertanyaan berjudul: Membatasi waktu program berjalan di Linux . Khususnya jawaban ini .

CATATAN: Per komentar yang ditinggalkan oleh @mattdm metode di atas bisa berisiko karena membuat asumsi bahwa belum ada proses baru yang dimulai sejak proses Anda. Jadi tidak ada PID baru yang ditugaskan. Mengingat hal ini, pendekatan ini mungkin tidak boleh digunakan tetapi di sini hanya sebagai referensi untuk pendekatan umum untuk masalah tersebut. The timeoutmetode adalah pilihan yang lebih baik dari 2.

slm
sumber
Tetapi kemudian akan dijamin, bahwa skrip akan selalu mengambil semua waktu itu. Dalam kasus saya ini bukan 1 detik, melainkan 15 menit.
Adam Ryczkowski
Tetapi solusi lain yang ditemukan dalam pertanyaan itu harus tepat seperti yang saya butuhkan. Terima kasih!
Adam Ryczkowski
2
Misalkan myProgram selesai dalam waktu kurang dari sleep(bukan asumsi yang tidak masuk akal karena tujuannya adalah untuk menetapkan runtime maksimum yang diizinkan). Anda kemudian mengirim sinyal baik ke PID yang tidak ada (tidak ada kerusakan nyata yang dilakukan) atau ke proses acak pada sistem (berpotensi fatal).
CVn
1
@ MichaelKjörling, terima kasih untuk feebacknya. Saya telah memperbarui jawaban saya per komentar yang sama yang ditinggalkan OP juga. Sepertinya timeoutperintah melakukan apa yang dia cari, menunggu OP untuk menanggapi komentar saya.
slm
@slm timeoutharus menjadi solusi yang saya butuhkan. Saya sedang mengujinya saat ini
Adam Ryczkowski
4

Saya telah menemukan sesuatu yang sedikit lebih baik, daripada timeout: timelimit.

Ini memiliki beberapa keunggulan; satu adalah bahwa pengguna dapat secara manual membatalkan eksekusi dengan menekan "Ctrl + C".

The timelimitprogram ini tersedia di Debian repositori.

Adam Ryczkowski
sumber
1
Mencoba memahami perbedaan antara timelimit dan waktu habis. batas waktu dapat dihentikan dengan Ctrl + C. Apa kelebihan lainnya?
slm
Yah, batas waktu saya tidak bisa. Saya menggunakan Mint 14 (berdasarkan Jumlah Ubuntu).
Adam Ryczkowski
3

Anda dapat menyetel waktu cpu dan hal-hal lain dengan ulimit, untuk waktu cpu khususnya:

$ ulimit -t 60      # limit to 60 seconds
$ program
RSFalcon7
sumber
Lihat U&L Q&A ini: unix.stackexchange.com/a/4666/7453 . @Gilles memberikan gambaran yang baik tentang penggunaan ulimit untuk tujuan ini.
slm
0

Bash menggunakan variabel yang disebutnya $BASHPIDdapat digunakan dalam situasi seperti itu, misalnya:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

Anda dapat mengubah argumen dalam panggilan untuk sleepdi do_face()untuk 100bukannya 10dan melihat apa yang terjadi ketika anak memakan waktu terlalu lama untuk melakukan tugas-tugasnya. Ubah saja panggilan untuk tidur do_face()ke panggilan ke executable Anda dan jika terlalu lama maka skrip akan membunuhnya, 20detik adalah nilai pembatas dalam contoh ini. Parameter dapat diimplementasikan sehingga ini menjadi skrip sederhana untuk dipanggil dan dapat dipanggil oleh skrip lain dalam batch atau apa pun. Menangani file pid untuk setiap proses bersamaan adalah masalah yang perlu ditangani, mungkin menggunakan subdirektori yang berbeda ...

NB: Pada GNU Linux sleepdapat mengambil argumen floating point seperti sleep 0.1tidur selama sepersepuluh detik.

Overloaded_Operator
sumber