python 脚本程序监控linux服务器(程序自启)

一、python 程序后台自启

查询某个服务是否在后台运行

#!/usr/bin/env python
import subprocess
import datetime
import re
import sys
import os
res = subprocess.Popen("id root",stdout=subprocess.PIPE,shell=True)
output_lines=res.stdout.readlines()
for line in output_lines:
    if not re.search("ma", line):      # 若是没有找到该服务,执行以下
        line = line.strip()
        dt=datetime.datetime.now()
        fp=open('/root/check_ma_group/check_ma.txt','a')
        fp.write('root in ma group at %s\n' % dt.strftime('%Y-%m-%d %H:%M:%S'))
        fp.close()
        subprocess.Popen("/usr/sbin/usermod -G ma root",shell=True)
    else:
        pass
# -*- coding: utf-8 -*- 
#!/usr/bin/python 

import os 
import subprocess 

res = subprocess.Popen('ps -ef | grep python',stdout=subprocess.PIPE,shell=True) 
attn=res.stdout.readlines() 
counts=len(attn)             #获取关于 python 的进程个数 
print counts 
if counts<10:                #当进程不够正常运行的个数时,说明某程式退出了 
    os.system('python /home/weblogic/test.py') #启动程序

利用python的logging模块来记录日志,利用subprocess模块来和系统交互执行命令,检测到子程序结束运行之后,重新开启子程序。

# -*- coding: UTF-8 -*-
import os
import subprocess
import logging
from logging.handlers import RotatingFileHandler


class Config:
    LOG_PATH_FILE = "./my_service_mgr.log"
    LOG_MODE = 'a'
    LOG_MAX_SIZE = 10 * 1024 * 1024  # 10M per file
    LOG_MAX_FILES = 10               # 10 Files: my_service_mgr.log.1, printmy_service_mgrlog.2, ...
    LOG_LEVEL = logging.DEBUG
    LOG_FORMAT = "%(asctime)s %(levelname)-10s[%(filename)s:%(lineno)d(%(funcName)s)] %(message)s"

cfg = Config()

handler = RotatingFileHandler(cfg.LOG_PATH_FILE, cfg.LOG_MODE, cfg.LOG_MAX_SIZE, cfg.LOG_MAX_FILES)
formatter = logging.Formatter(cfg.LOG_FORMAT)
handler.setFormatter(formatter)
Logger = logging.getLogger()
Logger.setLevel(cfg.LOG_LEVEL)
Logger.addHandler(handler)


pid = os.getpid()


def print_error(s):
    print('\033[31m[%d: ERROR] %s\033[31;m' % (pid, s))


def print_info(s):
    print('\033[32m[%d: INFO] %s\033[32;m' % (pid, s))

def print_warning(s):
    print('\033[33m[%d: WARNING] %s\033[33;m' % (pid, s))

def start_child_proc(command, merged):
    try:
        if command is None:
            raise OSError("Invalid command")

        child = None
        if merged is True:
            child = subprocess.Popen(command,
                                     stderr=subprocess.STDOUT,  # 表示子进程的标准错误也输出到标准输出
                                     stdout=subprocess.PIPE     # 表示需要创建一个新的管道
                                     )
        else:
            child = subprocess.Popen(command)
        return child
    except subprocess.CalledProcessError:
        pass                                                    # 处理调用的可执行文件中的错误
    except OSError:
        raise OSError("Failed to run command!")


def run_forever(command):
    print_info("start child process with command: " + ' '.join(command))
    Logger.info("start child process with command: " + ' '.join(command))

    failover = 0
    merged = False
    child = start_child_proc(command, merged)

    while True:
        while child.poll() != None:
            failover = failover + 1
            print_warning("child process shutdown with return code: " + str(child.returncode))
            Logger.critical("child process shutdown with return code: " + str(child.returncode))

            print_warning("restart child process again, times=%d" % failover)
            Logger.info("restart child process again, times=%d" % failover)
            child = start_child_proc(command, merged)

        # 读取子进程stdout并记录它
        out, err = child.communicate()
        returncode = child.returncode
        if returncode != 0:
            for errorline in err.splitlines():
                Logger.info(errorline)
        else:
            Logger.info("execute child process failed")

if __name__ == "__main__":
    run_forever(['scrapy', 'crawl', 'CNSubAllInd'])
    Logger.exception("!!!should never run to this!!!")

二、对 Linux 服务器的监控

工作原理:基于/proc 文件系统

Linux 系统为管理员提供了非常好的方法,使其可以在系统运行时更改内核,而不需要重新引导内核系统,这是通过/proc 虚拟文件系统实现的。/proc 文件虚拟系统是一种内核和内核模块用来向进程(process)发送信息的机制(所以叫做“/proc”),这个伪文件系统允许与内核内部数据结构交互,获取有关进程的有用信息,在运行中(on the fly)改变设置(通过改变内核参数)。与其他文件系统不同,/proc 存在于内存而不是硬盘中。proc 文件系统提供的信息如下:

  • 进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的进程 ID,可以找到 cmdline、mem、root、stat、statm,以及 status。某些信息只有超级用户可见,例如进程根目录。每一个单独含有现有进程信息的进程有一些可用的专门链接,系统中的任何一个进程都有一个单独的自链接指向进程信息,其用处就是从进程中获取命令行信息。
  • 系统信息:如果需要了解整个系统信息中也可以从/proc/stat 中获得,其中包括 CPU 占用情况、磁盘空间、内存对换、中断等。
  • CPU 信息:利用/proc/CPUinfo 文件可以获得中央处理器的当前准确信息。
  • 负载信息:/proc/loadavg 文件包含系统负载信息。
  • 系统内存信息:/proc/meminfo 文件包含系统内存的详细信息,其中显示物理内存的数量、可用交换空间的数量,以及空闲内存的数量等。

/proc 目录中的主要文件的说明

文件或目录名称描 述
apm高级电源管理信息
cmdline这个文件给出了内核启动的命令行
CPUinfo中央处理器信息
devices可以用到的设备(块设备/字符设备)
dma显示当前使用的 DMA 通道
filesystems核心配置的文件系统
ioports当前使用的 I/O 端口
interrupts这个文件的每一行都有一个保留的中断
kcore系统物理内存映像
kmsg核心输出的消息,被送到日志文件
mdstat这个文件包含了由 md 设备驱动程序控制的 RAID 设备信息
loadavg系统平均负载均衡
meminfo存储器使用信息,包括物理内存和交换内存
modules这个文件给出可加载内核模块的信息。lsmod 程序用这些信息显示有关模块的名称,大小,使用数目方面的信息
net网络协议状态信息
partitions系统识别的分区表
pcipci 设备信息
scsiscsi 设备信息
self到查看/proc 程序进程目录的符号连接
stat这个文件包含的信息有 CPU 利用率,磁盘,内存页,内存对换,全部中断,接触开关以及赏赐自举时间
swaps显示的是交换分区的使用情况
uptime这个文件给出自从上次系统自举以来的秒数,以及其中有多少秒处于空闲
version这个文件只有一行内容,说明正在运行的内核版本。可以用标准的编程方法进行分析获得所需的系统信息

OrderedDict 是一个字典子类,可以记住其内容增加的顺序,方便遍历

#!/usr/bin/env Python
from __future__ import print_function
from collections import OrderedDict
import pprint,os



#  CPU(中央处理器)监测
def CPUinfo():
    '''
    读取/proc/CPUinfo 中的信息,返回 list,每核心一个 dict。
    CPU_info['proc0']={...}
    CPU_info['proc1']={...}
    '''
    CPUinfo=OrderedDict()
    procinfo=OrderedDict()

    nprocs = 0
    with open('/proc/CPUinfo') as f:
        for line in f:
            if not line.strip():
                # end of one processor
                CPUinfo['proc%s' % nprocs] = procinfo
                nprocs=nprocs+1
                # Reset
                procinfo=OrderedDict()
            else:
                if len(line.split(':')) == 2:
                    procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip()
                else:
                    procinfo[line.split(':')[0].strip()] = ''
    return CPUinfo
 
 # 系统负载监测
 def load_stat(): 
    loadavg = {} 
    f = open("/proc/loadavg") 
    con = f.read().split() 
    f.close() 
    loadavg['lavg_1']=con[0] 
    loadavg['lavg_5']=con[1] 
    loadavg['lavg_15']=con[2] 
    loadavg['nr']=con[3] 
    loadavg['last_pid']=con[4] 
    return loadavg 


 # 对于内存信息的获取
def meminfo():
    ''' Return the information in /proc/meminfo
    as a dictionary '''
    meminfo=OrderedDict()
 
    with open('/proc/meminfo') as f:
        for line in f:
            meminfo[line.split(':')[0]] = line.split(':')[1].strip()
    return meminfo



if __name__=='__main__':
    CPUinfo = CPUinfo()
    for processor in CPUinfo.keys():
        print(CPUinfo[processor]['model name'])

    loadavg = load_stat()
    print(loadavg['lavg_15'])

    meminfo = meminfo()
    print('Total memory: {0}'.format(meminfo['MemTotal']))
    print('Free memory: {0}'.format(meminfo['MemFree']))

对于网络接口的监测

#!/usr/bin/env Python
import time
import sys
 
if len(sys.argv) > 1:
    INTERFACE = sys.argv[1]
else:
    INTERFACE = 'eth0'
STATS = []
print ('Interface:',INTERFACE)
 
def rx():
    ifstat = open('/proc/net/dev').readlines()
    for interface in  ifstat:
        if INTERFACE in interface:
            stat = float(interface.split()[1])
            STATS[0:] = [stat]
 
def tx():
    ifstat = open('/proc/net/dev').readlines()
    for interface in  ifstat:
        if INTERFACE in interface:
            stat = float(interface.split()[9])
            STATS[1:] = [stat]
 
print('In         Out')

rx()
tx()

while True:
    time.sleep(1)
    rxstat_o = list(STATS)
    rx()
    tx()
    RX = float(STATS[0])
    RX_O = rxstat_o[0]
    TX = float(STATS[1])
    TX_O = rxstat_o[1]
    RX_RATE = round((RX - RX_O)/1024/1024,3)
    TX_RATE = round((TX - TX_O)/1024/1024,3)
    print (RX_RATE ,'MB      ',TX_RATE ,'MB')

三、以表格形式终端输出

在这里插入图片描述
照着这个图,可以发现几个关键的实现点

  1. 由数据项的各个属性,整理出表头
  2. 计算每个属性对应的最大宽度,作为每列的宽度
  3. 每列左右留一些空
  4. 表头上下,以及数据项末尾添加一行 --±- 外围
  5. 循环每项,各项左右使用 | 做外围
  6. 需支持居中显示或左对齐,这些可以通过计算列的总长度,再补空格来实现 利用 .center .ljust 这些快捷方法

鸣谢:
https://www.ibm.com/developerworks/cn/linux/1312_caojh_pythonlinux/#icomments
https://www.cnblogs.com/imwtr/p/11062308.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值