【问题标题】:How do you kill a specific process that exceeds CPU usage and runtime limit in Linux?如何杀死超过 Linux 中 CPU 使用率和运行时限制的特定进程?
【发布时间】:2020-06-25 19:40:56
【问题描述】:

我有一个网站(Ubuntu OS 和 Apache 服务器上的 Wordpress 网站),其中包含特殊的数学计算器,其中许多使用 python3 脚本进行主要计算。这些计算器上的数据流是这样的:

1.) 用户在 html 表单中输入数字,然后点击提交按钮。

2.) 调用 PHP 函数,它将 html 用户输入分配给变量,并使用这些变量在适用的 python3 文件上执行 exec()(过滤用户输入并使用 escapeshellarg,所以在这里一切都很好)。

3.) PHP 函数返回 python3 脚本的结果,通过简码显示在计算器网页上。

我遇到的问题是,有时我的 python 脚本中的符号和数字计算会无限期地挂起。随着那个 python3 进程继续运行,它开始使用大量的 CPU 和内存资源(在流量高峰时段是个大问题)。

我的问题是:是否有某种方法可以在我的服务器后端创建一个脚本或程序,如果它超过了任意运行时和 CPU 使用级别,它将杀死 python3 的进程实例?我想把它限制在python3的实例上,这样它就不能杀死像mysqld这样的东西。另外,如果它只使用运行时作为终止条件,我也可以。在正常情况下,我的任何 python 脚本的运行时间都不应超过 ~10 秒,如果它们的运行时间不超过 10 秒,CPU 使用率不会成为问题。

【问题讨论】:

  • @stark 可能会回答我的问题。 bash 超时是可以在 PHP exec() 中调用的,还是我需要做更多的研究来制作一个单独运行的 Bash 文件?
  • 关于 Bash 超时,我发现了这个线程:stackoverflow.com/questions/9419122/exec-with-timeout 使用该方法,我似乎可以通过执行类似的操作来实现它? $result = exec("timeout {$time} python_script.py "."variable1"."variable2");
  • Linux 有setrlimit 系统调用(并且shell 提供ulimit 命令)...其中任何一个可能对您有用吗?
  • @OndrejK。看起来可以以与 bash 超时类似的方式使用它。两者都超出了我目前的理解水平,但我认为 RLIMIT_CPU 可用于限制进程使用的 cpu 时间。我只是不确定它是否会直接应用于 python 进程。

标签: python php python-3.x linux ubuntu


【解决方案1】:

您可以基于psutilos 模块创建另一个python 脚本作为服务器上的健康检查器。

以下代码可以作为您特定需求的基础,请注意,它的作用基本上是根据脚本名称检查 script_name_list 变量上的 python 脚本的 PID,并在检查是否您的服务器的 CPU 高于某个阈值,或者如果可用内存也低于某个阈值。

#!/usr/bin/env python3

import psutil
import os
import signal

CPU_LIMIT = 80 #Change Me
AV_MEM = 500.0 #Change Me
script_name_list = ['script1'] #Put in the name of the scripts

def find_other_scripts_pid(script_list):
    pid_list = []
    for proc in psutil.process_iter(['pid','name', 'cmdline']):
        #this is not the PID of the process referencing this script and therefore we chould check inside the list of script name to kill them
        if proc.info['pid'] != os.getpid() and proc.info['name'] in ['python','python3']:
            for element in proc.info['cmdline']:
               for script_name in script_name_list:
                   if script_name in element:
                       pid_list.append(proc.info['pid'])
    return pid_list

def kill_process(pid):
    if psutil.pid_exists(pid):
        os.kill(pid,signal.SIGKILL)
    return None


def check_cpu():
    return psutil.cpu_percent(interval=1)


def check_available_memory():
    mem = psutil.virtual_memory()
    return mem.available/(2**(20))


def main():

    cpu_usage = check_cpu()
    av_memory_mb = check_available_memory()
    if cpu_usage > CPU_LIMIT or av_memory_mb < AV_MEM:
        pid_list = find_other_scripts_pid(script_name_list)
        for pid in pid_list:
            kill_process(pid)


if __name__ == "__main__":
    main()

之后,您可以使用 crontab 在您的服务器上定期运行此脚本,如社区内共享的 post 中所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-19
    • 2023-03-24
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多