V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
longmeier90
V2EX  ›  Python

Python 监控服务器 cpu 及报警,手动执行没有问题,但是后台启动就会有问题,不会发送报警。不知道是什么原因,请大佬给点建议

  •  
  •   longmeier90 · 2021-03-02 14:23:22 +08:00 · 1133 次点击
    这是一个创建于 1369 天前的主题,其中的信息可能已经有所发展或是发生改变。
    import subprocess
    import re
    import pika
    import time, datetime
    
    # 定义删除 ANSI escape code
    ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
    
    # 消息队列连接
    def rabbit_connect():
        credentials = pika.PlainCredentials("admin", "bolin1024")
        connection = pika.BlockingConnection(pika.ConnectionParameters(
            host="39.96.5.133", port=5672, credentials=credentials))  # 定义连接池
        channel = connection.channel()  # 声明队列以向其发送消息消息
        return channel, connection
    
    # 消息队列关闭
    def rabbit_close(connection):
        connection.close()
    
    # 消息队列发送消息
    def create_msg(channel, msg):
        """
        消息发送方
        :param msg:
        :return:
        """
    
        # durable server 挂了 队列仍然存在
        channel.queue_declare(queue="cpu_monitor", durable=True)
        # delivery_mode=2:使消息持久化。和队列名称绑定 routing_key
        channel.basic_publish(exchange='', routing_key="cpu_monitor", body=msg,
                              properties=pika.BasicProperties(delivery_mode=2))
    
    
    # 监控程序
    def monitor_process():
    
    
        top_info = subprocess.Popen(["top", "-n", "1"], stdout=subprocess.PIPE)
        out, err = top_info.communicate()
        out_info = out.decode('unicode-escape')
        lines, result = [], []
        lines = out_info.split('\n')
        if len(lines) >= 13:
            load_average = lines[0]
            load_aver = load_average.split()
            loads = [ansi_escape.sub('', col).upper().replace("\x1b(B", '') for col in load_aver]
            loads = list(filter(None, loads))
            loads_cpu0 = float(loads[11].replace(',', '').strip()) if len(loads) > 11 else 4
            for l in range(7, 13):
                hang = str(lines[l])
                hangs = hang.split()
                hangs = [ansi_escape.sub('', col).upper().replace("\x1b(B", '') for col in hangs]
                hangs = list(filter(None, hangs))
                if len(hangs) > 11:
                    pid = hangs[0]
                    user = hangs[1]
                    cpu = hangs[8]
                    mem = hangs[9]
                    apps = hangs[11]
                    if float(cpu) > 80 and 'MYSQL' not in apps and loads_cpu0 > 4:
                        print(pid, user, cpu, mem, apps, loads_cpu0) 
                        print('请开始报警....', cpu)
                        spy_info = subprocess.Popen(["py-spy","dump","--pid", pid], stdout=subprocess.PIPE)
                        out2, err2 = spy_info.communicate()
                        out_info2 = out2.decode('unicode-escape')
                        lines2 = []
                        lines2 = out_info2.split('\n')
                        for l in range(len(lines2)):
                            hang2 = str(lines2[l])
                            print(hang2)
                            hangs2 = hang2.split("(")
                            if len(hangs2) > 1:
                                meth = hangs2[0].strip()
                                path = hangs2[1].split(")")[0].strip()
                                if meth == "get" and "/views/" in path:
                                    meta = {'name': path, 'cpu': cpu, 'loads_cpu0': loads_cpu0}
                                    print(meta)
                                    result.append(meta)
        # 如果存在要发送的消息
        if len(result) > 0:
            channel_, connection_ = rabbit_connect()
            for rt in result:
                create_msg(channel_, str(meta))
            rabbit_close(connection_)
    
    
    if __name__ == "__main__":
    
        print('cpu 报警程序已启动....')
        
        while True:
            now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print('%s cpu 报警程序 monitor_process...' % now_time)
            try:
                monitor_process()
            except Exception as e:
                print(e)
                
            time.sleep(20)
    
    program9527
        1
    program9527  
       2021-03-02 14:32:16 +08:00
    整个代码中使用了两处 subprocess.Popen,手动启动时,你的终端会加载用户目录下的 .bashrc 文件,也就是环境变量。在后台启动可能不会加载,从而导致一些系统调用无法正确找到命令。例如你上面的一行:

    subprocess.Popen(["py-spy","dump","--pid", pid]

    建议排查下。。。
    program9527
        2
    program9527  
       2021-03-02 14:33:04 +08:00
    把这种系统调用改成绝对路径试试
    lmaq
        3
    lmaq  
       2021-03-02 14:43:41 +08:00
    改下管理员密码吧,暴漏了!
    longmeier90
        4
    longmeier90  
    OP
       2021-03-02 14:45:00 +08:00
    @lmaq 不知道不能删帖,太坑啦。马上就改
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2575 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:19 · PVG 11:19 · LAX 19:19 · JFK 22:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.