检查Python脚本是否已经在运行

我想我的Python脚本检查,如果它已经运行,如果是的话,杀死旧的进程。 我试过这个,但是并没有真正的工作。

import os import subprocess import signal process_name = "python " + os.path.abspath(__file__) proc = subprocess.Popen(["pgrep", process_name], stdout=subprocess.PIPE) # Kill process. for pid in proc.stdout: os.kill(int(pid), signal.SIGTERM) # Check if the process that we killed is alive. try: os.kill(int(pid), 0) raise Exception("""wasn't able to kill the process HINT:use signal.SIGKILL or signal.SIGABORT""") except OSError as ex: continue 

它不杀死旧的进程,现在运行多次。

确定是否使用基于pgrep的方法运行python脚本是不可靠的。 例如:

 > ps -ef | grep 'python sleep.py' userid 21107 2069 0 12:51 pts/3 00:00:00 python sleep.py userid 21292 2069 0 13:08 pts/3 00:00:00 grep python sleep.py > pgrep 'python sleep.py' > 

通过其名称识别正在运行的python脚本的其他困难:

  • 实际的python字符串可能会有所不同,具体取决于脚本的执行方式,例如,它可能如下所示:

/usr/bin/python2.7 sleep.py

  • 使用os.path.abspath(__file__)方法在进程名称中查找脚本可能会失败,如果脚本是符号链接到实际文件,并且可以从两个位置执行

例:

 > cat abs_path.py import os print os.path.abspath(__file__) > ls -l abs_path.py lrwxrwxrwx 1 userid at 15 Apr 22 13:22 abs_path.py -> bin/abs_path.py > python abs_path.py /home/userid/abs_path.py > python bin/abs_path.py /home/userid/bin/abs_path.py 
  • 进程(包括来自python脚本的进程)在执行过程中实际上可以改变它们的名字(可能不是在你的脚本的情况下,是正确的)

在处理这样的问题时,我个人的偏好是让脚本在一个独特的,众所周知的位置创建一个pidfile,在这个位置它将放置自己的pid。 这使得确定可能已经运行的过程的PID更加可靠。

您仍然必须考虑创建pid文件的竞争条件,并可靠地写入自己的pid。 通常情况下,如果检测到不匹配,则重新检查文件内容并自杀,这足以确保最多存在单个正在运行的流程实例,而不管流程是如何命名的。

从丹的回答开始,我想出了

 > ps -f -C python | grep 'sleep.py' userid 21107 2069 0 12:51 pts/3 00:00:00 anypath/python anypath/sleep.py 

这在前面的答案中仍然有很多问题,但是至少可以避免看到grep的结果,并且依赖于脚本的路径。

也可以用以下方式检查几个python版本:

 > ps -f -C python,python2.7 | grep 'sleepy.py' 

编辑:这是不正确的,如果多个python3实例正在运行。 更好地使用:

 > pgrep -a python | grep 'sleepy.py' 

我目前的解决方案是这样的(在OSX上)。 我正在使用pgrep结合正则表达式

 import subprocess cmd = ['pgrep -f .*python.*testing03.py'] process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) my_pid, err = process.communicate() if len(my_pid.splitlines()) >0: print("Running") exit() else: print("Not Running") 

据我测试这应该工作,即使python字符串不同。 脚本的位置也不重要