最近有个监控需求,需要远程执行集群每个节点上的脚本,并获取脚本执行结果,为了安全起见不需要账号密码登陆主机,要求只需要调用远程脚本模块的方法就能实现。
总结下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