【问题标题】:How do I schedule a process' termination?如何安排进程的终止?
【发布时间】:2010-10-16 19:04:03
【问题描述】:

我需要运行一个进程,等待几个小时,杀死它,然后重新启动它。有没有一种简单的方法可以使用 Python 或 Bash 完成此任务?我可以在后台运行它,但是如何识别它以对其使用 kill 呢?

【问题讨论】:

    标签: python bash unix process kill


    【解决方案1】:

    使用 bash:

    while true ; do
        run_proc &
        PID=$!
        sleep 3600
        kill $PID
        sleep 30
    done
    

    $! bash 变量扩展为最近启动的后台进程的 PID。 sleep 只等待一个小时,然后 kill 关闭该进程。

    while 循环只是不断重复。

    【讨论】:

    • bash 会自动回收它的子节点吗?这会留下一堆僵尸(如果 bash 不自动回收),或者您冒着将 SIGTERM 发送到不相关进程的风险(bash 自动回收,为另一个进程释放 pid)。
    • 我假定该过程不退出(基于问题),在这种情况下,PID不会被重新使用它的杀害之前。跨度>
    • 进程确实退出了,但它运行时间很长。这个解决方案效果很好!
    【解决方案2】:

    这是在 Perl 中,但您应该能够将其翻译成 Python。

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    #set times to 0 for infinite times
    my ($times, $wait, $program, @args) = @ARGV;
    
    $times = -1 unless $times;
    while ($times--) {
        $times = -1 if $times < 0; #catch -2 and turn it back into -1
        die "could not fork" unless defined(my $pid = fork);
    
        #replace child with the program we want to launch
        unless ($pid) {
            exec $program, @args;
        }
    
        #parent waits and kills the child if it isn't done yet
        sleep $wait;
    
        kill $pid;
        waitpid $pid, 0; #clean up child
    }
    

    因为我想自学 Python,所以这里是 Python(我不相信这段代码):

    #!/usr/bin/python
    
    import os
    import sys
    import time
    
    times    = int(sys.argv[1])
    wait     = int(sys.argv[2])
    program  = sys.argv[3]
    args     = []
    if len(sys.argv) >= 4:
        args = sys.argv[3:]
    
    if times == 0:
        times = -1
    
    while times:
        times = times - 1
        if times < 0:
            times = -1
    
        pid = os.fork()
    
        if not pid:
            os.execvp(program, args)
    
        time.sleep(wait)
    
        os.kill(pid, 15)
        os.waitpid(pid, 0)
    

    【讨论】:

    • 进程id不能被其他进程使用,因为子进程还没有被父进程收割(它是僵尸)。
    【解决方案3】:

    在python中:

    import subprocess
    import time
    
    while True:    
        p = subprocess.Popen(['/path/to/program', 'param1', 'param2'])
        time.sleep(2 * 60 * 60) # wait time in seconds - 2 hours
        p.kill()
    

    p.kill() 是 python >= 2.6。

    在 python

    os.kill(p.pid, signal.SIGTERM)
    

    【讨论】:

    • 我得到 NameError: name 'subprocess' is not defined
    • 添加导入子进程导致 AttributeError: 'Popen' object has no attribute 'kill'
    • @chas。欧文斯:p.kill() 适用于 python >= 2.6。
    【解决方案4】:

    您总是可以编写一个脚本来搜索这些进程并在找到时终止它们。 然后添加一个cronjob来执行脚本。

    Find process ID of a process with known name

    Kill processes with a known ID

    在 python 中,os.kill() 可用于杀死给定 id 的进程。

    【讨论】:

      【解决方案5】:

      看看start-stop-daemon 实用程序。

      【讨论】:

      • ...我已将其修复为可以使用的页面,但您应该检查它是否是您想要的正确页面。
      【解决方案6】:

      一个想法:将进程的 PID(由您的子进程中的 fork() 返回)保存到一个文件中,然后安排一个 cron 作业来终止它,或者手动终止它,从文件中读取 PID。

      另一个选项:创建一个自动终止并重新启动进程的 shell 脚本包装器。同上,但你可以将 PID 保存在内存中,只要你需要就休眠,杀死进程,然后循环。

      【讨论】:

        【解决方案7】:

        不是一个理想的方法,但如果您知道程序的名称,并且您知道它是系统上运行的唯一进程,您可以在 cron 中使用它:

        0 */2 * * * kill `ps -ax | grep programName | grep -v grep | awk '{ print $1 }'` && ./scriptToStartProcess
        

        这将在整点每两个小时运行一次并杀死 programName 然后再次启动该进程。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-26
          • 1970-01-01
          • 1970-01-01
          • 2023-03-25
          • 2013-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多