检查Python脚本是否已在运行

时间:2016-04-22 16:39:42

标签: python linux process kill

我希望我的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

它不会杀死旧进程并且现在多次运行。

4 个答案:

答案 0 :(得分:4)

使用基于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脚本的进程)实际上可以在执行期间更改其名称(可能不在脚本的情况下,为true)

我个人倾向于解决此类问题的方法是让脚本在一个独特的,众所周知的位置创建一个pid文件,在该位置放置自己的pid。这使得确定潜在已经运行的进程的pid更加可靠。

你仍然需要考虑创建pidfile的竞争条件,并可靠地写入自己的pid。通常,如果检测到不匹配,则重新检查文件内容并自杀,这足以确保最多只存在一个正在运行的流程实例,而不管该流程的实际命名方式如何。

答案 1 :(得分:3)

我目前的解决方案是这样的(在OSX上)。 我正在使用pgrep与regexp结合使用

var datesWithEvent = ["2015-10-03", "2015-10-06", "2015-10-12", "2015-10-25"]
var datesWithMultipleEvents = ["2015-10-08", "2015-10-16", "2015-10-20", "2015-10-28"]

fileprivate lazy var dateFormatter2: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    return formatter
}()

func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
    let dateString = self.dateFormatter2.string(from: date)
    if self.datesWithEvent.contains(dateString) {
        return 1
    }
    if self.datesWithMultipleEvents.contains(dateString) {
        return 3
    }
    return 0
}

就我测试而言,即使python字符串不同,这也应该有效。脚本的位置无关紧要

答案 2 :(得分:1)

Dan's answer开始,我想出了

> 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'

答案 3 :(得分:0)

这个问题与Check to see if python script is running

非常相似

我建议您使用PidFile module,它将为您处理所有事情。

import pidfile
import time

print('Starting process')
try:
    with pidfile.PIDFile():
        print('Process started')
        time.sleep(30)
except pidfile.AlreadyRunningError:
    print('Already running.')

print('Exiting')

尝试在两个终端上运行两次此脚本

我与图书馆的所有者没有关系,我刚刚找到它