1. RPC异步执行命令
  1. 需求:
  • 利用RibbitMQ进行数据交互
  • 可以对多台服务器进行操作
  • 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印
  • 实现异步操作

不懂rpc的请移步http://www.cnblogs.com/lianzhilei/p/5977545.html(最下边)

本节涉及最多的还是rabbitmq通信原理知识,要求安装rabbitmq服务

程序用广播topic模式做更好

程序目录结构:

程序简介:

  1. # 异步rpc程序
  2.  
  3. # 博客地址
  4. [第11天博客地址](http://www.cnblogs.com/lianzhilei/p/5970176.html)
  5. (http://www.cnblogs.com/lianzhilei/p/5970176.html)
  6.  
  7. ## 、需求
  8. - [ ] 利用RibbitMQ进行数据交互
  9. - [ ] 可以对多台服务器进行操作
  10. - [ ] 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印
  11. - [ ] 实现异步操作
  12.  
  13. ## 备注
  14.  
  15. - [ ] RabbitMQ队列名:
  16. ①执行命令时,队列名为服务器端的IP
  17. ②查询数据时,用的是回调时随机生成的callback_queue
  18. - [ ] threading多线程:
  19. 实现命令执行后不等待执行结果,依然可以输入新的指令
  20.  
  21. - [ ] 执行命令格式:
  22. -->>run "dir" host 192.168.20.22 192.168.20.23
  23. dir server端要执行的命令
  24. host host后可跟一个或多个可以通过rabbitMQ的服务器地址
  25.  
  26. - [ ] 查看后台所有的TASK_ID信息:
  27. -->>check_all
  28. 显示结果样式:TASK_ID【】 HOST192.168.20.22 COMMANDdir
  29. TASK_ID【】 HOST192.168.20.23 COMMANDdir
  30.  
  31. - [ ] 查看TASK_ID对应的执行结果:
  32. -->>check_task
  33. check_all查到的TASK_ID

README.md

程序流程图:

服务器端:

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. # !/usr/bin/env python
  6. # -*- coding:utf-8 -*-
  7. # -Author-Lian
  8.  
  9. import pika
  10. import os
  11.  
  12. class Server(object):
  13. def __init__(self,rabbitmq,queue_name):
  14. self.queue_name = queue_name
  15. self.connection = pika.BlockingConnection(pika.ConnectionParameters(
  16. host=rabbitmq))
  17. self.channel = self.connection.channel()
  18. self.channel.queue_declare(queue=self.queue_name)
  19.  
  20. def handle(self,command):
  21. command = command.decode()
  22. print(command,type(command))
  23. message = os.popen(command).read()
  24. if not message:
  25. message = "Wrong Command"
  26. return message
  27.  
  28. def on_request(self,ch, method, props, body):
  29. response = self.handle(body)
  30. ch.basic_publish(exchange='',
  31. routing_key=props.reply_to, # 回信息队列名
  32. properties=pika.BasicProperties(correlation_id=
  33. props.correlation_id),
  34. body=str(response))
  35. ch.basic_ack(delivery_tag=method.delivery_tag)
  36.  
  37. def start(self):
  38. self.channel.basic_consume(self.on_request,
  39. queue=self.queue_name)
  40.  
  41. print(" [x] Awaiting RPC requests")
  42. self.channel.start_consuming()
  43.  
  44. if __name__ == "__main__":
  45. rabbitmq = "localhost" #rabbitmq服务器地址
  46. queue_name = "192.168.20.22" #queue_name为本地ip地址
  47. server = Server(rabbitmq,queue_name)
  48. server.start()

server.py

客户端:

bin目录:

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3.  
  4. import sys
  5. import os
  6. import platform
  7.  
  8. #添加BASE_DIR,添加顶级目录到路径中,方便调用其他目录模块
  9. if platform.system() == 'Windows':
  10. print(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
  11. BASE_DIR = '\\'.join(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
  12. else:
  13. BASE_DIR = '/'.join(os.path.abspath(os.path.dirname(__file__)).split('/')[:-1])
  14.  
  15. #加载环境变量
  16. sys.path.append(BASE_DIR)
  17. from conf import settings
  18. from core import main
  19.  
  20. if __name__ == '__main__':
  21. obj = main.Handler()
  22. obj.start()

start.py

conf目录:

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. __author__ = 'luotianshuai'
  4.  
  5. import os
  6. import sys
  7. import platform
  8.  
  9. if platform.system() == 'Windows':
  10. BASE_DIR = '\\'.join(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
  11. school_dbpaths = os.path.join(BASE_DIR,'school_db')
  12.  
  13. else:
  14. BASE_DIR = '/'.join(os.path.abspath(os.path.dirname(__file__)).split('/')[:-1])
  15. school_dbpaths =os.path.join(BASE_DIR, 'school_db')
  16.  
  17. #rabbitmq服务地址ip
  18. RabbitMQ_IP = 'localhost'

settings.py

core目录

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #-Author-Lian
  4.  
  5. from conf import settings
  6. from modules.client import Client
  7. import random,time
  8. import threading
  9.  
  10. class Handler(object):
  11. def __init__(self):
  12. self.information = {} # 后台进程信息
  13.  
  14. def check_all(self,*args):
  15. '''查看所有task_id信息'''
  16. time.sleep(2)
  17. for key in self.information:
  18. print("TASK_ID【%s】\tHOST【%s】\tCOMMAND【%s】"%(key,self.information[key][0],
  19. self.information[key][1]))
  20.  
  21. def check_task(self,user_cmd):
  22. '''查看task_id执行结果'''
  23. time.sleep(2)
  24. try:
  25. task_id = user_cmd.split()[1]
  26. task_id = int(task_id)
  27. callback_queue=self.information[task_id][2]
  28. callback_id=self.information[task_id][3]
  29. client = Client()
  30. response = client.get_response(callback_queue, callback_id)
  31. print(response.decode())
  32. del self.information[task_id]
  33.  
  34. except KeyError as e :
  35. print("\33[31;0mWrong id[%s]\33[0m"%e)
  36. except IndexError as e:
  37. print("\33[31;0mWrong id[%s]\33[0m"%e)
  38.  
  39. def run(self,user_cmd):
  40. '''执行命令'''
  41. try:
  42. time.sleep(2)
  43. #print("--->>",user_cmd)
  44. command = user_cmd.split("\"")[1]
  45. hosts = user_cmd.split()[3:]
  46. for host in hosts:
  47. task_id = random.randint(10000, 99999)
  48. client = Client()
  49. response = client.call(host, command)
  50. # print(response)
  51. self.information[task_id] = [host, command, response[0],response[1]]
  52. except IndexError as e:
  53. print("\33[31;0mError:%s\33[0m"%e)
  54.  
  55. def reflect(self,str,user_cmd):
  56. '''反射'''
  57. if hasattr(self, str):
  58. getattr(self, str)(user_cmd)
  59. # else:
  60. # setattr(self, str, self.foo)
  61. # getattr(self, str)()
  62.  
  63. def start(self):
  64. while True:
  65. user_cmd = input("->>").strip()
  66. if not user_cmd:continue
  67. str = user_cmd.split()[0]
  68. t1 = threading.Thread(target=self.reflect,args=(str,user_cmd)) #多线程
  69. t1.start()

main.py

modules目录

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # -Author-Lian
  4.  
  5. import pika
  6. import uuid
  7. from conf import settings
  8.  
  9. class Client(object):
  10. def __init__(self):
  11. self.connection = pika.BlockingConnection(pika.ConnectionParameters(
  12. host=settings.RabbitMQ_IP))
  13. self.channel = self.connection.channel()
  14.  
  15. def on_response(self, ch, method, props, body):
  16. '''获取命令执行结果的回调函数'''
  17. # print("验证码核对",self.callback_id,props.correlation_id)
  18. if self.callback_id == props.correlation_id: # 验证码核对
  19. self.response = body
  20. ch.basic_ack(delivery_tag=method.delivery_tag)
  21.  
  22. def get_response(self,callback_queue,callback_id):
  23. '''取队列里的值,获取callback_queued的执行结果'''
  24. self.callback_id = callback_id
  25. self.response = None
  26. self.channel.basic_consume(self.on_response, # 只要收到消息就执行on_response
  27. queue=callback_queue)
  28. while self.response is None:
  29. self.connection.process_data_events() # 非阻塞版的start_consuming
  30. return self.response
  31.  
  32. def call(self,queue_name,command):
  33. '''队列里发送数据'''
  34. result = self.channel.queue_declare(exclusive=False) #exclusive=False 必须这样写
  35. self.callback_queue = result.method.queue
  36. self.corr_id = str(uuid.uuid4())
  37. # print(self.corr_id)
  38. self.channel.basic_publish(exchange='',
  39. routing_key=queue_name,
  40. properties=pika.BasicProperties(
  41. reply_to=self.callback_queue, # 发送返回信息的队列name
  42. correlation_id=self.corr_id, # 发送uuid 相当于验证码
  43. ),
  44. body=command)
  45.  
  46. return self.callback_queue,self.corr_id

client.py

运行示例图

Python开发【项目】:RPC异步执行命令(RabbitMQ双向通信)的更多相关文章

  1. Python开发程序:RPC异步执行命令(RabbitMQ双向通信)

    RPC异步执行命令 需求: 利用RibbitMQ进行数据交互 可以对多台服务器进行操作 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印 实现异步操作 不懂rpc的请移步h ...

  2. Saltstack异步执行命令(十三)

    Saltstack异步执行命令 salt执行命令有时候会有超时的问题,就是命令下发下去了,部分主机没有返回信息,这时候就很难判断命令或任务是否执行成功.因此,salt提供异步执行的功能,发出命令后立即 ...

  3. Python开发项目:大型模拟战争游戏(外星人入侵)

    外星人入侵 游戏概述: 现在准备用python开始搞一个大型游戏,模拟未来战争,地球人狙击外星人大战(其实就是小蜜蜂游戏2333),玩家控制一个飞船,用子弹歼灭屏幕上空的外星飞船:项目用到了Pygam ...

  4. python之实现批量远程执行命令(堡垒机)

    python远程批量执行 我并不是一个专业的开发,我一直在学习linux运维,对于python也是接触不久,所以代码写的并不是很规范简洁. 前段时间一个同学找我一起做一个自动化运维平台,我对pytho ...

  5. Python通过paramiko批量远程主机执行命令

    一.前言 在日常运维的过程中,经常需要登录主机去执行一些命令,有时候需要登录一批主机执行相同的命,手动登录执行的化效率太慢, 所以可以通过Python的paramiko模块批量执行,本篇文章基于pyt ...

  6. Python 实现远程服务器批量执行命令

    paramiko 远程控制介绍 Python paramiko是一个相当好用的远程登录模块,采用ssh协议,可以实现linux服务器的ssh远程登录.首先来看一个简单的例子 import parami ...

  7. python通过getopt模块获取执行命令参数

    python脚本和shell脚本一样可以获取命令行的参数,根据不同的参数,执行不同的逻辑处理. 通常我们可以通过getopt模块获得不同的执行命令和参数. 下面我通过新建一个test.py的脚本解释下 ...

  8. websocket+Django+python+paramiko实现web页面执行命令并实时输出

    一.概述 WebSocket WebSocket的工作流程:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 T ...

  9. 【python】用python脚本Paramiko实现远程执行命令、下载、推送/上传文件功能

    Paramiko: paramiko模块,基于SSH用于连接远程服务器并执行相关操作. SSHClient: 用于连接远程服务器并执行基本命令 SFTPClient: 用于连接远程服务器并执行上传下载 ...

随机推荐

  1. cutadapt 的安装与使用

    cutadapt 是一款质量过滤的软件, 它可以删除adapter, primer. polyA尾等序列:也可以用来去除低质量序列 源代码: https://github.com/marcelm/cu ...

  2. linux下安装dovecot

    Dovecot是一个开源的,为Linux/Unix-like系统提供IMAP,POP3服务的软件.主要是为了安全产生的,不管大小应用,Dovecot都是一个非常优秀的选择.它非常快,配置简单,不需要专 ...

  3. Unity3D - 详解Quaternion类(一)

    一.简介 Quaternion又称四元数,由x,y,z和w这四个分量组成,是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的数学概念.四元数的乘法不符合交换律.从明确地角度而言,四元数是复数的不可交 ...

  4. 一直误解的memset函数

    1.“想当然”导致的后果 今天犯了一个十分低级的错误,在对一个整型数组用memset进行初始化设置所有元素值为1.可是结果却大出所料,很意外啊!接着,我就做了代码测试. #include <io ...

  5. ORACLE expdp/impdp导出实例

    服务器上以sys或system超级管理员登录. SQL>create directory expdp_dir as '/home/oracle/dmpdata';(dmpdata 需要建立.赋予 ...

  6. 第三章 Spring.Net 环境准备和搭建

    在前面一章我们介绍了依赖注入,控制反转的概念.接下来我们来真正动手搭建一下Spring.Net的环境,看一下Spring.Net 中的控制反转和依赖注入是什么样子. 3.1  Spring.Net 下 ...

  7. Windows 端口占用

    1.netstat -ano | findstr "80"( 80为提示被占用的端口): 2.tasklist | findstr "5584"(5584是从上 ...

  8. 用命令行执行ROBOT FRAMEWORK用例

    转自:http://www.51testing.com/html/86/n-1430786.html 除了在ride中执行用例,我们也可以通过命令行的形式执行用例. 1.执行一整个项目 pybot+项 ...

  9. webstorm配置babel自动转译es6的方法

    1.npm安装babel npm install -g babel-cli 2.npm安装Babel的preset npm install --save-dev babel-preset-es2015 ...

  10. Js跨域、父级窗口执行JS赋值、取值,更改元素

    网站域名: A:http://www.xxoo.com/a.html B:http://www.aabb.com/b.html B网站嵌套与A网站(A的a中的Iframe指向B中的b)b要让父级a页面 ...