day11-RPC
作业要求:
可以对指定机器异步的执行多个命令
例子:
>>:run "df -h" --hosts 192.168.3.55 10.4.3.4
task id: 45334
>>: check_task 45334
>>:
注意,每执行一条命令,即立刻生成一个任务ID,不需等待结果返回,通过命令check_task TASK_ID来得到任务结果
server
1 import pika 2 import paramiko,os, 3 4 class Server(object): 5 def __init__(self,rabbitmq,queue_name): 6 self.queue_name = queue_name 7 self.connection = pika.BlockingConnection(pika.ConnectionParameters( 8 host=rabbitmq)) 9 self.channel = self.connection.channel() 10 self.channel.queue_declare(queue=self.queue_name) 11 12 def handle(self,cmd,host): 13 14 #print(cmd,host) 15 message = self.paramiko_ex(cmd,host) 16 if not message: 17 message = "Wrong Command" 18 return message 19 20 def paramiko_ex(self,command,host): 21 transport =paramiko.Transport((host,22)) 22 transport.connect(username="root",password="cdw123") #用户密码简单写死,可以扩展类别根据IP 判断用户,密码。 23 ssh=paramiko.SSHClient() 24 ssh._transport = transport 25 stdin,stdout,stderr = ssh.exec_command(command) 26 #print(stdout.read().decode()) 27 ack_msg=stdout.read().decode() 28 #print(ack_msg) 29 transport.close() 30 return ack_msg 31 32 def on_request(self,ch, method, props, body): 33 #print(body,type(body)) 34 body=body.decode() 35 body=body.split("_") 36 cmd,host=body[0],body[1] 37 #print(cmd,host) 38 response = self.handle(cmd,host) 39 ch.basic_publish(exchange='', 40 routing_key=props.reply_to, # 回信息队列名 41 properties=pika.BasicProperties(correlation_id= 42 props.correlation_id), 43 body=str(response)) 44 ch.basic_ack(delivery_tag=method.delivery_tag) 45 46 def start(self): 47 self.channel.basic_consume(self.on_request, 48 queue=self.queue_name) 49 50 print(" [x] Awaiting RPC requests") 51 self.channel.start_consuming() 52 53 54 if __name__ == "__main__": 55 rabbitmq = "localhost" #rabbitmq服务器地址 56 queue_name = "rpc_5" 57 server = Server(rabbitmq,queue_name) 58 server.start()
client
1 import pika,random,uuid,threading 2 3 4 class Client(object): 5 def __init__(self): 6 self.connection = pika.BlockingConnection(pika.ConnectionParameters( 7 host="localhost")) 8 self.channel = self.connection.channel() 9 10 def on_response(self, ch, method, props, body): 11 '''获取命令执行结果的回调函数''' 12 # print("验证码核对",self.callback_id,props.correlation_id) 13 if self.callback_id == props.correlation_id: # 验证码核对 14 self.response = body 15 ch.basic_ack(delivery_tag=method.delivery_tag) 16 17 def get_response(self,callback_queue,callback_id): 18 '''取队列里的值,获取callback_queued的执行结果''' 19 self.callback_id = callback_id 20 self.response = None 21 self.channel.basic_consume(self.on_response, # 只要收到消息就执行on_response 22 queue=callback_queue) 23 while self.response is None: 24 self.connection.process_data_events() # 非阻塞版的start_consuming 25 return self.response 26 27 def call(self,host,command): 28 '''队列里发送数据''' 29 30 result = self.channel.queue_declare(exclusive=False) #exclusive=False 必须这样写 31 self.callback_queue = result.method.queue 32 self.corr_id = str(uuid.uuid4()) 33 # print(self.corr_id) 34 self.channel.basic_publish(exchange='', 35 routing_key="rpc_5", 36 properties=pika.BasicProperties( 37 reply_to=self.callback_queue, # 发送返回信息的队列name 38 correlation_id=self.corr_id, # 发送uuid 相当于验证码 39 ), 40 body=command+"_"+host) #组合命令,跟主机IP发给server 41 42 return self.callback_queue,self.corr_id 43 44 45 46 47 class Handler(object): 48 def __init__(self): 49 self.information = {} # 后台进程信息 50 def check_all(self,*args): 51 '''查看所有task_id信息''' 52 53 for key in self.information: 54 print("TASK_ID【%s】\tHOST【%s】\tCOMMAND【%s】"%(key,self.information[key][0], 55 self.information[key][1])) 56 57 def check_task(self,user_cmd): 58 '''查看task_id执行结果''' 59 60 try: 61 task_id = user_cmd.split()[1] 62 task_id = int(task_id) 63 callback_queue=self.information[task_id][2] 64 callback_id=self.information[task_id][3] 65 client = Client() 66 response = client.get_response(callback_queue, callback_id) 67 print(response.decode()) 68 del self.information[task_id] 69 70 except KeyError as e : 71 print("\33[31;0mWrong id[%s]\33[0m"%e) 72 except IndexError as e: 73 print("\33[31;0mWrong id[%s]\33[0m"%e) 74 75 def run(self,user_cmd): 76 '''执行命令''' 77 try: 78 #time.sleep(2) 79 #print("--->>",user_cmd) 80 #print(user_cmd) 81 command = user_cmd.split("\"")[1] 82 #print(user_cmd.split()[4:]) 83 hosts = user_cmd.split()[4:] 84 for host in hosts: 85 #print(command,host) 86 # cmd_dict={"cmd":command, 87 # "host":hosts} 88 task_id = random.randint(10000, 99999) 89 client = Client() 90 response = client.call(host, command) 91 # print(response) 92 self.information[task_id] = [host, command, response[0],response[1]] 93 except IndexError as e: 94 print("\33[31;0mError:%s\33[0m"%e) 95 96 def reflect(self,str,user_cmd): 97 '''反射''' 98 if hasattr(self, str): 99 getattr(self, str)(user_cmd) 100 101 102 def start(self): 103 while True: 104 user_cmd = input("->>").strip() 105 if not user_cmd:continue 106 str = user_cmd.split()[0] 107 t1 = threading.Thread(target=self.reflect,args=(str,user_cmd)) #多线程 108 t1.start() 109 110 if __name__ == '__main__': 111 obj = Handler() 112 obj.start()

浙公网安备 33010602011771号