检查进程是否仍在运行

时间:2016-08-28 07:16:43

标签: python linux bash process psutil

我有以下问题:

我需要我的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

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

由于您已经在使用psutil,因此我建议您通过调用psutil.Popen替换对subprocess模块的调用。此类具有subprocess.Popen的相同接口,但提供psutil.Process的所有功能。

另请注意, psutil库已经先发制人地检查PID重用,至少对于包括terminatekill在内的多种方法(只是阅读documentation for 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的文档说:

  

<强>儿童(递归=假)

     

将此过程的子项作为Process个对象的列表返回,先发制人地检查PID是否已被重用。

总之,这意味着:

  1. 当您致电children时,psutil图书馆会检查您是否希望正确流程的子项而不是具有相同pid的子项
  2. 当您致电terminatekill时,图书馆会确保您杀死您的子进程,而不是使用相同pid的随机进程。

答案 1 :(得分:0)

我认为timeout命令对你来说非常合适。从文档页面:

  

概要

     

超时 [OPTION] NUMBER [SUFFIX] COMMAND [ARG] ...
  超时 [选项]

           

描述

     

启动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

答案 2 :(得分:-3)

我在ubuntu上使用命令stop process_name来停止我的进程。 愿它有用。