最近有个监控需求,需要远程执行集群每个节点上的脚本,并获取脚本执行结果,为了安全起见不需要账号密码登陆主机,要求只需要调用远程脚本模块的方法就能实现。
总结下python进行远程调用脚本方法:
登陆主机执行脚本,python模块支持如 pssh、pexpect、paramiko
以远程方法调用(不需要登陆主机),python模块 rpyc,支持分布式
socket 方式,稍显复杂,需要熟悉网络协议,起点比较高
rpyc支持远程调用、分布式计算,以较少代码量实现需复杂socket编程,本文主要介绍 rpyc 并用它来实现一个 demo。
以代码方式介绍:
需求:分别执行集群每个节点上 server 端的脚本,并返回执行结果给 client 端
#Monitor_RPC_Client.py ... hostDict = {‘*.*.*.189‘: 12345, ‘*.*.*..188‘: 12345, ‘*.*.*..187‘: 12345} class ProcessWorker(Thread): def __init__(self, queue): Thread.__init__(self) self.queue = queue def run(self): while True: host, port, localPath = self.queue.get() try: c = rpyc.connect(host, port) localFileSize = c.root.getLocalFileSize(localPath, glob30minAgo) localFileSizeDict[host] = localFileSize c.close() except Exception, e: print ‘{0} → {1}:{2} occur a Error:{3}\n‘.format(self.getName(), host, port, e) def getLocalSize(localPath): queue = Queue() for x in range(3): worker = ProcessWorker(queue) worker.daemon = True worker.start() for (host, port) in hostDict.items(): queue.put((host, port, localPath)) time.sleep(3) # queue.join() ... #Monitor_RPC_Server.py ... datePattern = re.compile(r‘\d{4}(?:-\d{2}){4}‘) def get_ip_address(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # SIOCGIFADDR struct.pack(‘256s‘, ifname[:15]) )[20:24]) class remote_call_func(Service): def on_connect(self): print "[{0}]\t--------------<<< on_connect".format(getNowTime()) def on_disconnect(self): print "[{0}]\t-------------->>> on_disconnect".format(getNowTime()) def exposed_getLocalFileSize(self, path, glob30minAgo): exitCode, execResult = commands.getstatusoutput("ls -lrt " + path + "`|awk ‘{s+=$5}END{print s}‘") dateTime30minAgo = (datetime.datetime.now() - datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") print "[{0}] → {1} → {2}".format(dateTime30minAgo, path, format(execResult, ‘,‘)) return execResult rpycServer = ThreadedServer(remote_call_func, hostname=get_ip_address(‘eth0‘), port=12345, auto_register=False) rpycServer.start()
官方文档中类似例子很多,就不详细介绍了,需注意两点:
server端定义方法需要被client调用,必须定义以exposed 开头的方法,不然会报错AttributeError: ‘remote_call_script’ object has no attribute ‘exposed_iamshell’
server端默认不设认证机制,如果需要认证有推荐两种方法: ThreadedServer的authenticator参数与SSL模块
pip install rpyc ,如果 import rpyc 报错则 yum install openssl-devel,然后重新编译、安装 python
当然还需要考虑很多异常处理,如超时、验证失败等。
Refer:
[1] python远程调用脚本(一)
http://rpyc.readthedocs.org/en/latest/tutorial.html
[2] python学习——python中执行shell命令
http://zhou123.blog.51cto.com/4355617/1312791
原文:http://my.oschina.net/leejun2005/blog/471624