文章目录

一、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

系统识别的分区表

pci

pci 设备信息

scsi

scsi 设备信息

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')

三、以表格形式终端输出

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


照着这个图,可以发现几个关键的实现点

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

鸣谢:
​​​ https://www.ibm.com/developerworks/cn/linux/1312_caojh_pythonlinux/#icomments​