簡體   English   中英

檢查進程是否仍在運行

[英]Check if a process is still running

我有以下問題:

我需要我的Python腳本運行bash腳本。 如果bash腳本的運行時間超過10秒,我需要將其殺死。 這是我到目前為止的內容:

cmd = ["bash", "script.sh", self.get_script_path()]
process = subprocess.Popen(cmd)

time.sleep(10)  # process running here...

procinfo = psutil.Process(process.pid)
children = procinfo.children(recursive=True)
for child in children:
    os.kill(child.pid, signal.SIGKILL)

我擔心的是這種情況:bash腳本在1秒內完成,釋放其PID,系統將PID傳遞給另一個進程。 10秒后,我殺死了我認為它屬於我的腳本的PID,但那不是真的,並且我殺死了其他一些進程。 該腳本需要以root身份運行,因為我需要在其中使用chroot

有任何想法嗎?

由於您已經在使用psutil所以建議您將對subprocess模塊的調用替換為對psutil.Popen調用。 這個類有相同的接口subprocess.Popen但提供的所有功能psutil.Process

還要注意的psutil為PID庫先發制人檢查已經重用 ,至少在許多方法,包括terminatekill (剛讀出的用於文檔Process )。

這意味着下面的代碼:

cmd = ["bash", "script.sh", self.get_script_path()]
process = psutil.Popen(cmd)

time.sleep(10)  # process running here...

children = process.children(recursive=True)
for child in children:
    child.terminate()   # try to close the process "gently" first
    child.kill()

請注意, children文檔說:

子項(遞歸= False)

返回該進程的子進程作為Process對象的列表, 搶先檢查PID是否已被重用。

總之,這意味着:

  1. 當您調用childrenpsutil庫會檢查您是否希望子代具有正確的進程,而不是碰巧具有相同pid的子代。
  2. 當你調用terminatekill庫可以確保您使用相同的PID殺死你的孩子過程,而不是一個隨機過程。

我認為timeout命令非常適合您。 在文檔頁面上:

概要

超時 [OPTION] NUMBER [SUFFIX]命令[ARG] ...
超時 [OPTION]


描述

啟動COMMAND,如果在NUMBER秒后仍在運行,則將其殺死。 SUFFIX可能是“ s”代表秒(默認值),“ m”代表分鍾,“ h”代表小時或“ d”代表天。

-s ,-- signal = 信號
指定超時時要發送的信號。
SIGNAL可以是“ HUP”之類的名稱或數字。
請參閱“ kill -l”以獲取信號列表

通過timeout ,您不必擔心PID重用,競爭條件等雜亂無章的細節。這些擔憂已很好地封裝在此標准Unix實用程序中。 另一個好處是您的腳本將在子進程提前終止后立即恢復執行,而不用不必要地休眠整整10秒鍾。

bash中的演示:

timeout -s9 10 sleep 11; echo $?;
## Killed
## 137
timeout -s9 10 sleep 3; echo $?;
## 0

python演示:

import subprocess;
subprocess.Popen(['timeout','-s9','10','sleep','11']).wait();
## -9
subprocess.Popen(['timeout','-s9','10','sleep','3']).wait();
## 0

我在ubuntu上使用命令stop process_name停止進程。 可能會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM