代码更新系统(一):配置文件配置

  • 背景:

平常工作中,经常写更新脚本,一个会拉,一会推,一会使用ssh隧道。脚本好几个不利于管理。一直以来都想些一套更新系统。系统可以复用,可以自己选择在配置文件里更新方法或者选择在WEB上配置,WEB接受更新和展示更新状态,甚至在WEB实事执行更新操作。为了实现这些功能,一步步来,先实现从配置文件里读取配置并执行更新。以后功能都写好后再整合

  • 更新工具:rsync
  • 代码
  1 #-*- coding: utf-8 -*-
  2 '''
  3 Created on 2013-7-1
  4 
  5 @author: Jin
  6 '''
  7 import os
  8 import sys
  9 import ConfigParser
 10 import logging
 11 import subprocess
 12 
 13 #vars
 14 config_file='./config.ini'
 15 homedir   = './'
 16 logfile   = os.path.basename(sys.argv[0])+'.log'
 17 logpath   = homedir+logfile
 18 
 19 #logconfig
 20 logging.basicConfig(level=logging.DEBUG,
 21                     format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
 22                     datefmt='%Y-%m-%d %H:%M',
 23                     filename=logpath,
 24                     filemode='a')
 25 
 26 console = logging.StreamHandler()
 27 console.setLevel(logging.INFO)
 28 formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
 29 console.setFormatter(formatter)
 30 logging.getLogger('').addHandler(console)
 31 
 32 
 33 def check_file(filename):
 34     if os.path.exists(filename) and os.path.isfile(filename):
 35         return True
 36     else:
 37         return False
 38     
 39 def config_from_file(config_file='./config.ini'):
 40     '''
 41     Get config from config file.return dict date
 42     The dict keys is:'method','action','rsync_bin','ip','user','argv','excludeconf','localdir','pwdfile','module','remotedir'
 43     If pwdfile,module,excludeconf undefine,will use default set:
 44     password file is '/etc/rsync/rsync_default.secrets'
 45     module is 'default'
 46     excludeconf is '/etc/rsync/exclude_files.conf'
 47     '''
 48     
 49     if check_file(config_file):
 50         config=ConfigParser.ConfigParser()
 51         config.read(config_file)
 52         
 53         if config.has_option('rsyncclient','method'):
 54             method=config.get('rsyncclient','method')
 55         else:
 56             method=None           
 57         if config.has_option('rsyncclient','action'):
 58             action=config.get('rsyncclient','action')
 59         else:
 60             action=None
 61         if config.has_option('rsyncclient','rsync_bin'):
 62             rsync_bin=config.get('rsyncclient','rsync_bin')
 63         else:
 64             rsync_bin='rsync'
 65         if config.has_option('rsyncclient','ip'):
 66             ip=config.get('rsyncclient','ip')
 67         else:
 68             ip=None   
 69         if config.has_option('rsyncclient','user'):
 70             user=config.get('rsyncclient','user')
 71         else:
 72             user=None           
 73         if config.has_option('rsyncclient','argv'):
 74             argv=config.get('rsyncclient','argv')
 75         else:
 76             argv=None       
 77         if config.has_option('rsyncclient','localdir'):
 78             localdir=config.get('rsyncclient','localdir')
 79         else:
 80             localdir=None           
 81         if config.has_option('rsyncclient','excludeconf'):
 82             excludeconf=config.get('rsyncclient','excludeconf')
 83         else:
 84             excludeconf='/etc/rsync/exclude_files.conf'
 85                    
 86         #method daemon options  need passwordfile and module         
 87         if config.has_option('rsyncclient','pwdfile'):
 88             pwdfile=config.get('rsyncclient','pwdfile')
 89         else:
 90             pwdfile='/etc/rsync/rsync_default.secrets'
 91         if config.has_option('rsyncclient','module'):
 92             module=config.get('rsyncclient','module')
 93         else:
 94             module='default'
 95         
 96         #method ssh options need remotedir
 97         if config.has_option('rsyncclient','remotedir'):
 98             remotedir=config.get('rsyncclient','remotedir')
 99         else:
100             remotedir=None
101           
102         data = {'method':method,'action':action,'rsync_bin':rsync_bin,'ip':ip,'user':user,'argv':argv,'localdir':localdir,'excludeconf':excludeconf,'pwdfile':pwdfile,'module':module,'remotedir':remotedir}
103         #logging.debug("data:%s" % data)
104         return data
105     
106     else:
107         logging.error("%s is not exist" % config_file) 
108         return None    
109         
110 def get_cmd(configdata):
111     '''
112     assembling command from config dict
113     '''
114     if type(configdata)==type({}):   
115         if None in configdata.values():
116             for key in configdata:
117                 if configdata[key] == None:
118                     logging.error("%s is undefine!" % key)
119                     return None
120         else: 
121             if configdata['method']=='daemon' and configdata['action']=='push':
122                 '''push local to rsync daemon server'''
123                 cmd=configdata['rsync_bin']+' '+configdata['argv']+' '+'--exclude-from='+configdata['excludeconf']+' '+'--password-file='+configdata['pwdfile']+' '+configdata['localdir']+' '+configdata['user']+'@'+configdata['ip']+'::'+configdata['module']
124                 return cmd
125             elif configdata['method']=='daemon' and configdata['action']=='pull':
126                 '''pull from rsync daemon server to local'''
127                 cmd=configdata['rsync_bin']+' '+configdata['argv']+' '+'--exclude-from='+configdata['excludeconf']+' '+'--password-file='+configdata['pwdfile']+' '+configdata['user']+'@'+configdata['ip']+'::'+configdata['module']+' '+configdata['localdir']
128                 return cmd
129             elif configdata['method']=='ssh' and configdata['action']=='push':
130                 '''push local to remote server use ssh'''
131                 cmd=configdata['rsync_bin']+' '+configdata['argv']+' '+'-e '+configdata['method']+' '+'--exclude-from='+configdata['excludeconf']+' '+configdata['localdir']+' '+configdata['user']+'@'+configdata['ip']+':'+configdata['remotedir']
132                 return cmd
133             elif configdata['method']=='ssh' and configdata['action']=='pull':
134                 '''pull from to remote server to local use ssh'''
135                 cmd=configdata['rsync_bin']+' '+configdata['argv']+' '+'-e '+configdata['method']+' '+'--exclude-from='+configdata['excludeconf']+' '+configdata['user']+'@'+configdata['ip']+':'+configdata['remotedir']+' '+configdata['localdir']
136                 return cmd
137             else:
138                 '''undefine'''
139                 logging.error("method:%s or action:%s error!" % (configdata['method'],configdata['action']))
140                 return None  
141             
142 def check_rsyncclient_runevn(configdata):
143     '''check excludeconf,is not exists create it,check pwdfile,is not exists warning and exit'''
144     if not check_file(configdata['excludeconf']):
145         logging.info("%s is not exists,Now create it!" % configdata['excludeconf'])
146         with open(configdata['excludeconf'],'wt') as f:
147             f.write('')
148         
149     if configdata['method']=='daemon':
150         if not check_file(configdata['pwdfile']):
151             logging.error("%s is not exists!" % configdata['pwdfile'])
152             return False
153         else:
154             return True
155     elif configdata['method']=='ssh':
156         return True
157     else:
158         return False
159               
160 def is_running(processname):
161     '''Get processname status '''
162     cmd='/usr/bin/pgrep '+ processname+' > /dev/null 2>&1'
163     try:
164         #pstat=subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE)
165         pstat=subprocess.Popen(cmd,shell=True)
166     except StandardError,e:
167         logging.error("Get run status failed:: %s ,exit run!" % e)
168         sys.exit(1)
169     else:
170         pstat.wait()
171         if pstat.returncode == 0:
172             return True
173         else:
174             return False
175         
176 def run_command(cmd):
177     '''run command'''
178     if is_running('rsync'):
179         logging.warning("rsync is running!")
180     else:
181         try:
182             pstat=subprocess.Popen(cmd,shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
183         except StandardError,e: 
184             logging.error("Run script failed:: %d (%s) ,exit run!" % (e.errno, e.strerror))
185             sys.exit(1)
186         else:
187             pstat.wait()
188             if pstat.returncode == 0:
189                 logging.info("Run script Successful,exit code is %s" % pstat.returncode)
190                 lines=pstat.stdout.readlines()
191                 dellist=[]
192                 rsync_dict={}
193                 for line in lines:
194                     if 'deleting' in line:
195                         dellist.append(line.split()[1])
196                 delcount=len(dellist)
197                 addlist=[i.rstrip('\n') for i in lines[delcount+2:-3]]
198                 addcount=len(addlist)
199                 speed=' '.join(lines[-2].split()[-2:])
200                 rsync_dict={}
201                 rsync_dict['delcount']=delcount
202                 rsync_dict['dellist']=dellist
203                 rsync_dict['addcount']=delcount
204                 rsync_dict['addlist']=addlist
205                 rsync_dict['speed']=speed
206                 print rsync_dict
207                 logging.info("Result,delcount:%d,dellist:%s,addcount:%d,addlist:%s,speed:%s" % (delcount,dellist,addcount,addlist,speed))
208                     
209             else:
210                 logging.error("Run script End,exit code is %s,With reason <%s>" % (pstat.returncode,pstat.stderr.read().rstrip('\n')))
211                 
212 
213 def __main__():
214     configdata=config_from_file(config_file)
215     if configdata:
216         cmd=get_cmd(configdata)
217         if cmd:
218             if check_rsyncclient_runevn(configdata):
219                 run_command(cmd)
220             else:
221                 logging.error("check rsyncclient runenv fail,detail see log!")
222                 sys.exit(3)
223         else:
224             logging.error("command is None,detail see log!")
225             sys.exit(2)
226     else:
227         logging.error("configdata is None,detail see log!")
228         sys.exit(1)
229     
230         
231 if __name__ == '__main__':
232     __main__()
View Code
  • 配置文件格式

[rsyncclient]
action = pull
method = daemon
localdir = /tmp/testdir/
user = rsync_store
ip = 127.0.0.1
argv = -vzrtopg --delete
excludeconf=./exclude_files.conf
remotedir = /tmp/remotedir/
module = store
pwdfile = ./rsync_store.passwd

  • 代码简单说明:

check_file:判断文件存在且进为文件(排除文件存在为目录的情况)

config_from_file:从ini文件读取配置,吐出一个配置字典

get_cmd:将配置字典组合成一个command,根据method和

check_rsyncclient_runevn:根据配置字典检查rsync的运行环境 排除文件和密码文件,这里是我比较纠结的地方,要不要创建空的排除列表文件?

is_running:检查程序是否运行,其实不严谨,下一个版本看是否能改进

run_command():运行组合好的命令

 __main__():前面的函数逻辑上组合在一起

 

 

 

 

posted on 2013-07-04 10:50  @Jin  阅读(556)  评论(0编辑  收藏  举报

导航