2 Star 1 Fork 1

ksc/sitemonitor

Create your Gitee Account
Explore and code with more than 14 million developers,Free private repositories !:)
Sign up
文件
Clone or Download
sitemonitor.py 6.13 KB
Copy Edit Raw Blame History
ksc authored 2014-03-19 11:03 +08:00 . 初始化
#!/usr/bin/env python
#coding=utf-8
'''
Copyright (c) 2014 ksc
author: ksc (http://blog.geekli.cn)
Dependencies:
python 2.7
Linux ≥ 2.6.13
pyinotify
API http://seb-m.github.io/pyinotify/
'''
import os,sys
import pyinotify
import logging
import hashlib
import time
import ConfigParser
import threading
import thread
import subprocess as subpro
__version__='0.6.1'
__author__='ksc'
if len(sys.argv)>1 and sys.argv[1]=='-v':
print(__version__)
sys.exit()
logformat="%(asctime)s %(levelname)s %(message)s"
logging.basicConfig(level=logging.ERROR,format=logformat,filename='km.log',filemode='a')
klog=logging.getLogger('klog')
klog.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
#ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-4s: %(levelname)-4s %(message)s')
ch.setFormatter(formatter)
klog.addHandler(ch)
class EventHandler(pyinotify.ProcessEvent):
name=None
backup_path=''
backup_ext=[]
backup_maxfilesize=0
def init(self, name ):
self.name=name
def setBackup(self, path, ext, maxfilesize= 1024000):
''' set file's ext which need backup'''
self.backup_path = path
self.backup_ext = ext
self.backup_maxfilesize=maxfilesize
def process_IN_MODIFY(self, e):
#print event
#klog.info("MODIFY :%s"%(event.pathname))
pass
def process_IN_CLOSE_WRITE(self, e):
stat=os.stat(e.pathname)
md5=hashlib.md5(e.pathname+str(time.time()))
md5=md5.hexdigest()
_datepath=time.strftime('%m%d-%y')
_dst=os.path.join(_datepath, md5)#relative path
info="MODIFY: %s %d %s"%(e.pathname,stat.st_size,_dst)
klog.info(info)
if stat.st_size==0 or stat.st_size > self.backup_maxfilesize:
return
file_ext=os.path.splitext(e.pathname)[1]# may be ''
if len(self.backup_ext) and file_ext not in self.backup_ext:
return
if self.backup_path !='':
absdatepath=os.path.join(self.backup_path,_datepath)
if not os.path.isdir(absdatepath):
os.makedirs(absdatepath)
klog.debug('MKBACKDIR:%s',absdatepath)
dst=os.path.join(self.backup_path, _dst)
sh='cp %s %s'%(e.pathname,dst)
pipe=subpro.Popen(sh, shell=True,stdout=subpro.PIPE,stderr=subpro.PIPE)
pipe.wait()
if pipe.returncode:
_error=pipe.stderr.readline()
_error='"backupfailed-%s"'%(_dst)
klog.warn('BACKUP:%s',_error)
return
klog.debug('BACKUP:%s',e.pathname)
def process_IN_DELETE(self, e):
klog.info("DELETE: %s"%(e.pathname))
def process_IN_CREATE(self, e):
#print e
klog.info("CREATE: %s"%(e.pathname))
def process_default(self, e):
#print e
pass
class myMonitor(object):
def __init__(self, name, path, excl_list=[] ):
self.name= name
self.path= path
self.maxfilesize=0
self.excl_list=excl_list # only dir can be filter
self.wm= pyinotify.WatchManager()
self.ehandler= EventHandler()
self.ehandler.init(self.name)
def setBackup(self, path, ext=[]):
if isinstance(ext, str):
ext=ext.split(',')
ext=[item.strip() for item in ext if item.strip() !='']
self.backup_path=path
self.backup_ext=ext
klog.debug('SITE[%s] BACKUP_EXT: %s', self.name, ext)
self.ehandler.setBackup(path,ext)
def getExcludeList(self):
if isinstance(self.excl_list, str):
self.excl_list=self.excl_list.split(';')
#remove empty item in list
slist=[item.strip() for item in self.excl_list if item.strip() !='']
return ['^'+self.path+'/'+item for item in slist]
def exit(self):
self.notifier.stop()
klog.info('SITE[%s] exit watch', self.name)
def start(self):
if not os.path.isdir(self.path):
klog.warn('SITE[%s] path "%s" not exist',self.name, self.path);
return False
#init EventHandler
self.notifier = pyinotify.ThreadedNotifier(self.wm,self.ehandler)
klog.debug('SITE[%s] Exclude:%s',self.name, self.getExcludeList())
excl = pyinotify.ExcludeFilter(self.getExcludeList())
klog.info('SITE[%s] add watch', self.name)
self.wm.add_watch(self.path, pyinotify.ALL_EVENTS, rec=True,
exclude_filter=excl, auto_add=True)
#self.notifier.loop()
self.notifier.start()
klog.info('SITE[%s] start', self.name)
return True
def getOption(section, option, default=''):
global cf
if cf.has_option(section, option):
return cf.get(section, option)
else:
return default
script_path=sys.argv[0]
script_dir=os.path.dirname(script_path)
config_file=os.path.realpath(os.path.join(script_dir, 'config.ini'))
if not os.path.isfile(config_file):
klog.error("config not exit")
sys.exit(2)
cf = ConfigParser.ConfigParser()
try:
print config_file
cf.read(config_file)
except Exception as e:
logging.error(e)
sys.exit(1)
logging.info('demon start')
logging.debug('CONFIG:'+config_file)
has_valid=False
mThreads={}
#global config
gbackup_path=getOption('global','backup_path')
gbackup_ext=getOption('global','backup_ext')
for site in cf.sections():
if site =='global':
continue
if not cf.has_option(site, 'path'):
logging.error('SITE[%s] "no path in config file"', site)
continue
path=cf.get(site, 'path')
excl_list=getOption(site, 'exclude_list')
backup_path=getOption(site, 'backup_path',gbackup_path)
backup_ext=getOption(site, 'backup_ext',gbackup_ext)
t = myMonitor(site, path, excl_list )
t.setBackup(backup_path, backup_ext)
#continue
if t.start():
has_valid=True
mThreads[site]=t
if not has_valid:
klog.error("no valid site section in config file")
sys.exit()
try:
while 1:
time.sleep(2)
except KeyboardInterrupt:
for t in mThreads:
mThreads[t].exit()
print "main thread exit"
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/ksc/sitemonitor.git
git@gitee.com:ksc/sitemonitor.git
ksc
sitemonitor
sitemonitor
master

Search