Làm thế nào để hạn chế thời gian một chương trình chạy trong Linux?


10

Tôi có một vài mô phỏng để làm, mỗi cái được gọi với python simulate.py <parameter list>. Vấn đề với các mô phỏng này là một số trong số chúng bị treo mà không thoát ra, điều này ngăn tôi chạy chúng theo lô với một tập lệnh đơn giản.

Điều tôi cần, là một số dạng lệnh "hạn chế thời gian chạy", sẽ tự động giết tiến trình (tốt nhất là bằng cách nhấn Ctrl + C , nhưng tôi nghĩ việc giết đơn giản cũng sẽ làm được) sau một thời gian xác định, nếu quá trình không kết thúc một cách duyên dáng.

Dĩ nhiên tôi có thể viết kịch bản như vậy bản thân mình, nhưng tôi nghi ngờ rằng ai đó đã làm nó đã đi trước tôi, vì vậy tôi không cần phải phát minh lại bánh xe hàng giờ với ps, timevà hướng dẫn sử dụng bash.

Câu trả lời:


15

Giải pháp tiềm năng số 1

Sử dụng timeoutlệnh:

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

Bạn cũng có thể đặt một người bảo vệ vào timeoutlệnh để killxử lý nếu nó cũng không dừng sau một khoảng thời gian.

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

Điều này sẽ đợi tối đa 20 giây sau khi quá trình sleep 100nên dừng lại, nếu nó vẫn chạy, sau đó timeoutsẽ gửi killtín hiệu.

Giải pháp tiềm năng số 2

Một cách khác, mặc dù phương pháp rủi ro hơn sẽ như sau:

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

Tìm thấy kỹ thuật này trên Stack Overflow trong một câu hỏi có tiêu đề: Giới hạn thời gian chương trình chạy trong Linux . Cụ thể câu trả lời này .

LƯU Ý: Mỗi nhận xét do @mattdm để lại, phương pháp trên có thể có rủi ro do nó đưa ra giả định rằng không có bất kỳ quy trình mới nào được bắt đầu kể từ quy trình của bạn. Vì vậy, không có PID mới đã được chỉ định. Vì điều này, cách tiếp cận này có lẽ không nên được sử dụng mà ở đây chỉ là tài liệu tham khảo cho cách tiếp cận chung cho vấn đề. Các timeoutphương pháp là lựa chọn tốt hơn về 2.


Nhưng sau đó sẽ được đảm bảo, rằng kịch bản sẽ luôn mất tất cả thời gian đó. Trong trường hợp của tôi, nó không phải là 1 giây, mà là 15 phút.
Adam Ryczkowski

Nhưng giải pháp khác được tìm thấy trong câu hỏi đó phải chính xác là những gì tôi cần. Cảm ơn!
Adam Ryczkowski

2
Giả sử myProgram kết thúc trong thời gian ít hơn sleep(không phải là một giả định không hợp lý vì mục tiêu là đặt thời gian chạy tối đa được phép). Sau đó, bạn gửi tín hiệu tới một bộ lọc không tồn tại (không gây hại thực sự) hoặc cho bất kỳ quy trình ngẫu nhiên nào trên hệ thống (có khả năng gây tử vong).
một CVn

1
@ MichaelKjorling, cảm ơn vì sự trở lại. Tôi đã cập nhật câu trả lời của mình cho cùng một nhận xét mà OP cũng để lại. Có vẻ như timeoutlệnh thực hiện chính xác những gì anh ta đang tìm kiếm, chờ đợi OP phản hồi ý kiến ​​của tôi.
slm

@slm timeoutnên là giải pháp tôi cần. Tôi đang thử nghiệm nó vào lúc này
Adam Ryczkowski

4

Tôi đã tìm thấy một cái gì đó tốt hơn một chút, hơn timeout: timelimit.

Nó có một số lợi thế; một là người dùng có thể hủy bỏ thủ công bằng cách nhấn "Ctrl + C".

Các timelimitchương trình có sẵn trong kho Debian.


1
Cố gắng để hiểu sự khác biệt b / w tim timit và thời gian chờ. thời gian chờ có thể được dừng lại bằng Ctrl + C. Những lợi thế khác là gì?
slm

Vâng, thời gian chờ của tôi không thể. Tôi sử dụng Mint 14 (dựa trên Ubuntu Quantal).
Adam Ryczkowski

3

Bạn có thể điều chỉnh thời gian cpu và những thứ khác với ulimit, đối với thời gian cpu đặc biệt:

$ ulimit -t 60      # limit to 60 seconds
$ program

Xem câu hỏi và trả lời này của U & L: unix.stackexchange.com/a/4666/7453 . @Gilles cung cấp một cái nhìn tổng quan tốt về việc sử dụng ulimit cho mục đích này.
slm

0

Bash sử dụng một biến gọi là $BASHPIDnó có thể được sử dụng trong tình huống như vậy, ví dụ:

#!/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

Bạn có thể thay đổi các tham số trong các cuộc gọi đến sleeptrong do_face()để 100thay 10và xem những gì sẽ xảy ra khi đứa trẻ mất quá nhiều thời gian để làm công việc của mình. Chỉ cần thay đổi cuộc gọi để chuyển do_face()sang cuộc gọi thành thực thi của bạn và nếu mất quá nhiều thời gian thì tập lệnh sẽ giết nó, 20giây là giá trị giới hạn trong ví dụ này. Các tham số có thể được thực hiện để điều này trở thành một tập lệnh đơn giản để gọi và có thể được gọi bởi một tập lệnh khác theo lô hoặc bất cứ điều gì. Xử lý các tệp pid cho mỗi quy trình đồng thời là một vấn đề sẽ cần được xử lý, có thể sử dụng các thư mục con khác nhau ...

Lưu ý: Trên GNU Linux sleepcó thể lấy các đối số dấu phẩy động như sleep 0.1ngủ trong một phần mười giây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.