平时工作中做大量的分发工作是使用研发部同事基于twisted设计的一套很不错的程序。当然该同事比较大牛。很好奇也想自己来做这样的一套,做为一个python新手来说,纯粹是在扯淡。在网上看了些资料,依样画葫芦,写个入门级的。配置文件参照了同事大牛的风格。
#!/usr/bin/env python
import subprocess
import ConfigParser
"""
A ssh based command dispatch system
"""
def readConfig(file="config.ini"):
"""Extract IP addresses and CMDS from config file and returns tuple"""
ips = []
cmds = []
Config = ConfigParser.ConfigParser()
Config.read(file)
machines = Config.items("MACHINES")
commands = Config.items("COMMANDS")
for ip in machines:
ips.append(ip[1])
for cmd in commands:
cmds.append(cmd[1])
return ips, cmds
ips, cmds = readConfig()
for ip in ips:
for cmd in cmds:
subprocess.call("ssh root@%s %s" % (ip, cmd), shell=True)
下一步准备解决多线程及异步请求的问题,当然以我目前的python水平来说还属于痴人说梦。当然还是要想想的,主要是想使用django来做套bs构架的分发工具,又或用pyqt来做套desktop级的跨平台的工具。又或者。。。。。。
我还是好好看的入门级书籍《python学习手册》吧.
接上次:http://blog.oldyang.net/archives/163
对部分功能进行了完善,先放这里以后接着优化
update:2010-2-28:今天下午看了点资料,对程序的线程处理上进行了部分优化,性能又提高了小小。
查看源代码打印帮助
001 #!/usr/bin/env python
002 # -*- coding: utf-8 -*-
003
004 """
005 FileName : dispatch.py
006 Autor: David Young <e4twood@gmail.com>
007 Version:0.1.4(20100228)
008 A ssh based command simple dispatch tool
009 Using this program requires paramiko support, so that before the use of the python modules to install paramiko
010
011 Usage:
012 python dispatch.py CONFIGFILE
013 Example:
014 python dispatch.py conf/config.ini
015
016 More config options please see the config file on conf directory
017 """
018
019 #导入相关模块
020 import Crypto
021 import paramiko
022 import os
023 import time
024 import ConfigParser
025 import base64
026 import sys
027 from threading import Thread
028 from Queue import Queue
029 from paramiko import AutoAddPolicy, SSHClient
030
031 queue = Queue()
032
033 #记录开始时间戳
034 start = int(time.time())
035
036 # 检查参数个数
037 if len(sys.argv) <= 1:
038 print ‘Error!missing parameter.’
039 print ‘Usage:python %s configfile’ % sys.argv[0]
040 print ‘Example:python %s conf/config.ini’ % sys.argv[0]
041 exit(1)
042
043 #读取配置文件
044 configfile = sys.argv[1]
045 def readConfig(file=configfile):
046 ips = []
047 cmds = []
048 Config = ConfigParser.ConfigParser()
049 Config.read(file)
050 username = Config.get("BASEINFO","USERNAME")
051 password = base64.b64decode(Config.get("BASEINFO","PASSWORD"))
052 port = int(Config.get("BASEINFO","PORT"))
053 threads = int(Config.get("BASEINFO","THREADS"))
054 log_file = Config.get("BASEINFO","LOG_FILE")
055 log_level = int(Config.get("BASEINFO","LOG_LEVEL"))
056 pid_file = Config.get("BASEINFO","PID_FILE")
057 machines = Config.items("MACHINES")
058 commands = Config.items("COMMANDS")
059 for ip in machines:
060 ips.append(ip[1])
061 for cmd in commands:
062 cmds.append(cmd[1])
063 return ips, cmds, username, password, port, threads, log_file, log_level, pid_file
064
065 ips, cmds, username, password, port, threads, log_file, log_level, pid_file = readConfig()
066
067 #记录当前pid
068 pid = str(os.getpid())
069 f = file(pid_file, ‘w’)
070 f.write(pid)
071 f.close
072
073 #使用paramiko进行远程SSH调用
074 def launcher(i,q, cmd):
075 while True:
076 ip = q.get()
077 for cmd in cmds:
078 try:
079 paramiko.util.log_to_file(log_file, level = log_level)
080 client = paramiko.SSHClient()
081 client.set_missing_host_key_policy(AutoAddPolicy())
082 client.connect((ip), username=(username), password=(password), port=(port))
083 stdin, stdout, stderr = client.exec_command(cmd)
084 print stdout.read()
085 client.close()
086 except:
087 pass
088 print "Connect to %s Failed!" % ip
089 q.task_done()
090
091 #使用线程启动,并检测线程数量
092 if len(ips) < threads:
093 num_threads = len(ips)
094 else:
095 num_threads = threads
096
097 for i in range(num_threads):
098 for cmd in cmds:
099 worker = Thread(target=launcher, args=(i, queue, cmd))
100 worker.setDaemon(True)
101 worker.start()
102
103 #线程排队
104 for ip in ips:
105 queue.put(ip)
106 queue.join()
107
108 #打印任务结束时间戳
109 end = int(time.time())
110
111 #统计任务运行时间
112 print "Dispatch Task Completed in %s seconds" % (end – start)
配置文件式例:
查看源代码打印帮助01 ;基本的配置信息
02 [BASEINFO]
03 ;远程ssh主机用户名
04 USERNAME = root
05 ;远程ssh主机密码,做base64加密处理
06 PASSWORD = <code>MTIzMzMzMw</code><code>=</code><code>=</code>
07 ;远程ssh主机端口
08 PORT = 22
09 ;线程数量 默认为10,并非越多越好。
10 THREADS = 10
11 ;日志存放路径
12 LOG_FILE = logs/dispatch.log
13 ;日志等级,分别为10,20,30,40,50
14 LOG_LEVEL = 10
15 ;pid文件存放路径
16 PID_FILE = logs/dispatch.pid
17 ;主机列表
18 [MACHINES]
19 APP2 : 192.168.0.1
20 APP3 : 192.168.1.8
21 ;命令列表
22 [COMMANDS]
23 B : echo `hostname`