Python开发【项目】:RPC异步执行命令(RabbitMQ双向通信)
- RPC异步执行命令
- 需求:
- 利用RibbitMQ进行数据交互
- 可以对多台服务器进行操作
- 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印
- 实现异步操作
不懂rpc的请移步http://www.cnblogs.com/lianzhilei/p/5977545.html(最下边)
本节涉及最多的还是rabbitmq通信原理知识,要求安装rabbitmq服务
程序用广播topic模式做更好
程序目录结构:
程序简介:
- # 异步rpc程序
- # 博客地址
- [第11天博客地址](http://www.cnblogs.com/lianzhilei/p/5970176.html)
- (http://www.cnblogs.com/lianzhilei/p/5970176.html)
- ## 、需求
- - [ ] 利用RibbitMQ进行数据交互
- - [ ] 可以对多台服务器进行操作
- - [ ] 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印
- - [ ] 实现异步操作
- ## 备注
- - [ ] RabbitMQ队列名:
- ①执行命令时,队列名为服务器端的IP
- ②查询数据时,用的是回调时随机生成的callback_queue名
- - [ ] threading多线程:
- 实现命令执行后不等待执行结果,依然可以输入新的指令
- - [ ] 执行命令格式:
- -->>run "dir" host 192.168.20.22 192.168.20.23
- dir server端要执行的命令
- host host后可跟一个或多个可以通过rabbitMQ的服务器地址
- - [ ] 查看后台所有的TASK_ID信息:
- -->>check_all
- 显示结果样式:TASK_ID【】 HOST【192.168.20.22】 COMMAND【dir】
- TASK_ID【】 HOST【192.168.20.23】 COMMAND【dir】
- - [ ] 查看TASK_ID对应的执行结果:
- -->>check_task
- 为check_all查到的TASK_ID
README.md
程序流程图:
服务器端:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- #-Author-Lian
- # !/usr/bin/env python
- # -*- coding:utf-8 -*-
- # -Author-Lian
- import pika
- import os
- class Server(object):
- def __init__(self,rabbitmq,queue_name):
- self.queue_name = queue_name
- self.connection = pika.BlockingConnection(pika.ConnectionParameters(
- host=rabbitmq))
- self.channel = self.connection.channel()
- self.channel.queue_declare(queue=self.queue_name)
- def handle(self,command):
- command = command.decode()
- print(command,type(command))
- message = os.popen(command).read()
- if not message:
- message = "Wrong Command"
- return message
- def on_request(self,ch, method, props, body):
- response = self.handle(body)
- ch.basic_publish(exchange='',
- routing_key=props.reply_to, # 回信息队列名
- properties=pika.BasicProperties(correlation_id=
- props.correlation_id),
- body=str(response))
- ch.basic_ack(delivery_tag=method.delivery_tag)
- def start(self):
- self.channel.basic_consume(self.on_request,
- queue=self.queue_name)
- print(" [x] Awaiting RPC requests")
- self.channel.start_consuming()
- if __name__ == "__main__":
- rabbitmq = "localhost" #rabbitmq服务器地址
- queue_name = "192.168.20.22" #queue_name为本地ip地址
- server = Server(rabbitmq,queue_name)
- server.start()
server.py
客户端:
bin目录:
- #!/usr/bin/env python
- #-*- coding:utf-8 -*-
- import sys
- import os
- import platform
- #添加BASE_DIR,添加顶级目录到路径中,方便调用其他目录模块
- if platform.system() == 'Windows':
- print(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
- BASE_DIR = '\\'.join(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
- else:
- BASE_DIR = '/'.join(os.path.abspath(os.path.dirname(__file__)).split('/')[:-1])
- #加载环境变量
- sys.path.append(BASE_DIR)
- from conf import settings
- from core import main
- if __name__ == '__main__':
- obj = main.Handler()
- obj.start()
start.py
conf目录:
- #!/usr/bin/env python
- #-*- coding:utf-8 -*-
- __author__ = 'luotianshuai'
- import os
- import sys
- import platform
- if platform.system() == 'Windows':
- BASE_DIR = '\\'.join(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
- school_dbpaths = os.path.join(BASE_DIR,'school_db')
- else:
- BASE_DIR = '/'.join(os.path.abspath(os.path.dirname(__file__)).split('/')[:-1])
- school_dbpaths =os.path.join(BASE_DIR, 'school_db')
- #rabbitmq服务地址ip
- RabbitMQ_IP = 'localhost'
settings.py
core目录
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- #-Author-Lian
- from conf import settings
- from modules.client import Client
- import random,time
- import threading
- class Handler(object):
- def __init__(self):
- self.information = {} # 后台进程信息
- def check_all(self,*args):
- '''查看所有task_id信息'''
- time.sleep(2)
- for key in self.information:
- print("TASK_ID【%s】\tHOST【%s】\tCOMMAND【%s】"%(key,self.information[key][0],
- self.information[key][1]))
- def check_task(self,user_cmd):
- '''查看task_id执行结果'''
- time.sleep(2)
- try:
- task_id = user_cmd.split()[1]
- task_id = int(task_id)
- callback_queue=self.information[task_id][2]
- callback_id=self.information[task_id][3]
- client = Client()
- response = client.get_response(callback_queue, callback_id)
- print(response.decode())
- del self.information[task_id]
- except KeyError as e :
- print("\33[31;0mWrong id[%s]\33[0m"%e)
- except IndexError as e:
- print("\33[31;0mWrong id[%s]\33[0m"%e)
- def run(self,user_cmd):
- '''执行命令'''
- try:
- time.sleep(2)
- #print("--->>",user_cmd)
- command = user_cmd.split("\"")[1]
- hosts = user_cmd.split()[3:]
- for host in hosts:
- task_id = random.randint(10000, 99999)
- client = Client()
- response = client.call(host, command)
- # print(response)
- self.information[task_id] = [host, command, response[0],response[1]]
- except IndexError as e:
- print("\33[31;0mError:%s\33[0m"%e)
- def reflect(self,str,user_cmd):
- '''反射'''
- if hasattr(self, str):
- getattr(self, str)(user_cmd)
- # else:
- # setattr(self, str, self.foo)
- # getattr(self, str)()
- def start(self):
- while True:
- user_cmd = input("->>").strip()
- if not user_cmd:continue
- str = user_cmd.split()[0]
- t1 = threading.Thread(target=self.reflect,args=(str,user_cmd)) #多线程
- t1.start()
main.py
modules目录
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # -Author-Lian
- import pika
- import uuid
- from conf import settings
- class Client(object):
- def __init__(self):
- self.connection = pika.BlockingConnection(pika.ConnectionParameters(
- host=settings.RabbitMQ_IP))
- self.channel = self.connection.channel()
- def on_response(self, ch, method, props, body):
- '''获取命令执行结果的回调函数'''
- # print("验证码核对",self.callback_id,props.correlation_id)
- if self.callback_id == props.correlation_id: # 验证码核对
- self.response = body
- ch.basic_ack(delivery_tag=method.delivery_tag)
- def get_response(self,callback_queue,callback_id):
- '''取队列里的值,获取callback_queued的执行结果'''
- self.callback_id = callback_id
- self.response = None
- self.channel.basic_consume(self.on_response, # 只要收到消息就执行on_response
- queue=callback_queue)
- while self.response is None:
- self.connection.process_data_events() # 非阻塞版的start_consuming
- return self.response
- def call(self,queue_name,command):
- '''队列里发送数据'''
- result = self.channel.queue_declare(exclusive=False) #exclusive=False 必须这样写
- self.callback_queue = result.method.queue
- self.corr_id = str(uuid.uuid4())
- # print(self.corr_id)
- self.channel.basic_publish(exchange='',
- routing_key=queue_name,
- properties=pika.BasicProperties(
- reply_to=self.callback_queue, # 发送返回信息的队列name
- correlation_id=self.corr_id, # 发送uuid 相当于验证码
- ),
- body=command)
- return self.callback_queue,self.corr_id
client.py
运行示例图
Python开发【项目】:RPC异步执行命令(RabbitMQ双向通信)的更多相关文章
- Python开发程序:RPC异步执行命令(RabbitMQ双向通信)
RPC异步执行命令 需求: 利用RibbitMQ进行数据交互 可以对多台服务器进行操作 执行命令后不等待命令的执行结果,而是直接让输入下一条命令,结果出来后自动打印 实现异步操作 不懂rpc的请移步h ...
- Saltstack异步执行命令(十三)
Saltstack异步执行命令 salt执行命令有时候会有超时的问题,就是命令下发下去了,部分主机没有返回信息,这时候就很难判断命令或任务是否执行成功.因此,salt提供异步执行的功能,发出命令后立即 ...
- Python开发项目:大型模拟战争游戏(外星人入侵)
外星人入侵 游戏概述: 现在准备用python开始搞一个大型游戏,模拟未来战争,地球人狙击外星人大战(其实就是小蜜蜂游戏2333),玩家控制一个飞船,用子弹歼灭屏幕上空的外星飞船:项目用到了Pygam ...
- python之实现批量远程执行命令(堡垒机)
python远程批量执行 我并不是一个专业的开发,我一直在学习linux运维,对于python也是接触不久,所以代码写的并不是很规范简洁. 前段时间一个同学找我一起做一个自动化运维平台,我对pytho ...
- Python通过paramiko批量远程主机执行命令
一.前言 在日常运维的过程中,经常需要登录主机去执行一些命令,有时候需要登录一批主机执行相同的命,手动登录执行的化效率太慢, 所以可以通过Python的paramiko模块批量执行,本篇文章基于pyt ...
- Python 实现远程服务器批量执行命令
paramiko 远程控制介绍 Python paramiko是一个相当好用的远程登录模块,采用ssh协议,可以实现linux服务器的ssh远程登录.首先来看一个简单的例子 import parami ...
- python通过getopt模块获取执行命令参数
python脚本和shell脚本一样可以获取命令行的参数,根据不同的参数,执行不同的逻辑处理. 通常我们可以通过getopt模块获得不同的执行命令和参数. 下面我通过新建一个test.py的脚本解释下 ...
- websocket+Django+python+paramiko实现web页面执行命令并实时输出
一.概述 WebSocket WebSocket的工作流程:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 T ...
- 【python】用python脚本Paramiko实现远程执行命令、下载、推送/上传文件功能
Paramiko: paramiko模块,基于SSH用于连接远程服务器并执行相关操作. SSHClient: 用于连接远程服务器并执行基本命令 SFTPClient: 用于连接远程服务器并执行上传下载 ...
随机推荐
- cutadapt 的安装与使用
cutadapt 是一款质量过滤的软件, 它可以删除adapter, primer. polyA尾等序列:也可以用来去除低质量序列 源代码: https://github.com/marcelm/cu ...
- linux下安装dovecot
Dovecot是一个开源的,为Linux/Unix-like系统提供IMAP,POP3服务的软件.主要是为了安全产生的,不管大小应用,Dovecot都是一个非常优秀的选择.它非常快,配置简单,不需要专 ...
- Unity3D - 详解Quaternion类(一)
一.简介 Quaternion又称四元数,由x,y,z和w这四个分量组成,是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的数学概念.四元数的乘法不符合交换律.从明确地角度而言,四元数是复数的不可交 ...
- 一直误解的memset函数
1.“想当然”导致的后果 今天犯了一个十分低级的错误,在对一个整型数组用memset进行初始化设置所有元素值为1.可是结果却大出所料,很意外啊!接着,我就做了代码测试. #include <io ...
- ORACLE expdp/impdp导出实例
服务器上以sys或system超级管理员登录. SQL>create directory expdp_dir as '/home/oracle/dmpdata';(dmpdata 需要建立.赋予 ...
- 第三章 Spring.Net 环境准备和搭建
在前面一章我们介绍了依赖注入,控制反转的概念.接下来我们来真正动手搭建一下Spring.Net的环境,看一下Spring.Net 中的控制反转和依赖注入是什么样子. 3.1 Spring.Net 下 ...
- Windows 端口占用
1.netstat -ano | findstr "80"( 80为提示被占用的端口): 2.tasklist | findstr "5584"(5584是从上 ...
- 用命令行执行ROBOT FRAMEWORK用例
转自:http://www.51testing.com/html/86/n-1430786.html 除了在ride中执行用例,我们也可以通过命令行的形式执行用例. 1.执行一整个项目 pybot+项 ...
- webstorm配置babel自动转译es6的方法
1.npm安装babel npm install -g babel-cli 2.npm安装Babel的preset npm install --save-dev babel-preset-es2015 ...
- 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页面 ...