如何检查状态或用python杀死一个外部进程

我有一个运行在我的web服务器上的python脚本。 主函数被调用,然后当它返回它只是睡几秒钟,再次被调用。 目的是获取用户添加的所有新上传的视频并将其转换为webm,将中间框架作为图像和其他一些时髦的东西拉出。 我正在使用ffmpeg的外部呼叫。 下面的代码片段显示了我如何称它。

    duration = output[durationIndex+10:durationIndex+18]
    durationBits = duration.split(":")
    lengthInSeconds = (int(durationBits[0])*60*60) + (int(durationBits[1])*60) + (int(durationBits[2]))

    child = subprocess.Popen(["ffmpeg","-y","-i",sourceVideo,"-f","mjpeg","-vframes","1","-ss",str(lengthInSeconds/2),destination], shell=True, stderr=subprocess.PIPE)
    output = ""
    while True:
        out = child.stderr.read(1)
        if out == '' and child.poll() != None:
            break
        if out != '':
            output += out

    updateSQL = "update `videos_graduatevideo` set thumbnail = '" + str(destination) + "' where `original_video` = '" + sourceVideo + "'"
    cursor.execute(updateSQL)

这个脚本运行在Windows机器atm上,但是我可能会在开发完成时将它部署到Unix系统上。

问题是。 我需要这个python脚本来继续运行。 如果ffmpeg出现问题并且我的脚本挂起,用户上传的视频就会处于“挂起”状态,直到我去戳python脚本。 我知道一个特定的mov文件让ffmpeg不能完全挂起。 有没有办法可以检查一个进程已经运行了多长时间,如果运行时间过长,就把它关闭?


我同意S. Lott的看法,看起来你会从为你的架构考虑MQ而获益,但对于这个特殊问题,我认为你对Popen的使用是可以的。

对于您创建的每个进程,保存创建时间(类似datetime.datetime.today()就足够了)。 然后每隔一分钟左右浏览打开的进程和时间列表,并使用Popen.send_signal(signal),terminate()或kill()获得不应该在那里的列表。

例:

import time
from subprocess import Popen
from datetime import datetime
jobs = []
max_life = 600 # in seconds

def reap_jobs(jobs):
  now = datetime.datetime.today()
  for job in jobs:
    if job[0] < now - datetime.timedelta(seconds=max_life)
      job[1].kill()
      # remove the job from the list if you want. 
      # but remember not to do it while iterating over the list

for video in list_of_videos:
  time = datetime.datetime.today()
  job = Popen(...)
  jobs.append((time,child))

while True:
  reap_jobs(jobs)
  time.sleep(60)

由于控制脚本是启动它的控件,并且由于您希望它基于时间而不是系统资源使用而死亡,所以它应该非常简单。 以下是您的示例代码,进行了一些修改; 寻找有评论的线路。

import time
timeout = 60 #child is allowed to run for 1 minute.
duration = output[durationIndex+10:durationIndex+18]
durationBits = duration.split(":")
lengthInSeconds = (int(durationBits[0])*60*60) + (int(durationBits[1])*60) + (int(durationBits[2]))

child = subprocess.Popen(["ffmpeg","-y","-i",sourceVideo,"-f","mjpeg","-vframes","1","-ss",str(lengthInSeconds/2),destination], shell=True, stderr=subprocess.PIPE)
killtime = time.time() + timeout #timestamp after which the child process should be killed
output = ""
while True:
    out = child.stderr.read(1)
    if out == '' and child.poll() != None:
        break
    if out != '':
        output += out
    if time.time() > killtime: #check if 60 seconds have passed
        child.kill() #tell the child to exit
        raise RuntimeError("Child process still going %i seconds after launch" %killtime) #raise an exception so that updateSQL doesn't get executed

updateSQL = "update `videos_graduatevideo` set thumbnail = '" + str(destination) + "' where `original_video` = '" + sourceVideo + "'"
cursor.execute(updateSQL)

您可以将RuntimeError更改为其他值,或者设置一个标志而不是引发异常,具体取决于您需要执行的操作。 child.kill()行会导致子进程死掉,但它可能不是最优美的方式来结束它。 如果你将它部署在一个posix系统上,你可以使用os.system('kill -s 15%i'%child.pid)来更好地杀死它。


看看上帝 - 一个进程监视器,监视你指定的进程,并根据你的监视条件执行一些操作。 例如,它可以关注CPU使用情况,并在CPU使用率高于50%时重新启动进程:

# code in Ruby
# copyied from the documentation
w.restart_if do |restart|   
  restart.condition(:cpu_usage) do |c|
    c.above = 50.percent
    c.times = 5
  end
end
链接地址: http://www.djcxy.com/p/56821.html

上一篇: How to you check the status or kill an external process with python

下一篇: Ant FTP task fails: java.net.SocketException