一、作业需求

1、可以对指定机器异步的执行多个命令



例子:

请输入操作指令>>>:run ipconfig --host 127.0.0.0

in the call     tack_id:[24869c59-bdc3-4cfc-9a00-313e257d9f58]     cmd:[ipconfig]      host:[127.0.0.0]

>请输入操作指令>>>:check_all

查看所有任务编号:

1     24869c59-bdc3-4cfc-9a00-313e257d9f58

2     f2d05df2-05b7-4059-93cc-de7c80aee5af

请输入操作指令>>>:check_task 24869c59-bdc3-4cfc-9a00-313e257d9f58

查看任务[24869c59-bdc3-4cfc-9a00-313e257d9f58]返回结果:

Windows IP 配置





以太网适配器 本地连接:



   连接特定的 DNS 后缀 . . . . . . . :

   本地链接 IPv6 地址. . . . . . . . : fe80::cddb:da51:7e58:2515%11

   IPv4 地址 . . . . . . . . . . . . : 192.168.1.119

二、readme

一、作业需求:
1、可以对指定机器异步的执行多个命令
例子:
请输入操作指令>>>:run ipconfig --host 127.0.0.0
in the call tack_id:[24869c59-bdc3-4cfc-9a00-313e257d9f58] cmd:[ipconfig] host:[127.0.0.0]
请输入操作指令>>>:run dir --host 127.0.0.0
in the call tack_id:[f2d05df2-05b7-4059-93cc-de7c80aee5af] cmd:[dir] host:[127.0.0.0]
>请输入操作指令>>>:check_all
查看所有任务编号:
1 24869c59-bdc3-4cfc-9a00-313e257d9f58
2 f2d05df2-05b7-4059-93cc-de7c80aee5af
请输入操作指令>>>:chedk_task 24869c59-bdc3-4cfc-9a00-313e257d9f58
请输入有效操作指令
请输入操作指令>>>:check_task 24869c59-bdc3-4cfc-9a00-313e257d9f58
注意,每执行一条命令,即立刻生成一个任务ID,不需等待结果返回,通过命令check_task TASK_ID来得到任务结果
二、博客地址:http://www.cnblogs.com/catepython/p/9051490.html
三、运行环境
操作系统:Win10
Python:3.6.4rcl
Pycharm:2017.3.4
四 、具体实现
思路解析:
分析需求其实可以发现,输入命令为消费者,执行命令是生产者,参照RabbitMQ的官方文档rpc部分和课上的代码就可以了。
1. 使用RabbitMQ_RPC, Queen使用主机IP
2. 消费者输入命令,分割字段,获取run,check_task,check_task_all,host等信息,传给生产者。
3. 生产者执行命令处理windows/linux不同消息发送情况windows decode(‘gbk’) linux decode('utf-8'),返回结果。
4. 消费者将结果存成字典,查询结果后删除。
五、测试流程
1、在本次作业中处理了各种操作指令的异常处理 如:数组越界、使用check_task操作时无效任务ID处理
2、对用户输入的格式就行了正则 如:IP地址格式的判断
3、同时能对多个服务主机发送并接收相应的数据信息
六、备注
1、完成本次作业看了5遍视频,百度了所有大神们的心得代码,终于理清了整个RPC框架和原理

readme

三、流程图

四、目录结构图

五、核心代码

conf目录

#-*-coding:utf-8 -*-
# Author: D.Gray
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOCAL_HOST = ('localhost')

setting

core主逻辑目录

#-*-coding:utf-8 -*-
# Author: D.Gray
import pika,uuid,time,re
from conf import setting
class Producer(object):
def __init__(self):
self.connaction = pika.BlockingConnection(pika.ConnectionParameters(setting.LOCAL_HOST))
self.channel = self.connaction.channel()
self.result = self.channel.queue_declare(exclusive=True) #生产一个随机queue
self.callback_queue = self.result.method.queue
# 声明一个queue,一收到消息就调用on_response函数
self.channel.basic_consume(self.on_response,no_ack=True,queue=self.callback_queue)
def on_response(self,ch,method,props,body):
'''
处理收到消息函数
:param ch:
:param method:
:param props:
:param body:
:return:
'''
if self.corr_id == props.correlation_id:
self.response = body
def call(self,cmd,host):
'''
发送操作指令至服务端函数
:param cmd:
:param host:
:return:
'''
self.response = None
self.corr_id = str(uuid.uuid4())
#把操作指令发送给服务端,并把与服务端约定好一个随机queue一同传过去
self.channel.basic_publish(exchange='',routing_key=host,
properties=pika.BasicProperties(
reply_to=self.callback_queue, #与服务端约定好一个随机queue进行第二次数据交互
correlation_id = self.corr_id
),
body=str(cmd)
)
while self.response is None:
self.connaction.process_data_events() #非阻塞版的start_consume
# print('no message...')
# time.sleep(1)
task_id = self.corr_id
res = self.response.decode()
tmp_dict[task_id] = res
print('in the call\t tack_id:[%s]\t cmd:[%s]\t host:[%s]'%(task_id,cmd,host))
return task_id,res
def help():
'''
帮助函数
:return:
'''
meg = '''\033[32;1m
run "df -h" --hosts 127.0.0.1 192.168.84.66:执行操作命令格式
check_task 54385061-aa3a-400f-8a21-2be368e66493:查看某个任务id返回结果
check_all:查看所有任务编号
\033[0m'''
print(meg)
def checkip(ip):
'''
正则判断参数是否是IP地址格式
:param ip: 需判断的字符串
:return:
'''
p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
if p.match(ip):
return True
else:
return False
def start(cmd):
'''
:param cmd:
:return:
'''
#print('in the start:',cmd)
if cmd[0] == 'run':
if len(cmd) > 3:
hosts = cmd[3:]
for host in hosts:
if checkip(host) is True: #调用checkip方法来判断参数是否符合IP地址格式
try:
cmd_rpc.call(cmd[1],host) #把操作指令和ip 传给call()方法去解析
except Exception as e:
print('\033[31;1m有异常报错:\033[0m', e)
help()
else:
print('\033[31;1m请输入有效IP地址\033[0m')
help()
else:
print('\033[31;1m请正确输入有效指令')
help()
elif cmd[0] == 'help':
help()
elif cmd[0] == 'check_all':
if len(tmp_dict) == 0:
print('\033[31;1m暂无任务ID\033[0m')
else:
print('查看所有任务编号:')
for index,key in enumerate(tmp_dict.keys()):
print('%s\t %s'%(index+1,key))
elif cmd[0] == 'check_task':
try:
print('查看任务[%s]返回结果:%s'%(cmd[1],tmp_dict[cmd[1]]))
del tmp_dict[cmd[1]]
except IndexError as e:
print('\033[31;1m数组越界:\033[0m',e)
help()
except KeyError as e:
print('\033[31;1m无效任务ID:\033[0m',e)
else:
print('\033[31;1m请输入有效操作指令\033[0m')
cmd_rpc = Producer()
tmp_dict = {}
while True:
cmd_input = input('请输入操作指令>>>:').strip().split()
if len(cmd_input) == 0:continue
else:
start(cmd_input)

客户端

#-*-coding:utf-8 -*-
# Author: D.Gray
import pika
import subprocess
import platform
connaction = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connaction.channel()
channel.queue_declare(queue='127.0.0.0') #设置一个队列与客户端首次交互 os_res = platform.system()
def command(cmd):
if os_res == 'Windows':
res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
msg = res.stdout.read().decode('gbk')
if len(msg) == 0:
msg = res.stderr.read().decode('gbk')
#print(msg)
return msg
else:
res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#print(res)
msg = res.stdout.read().decode()
if len(msg) == 0:
msg = res.stderr.read().decode()
return msg
def on_response(ch,method,props,body):
'''
处理客户端传来消息的函数
:param ch:
:param method:
:param props:
:param body:
:return:
'''
cmd = body.decode()
#('收到客户端传来参数:[%s]'%cmd)
response = command(cmd) #调用command函数来解析函数 ch.basic_publish(exchange='',routing_key=props.reply_to, #把消息传到与客户端约定好的随机queue中
properties=pika.BasicProperties(correlation_id = props.correlation_id),
body = str(response))
ch.basic_ack(delivery_tag=method.delivery_tag) #手动确认消息有无被消费掉
#监听1270.0.0这个队列一收到客户端传来的消息就调用on_response处理消息
channel.basic_consume(on_response,queue='127.0.0.0')
print('等待客户端传来求值参数...')
channel.start_consuming()

服务端

RabbitMQ-RPC版主机管理程序的更多相关文章

  1. 老男孩Day12作业:RabbitMQ-RPC版主机管理程序

    一.作业需求 1.可以对指定机器异步的执行多个命令 例子: 请输入操作指令>>>:run ipconfig --host 127.0.0.0 in the call     tack ...

  2. 【python】-- RabbitMQ RPC模型

    RabbitMQ RPC模型 RPC(remote procedure call)模型说通俗一点就是客户端发一个请求给远程服务端,让它去执行,然后服务端端再把执行的结果再返回给客户端. 1.服务端 i ...

  3. python10作业思路及源码:类Fabric主机管理程序开发(仅供参考)

    类Fabric主机管理程序开发 一,作业要求 1, 运行程序列出主机组或者主机列表(已完成) 2,选择指定主机或主机组(已完成) 3,选择主机或主机组传送文件(上传/下载)(已完成) 4,充分使用多线 ...

  4. python第五十二天---第九周作业 类 Fabric 主机管理程序

    类 Fabric 主机管理程序开发:1. 运行程序列出主机组或者主机列表2. 选择指定主机或主机组3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载)4. 充分使用多线程或多进程5. 不同 ...

  5. python作业类Fabric主机管理程序开发(第九周)

    作业需求: 1. 运行程序列出主机组或者主机列表 2. 选择指定主机或主机组 3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载) 4. 充分使用多线程或多进程 5. 不同主机的用户名密码 ...

  6. python 学习分享-实战篇类 Fabric 主机管理程序开发

    # 类 Fabric 主机管理程序开发: # 1. 运行程序列出主机组或者主机列表 # 2. 选择指定主机或主机组 # 3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载) # 4. 充分 ...

  7. 类 Fabric 主机管理程序开发

    类 Fabric 主机管理程序开发:1. 运行程序列出主机组或者主机列表2. 选择指定主机或主机组3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载4. 充分使用多线程或多进程5. 不同主 ...

  8. 8.rabbitmq RPC模拟微服务架构中的服务调用

    标题 : 8.rabbitmq RPC模拟微服务架构中的服务调用 目录 : RabbitMQ 序号 : 8 { var connectionFactory = new ConnectionFactor ...

  9. python作业(第十一周)基于RabbitMQ rpc实现的主机管理

    作业需求: 可以对指定机器异步的执行多个命令 例子: >>:run "df -h" --hosts 192.168.3.55 10.4.3.4 task id: 453 ...

随机推荐

  1. Spring(IOC、AOP和事务)

    目录 Spring介绍 Spring IOC 传统代码对象管理的弊端 实现过程 bean标签属性介绍 对象创建方式 工厂bean bean的作用域 SpringBean的生命周期*** 依赖注入 注解 ...

  2. Codeforces Round #680 (Div. 2, based on Moscow Team Olympiad)【ABCD】

    比赛链接:https://codeforces.com/contest/1445 A. Array Rearrangment 题意 给定两个大小均为 \(n\) 的升序数组 \(a\) 和 \(b\) ...

  3. python 引用(import)文件夹下的py文件

    importlib.import_module动态导入模块: python中schedule模块的简单使用 || importlib.import_module动态导入模块 先看一下文件目录 1.同级 ...

  4. 如何用 4 个小时搭建一个新 “Clubhouse” ,引爆声音社交新风口

    Clubhouse,基于实时音频技术的声音社交现象级火爆 最近,让硅谷两位顶级 VC 大打出手争相投资的 Clubhouse 火到了国内,甚至在社交圈里 "一码难求",此种火爆程度 ...

  5. Bing壁纸-20200416

  6. Docker网络模式详解

    一.Docker四种工作模式 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络). none .hosthost:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用 ...

  7. postion:fixed和margin:0 auto的使用

    很多同学将顶部菜单固定,使用postion:fixed,然后使用margin:0 auto进行居中,发现margin:0 auto并不起作用. 通常,我们要让某元素居中,会这样做: #element{ ...

  8. Seven xxx in Seven Weeks ebooks | 七周七 xxx 系列图书 电子书| share 分享 | free of charge 免费!

    Seven xxx  in Seven Weeks ebooks |  七周七 xxx 系列图书  电子书| share  分享 | free of charge  免费! Seven Languag ...

  9. How to get the real screen size(screen resolution) by using js

    How to get the real screen size(screen resolution) by using js 获取用户屏幕的真实像素分辨率, 屏幕实际尺寸 window.deviceP ...

  10. MDN All In One

    MDN All In One https://github.com/mdn/ https://wiki.mozilla.org/MDN MDN 要凉了 https://developer.mozill ...