首页 文章 精选 留言 我的

精选列表

搜索[诊断自动化],共10000篇文章
优秀的个人博客,低调大师

Docker 集成 OSCAL 标准,让高度监管体系行业实现自动化

本文首发自“Docker公司”公众号(ID:docker-cn)编译丨小东每周一、三、五 与您不见不散! 金融服务业、保险业和政府企业这类拥有高度监管体系的行业都各自拥有着一系列复杂且极具挑战性的 IT 合规性要求(必须不断加以维护)。出于这个原因,引入新技术有时候会变得十分困难。Docker 企业版(EE)可以为这类组织提供了一个安全的平台,在这个平台上,容器是构建兼容应用程序以及大规模运营、管控工作流的基础。 即使出现了容器、云以及其它新工具,但问题依然存在,IT 合规领域仍然没有实质性变化,安全标准远远落后,从而导致传统控制装置与现代系统不匹配。组织仍然依赖于几十年前的那种文书繁重的审计和报告流程。因为所需资源文档和工件的开发和维护必须通过第三方的持续审核,所以构建符合 PCI、FISMA 或 HIPAA 标准系统的时间和成本不容小觑,即使对于大型企业来说也是如此。 为了满足这些需求,Docker 与美国国家标准与技术研究院(NIST)进行合作。今天,我们很高兴地宣布 Docker 将完全采用开放安全控制评估语言(OSCAL)标准并致力于其未来的发展。OSCAL是一种可以让机器识别的“标准”,它规范化了系统安全控制和相应的评估信息的表达方式。其目标是提高系统安全评估的效率、准确性和一致性,并大幅减少与评估相关的劳动力。OSCAL 使用户能够持续评估系统的安全状态,并同时对多组需求进行评估。OSCAL 规范在设计时考充分虑到了安全性和灵活性。它既基于 XML,也基于 json,而且它与技术和基础设施无关,所以在使用方面它非常的灵活。 此外,我们正在将 OSCAL 功能直接集成到 Docker 企业版(EE)的容器平台中来缓和合规性所带来的挑战。这些集成的最初重点将放在具有 PCI 和 FISMA 合规要求的组织(美国联邦政府)上,不久之后我们将为 HIPAA 和其他组织提供额外支持。 欢迎参加 6 月份举办的 DockerCon 欧洲大会(https://2018.dockercon.com), 参与关于 OSCAL 标准的讨论,或者通过邮件(sales@docker.com)与我们联系。

优秀的个人博客,低调大师

iGraph自动化流量预估及大规模数据智能调度

引言 iGraph是一个在线图存储和查询服务,从2015年年初正式上线到现在,已经平稳经历了3次双十一大促的历练。在这几年的发展过程中,我们持续改进用户接入体验、跟TPP推荐业务平台一站式集成、在线服务质量持续保持稳定,这一些长期投入让iGraph赢得了越来越多集团客户的信任,其中包括集团的核心搜索和推荐业务。随着支撑越来越多集团业务,iGraph已经发展成为集团在线服务架构中一个非常重要的基础服务设施。为了支撑iGraph业务的快速增长,今年上半年我们开发了AutoUmars基础管控组件,并基于此重构了iGraph管控系统。在刚刚过去的2017双十一大促中,iGraph系统的各项核心业务指标达到了前所未有的峰值。 下面我们分享一些今年大促中iGraph的相关业务数据: 在中美俄三地提供了万级别表数目的在线并发访问。 Proxy峰值入口访

优秀的个人博客,低调大师

基于python+appium+yaml安卓UI自动化测试分享

结构介绍 之前分享过一篇安卓UI测试,但是没有实现数据与代码分离,后期维护成本较高,所以最近抽空优化了一下。不想看文章得可以直接去Github,欢迎拍砖大致结构如下: 结构.png testyaml管理用例,实现数据与代码分离,一个模块一个文件夹 public 存放公共文件,如读取配置文件、启动appium服务、读取Yaml文件、定义日志格式等 page 存放最小测试用例集,一个模块一个文件夹 results 存放测试报告及失败截图 report.png logs 存放日志 logs.png logdetail.png testcase 存放测试用例 runtest.py 运行所有测试用例 yaml格式介绍 首先看下yaml文件的格式,之前也写过一点关于yaml语法学习的文章testcase部分是重点,其中: element_info:定位元素信息 find_type:属性,id、xpath、text、ids operate_type: click、sendkeys、back、swipe_up 为back就是返回,暂时就四种 上面三个必填,operate_type必填!!!!!! send_content:send_keys 时用到 index:ids时用到 times: 返回次数或者上滑次数 testinfo: - id: cm001 title: 新增终端门店 execute: 1 testcase: - element_info: 客户 find_type: text operate_type: click - element_info: com.fiberhome.waiqin365.client:id/cm_topbar_tv_right find_type: id operate_type: click - element_info: com.fiberhome.waiqin365.client:id/custview_id_singletv_inputtext find_type: ids operate_type: send_keys send_content: auto0205 index: 0 - element_info: find_type: operate_type: swipe_up times: 1 - element_info: 提交 find_type: text operate_type: click - element_info: find_type: operate_type: back times: 1 代码部分 公共部分 个人觉得核心的就是公共部分,相当于建房子,公共部分搞好了,后面仅仅是调用即可,建房子把架子搭好,后面就添砖加瓦吧。 读取配置文件readconfig.py设置日志格式logs.py获取设备GetDevices.py这几个通用的就不做介绍了 读取yaml文件 GetYaml.py主要用来读取yaml文件 #coding=utf-8 #author='Shichao-Dong' import sys reload(sys) sys.setdefaultencoding('utf8') import yaml import codecs class getyaml: def __init__(self,path): self.path = path def getYaml(self): ''' 读取yaml文件 :param path: 文件路径 :return: ''' try: f = open(self.path) data =yaml.load(f) f.close() return data except Exception: print(u"未找到yaml文件") def alldata(self): data =self.getYaml() return data def caselen(self): data = self.alldata() length = len(data['testcase']) return length def get_elementinfo(self,i): data = self.alldata() # print data['testcase'][i]['element_info'] return data['testcase'][i]['element_info'] def get_findtype(self,i): data = self.alldata() # print data['testcase'][i]['find_type'] return data['testcase'][i]['find_type'] def get_operate_type(self,i): data = self.alldata() # print data['testcase'][i]['operate_type'] return data['testcase'][i]['operate_type'] def get_index(self,i): data = self.alldata() if self.get_findtype(i)=='ids': return data['testcase'][i]['index'] else: pass def get_send_content(self,i): data = self.alldata() # print data['testcase'][i]['send_content'] if self.get_operate_type(i) == 'send_keys': return data['testcase'][i]['send_content'] else: pass def get_backtimes(self,i): data = self.alldata() if self.get_operate_type(i)=='back' or self.get_operate_type(i)=='swipe_up': return data['testcase'][i]['times'] else: pass def get_title(self): data = self.alldata() # print data['testinfo'][0]['title'] return data['testinfo'][0]['title'] 启动appium服务 StartAppiumServer.py主要是启动appium并返回端口port,这个port在下面的driver中需要 #coding=utf-8 #author='Shichao-Dong' from logs import log import random,time import platform import os from GetDevices import devices log = log() dev = devices().get_deviceName() class Sp: def __init__(self, device): self.device = device def __start_driver(self, aport, bpport): """ :return: """ if platform.system() == 'Windows': import subprocess subprocess.Popen("appium -p %s -bp %s -U %s" % (aport, bpport, self.device), shell=True) def start_appium(self): """ 启动appium p:appium port bp:bootstrap port :return: 返回appium端口参数 """ aport = random.randint(4700, 4900) bpport = random.randint(4700, 4900) self.__start_driver(aport, bpport) log.info( 'start appium :p %s bp %s device:%s' % (aport, bpport, self.device)) time.sleep(10) return aport def main(self): """ :return: 启动appium """ return self.start_appium() def stop_appium(self): ''' 停止appium :return: ''' if platform.system() == 'Windows': os.popen("taskkill /f /im node.exe") if __name__ == '__main__': s = Sp(dev) s.main() 获取driver GetDriver.pyplatformName、deviceName、appPackage、appActivity这些卸载配置文件config.ini文件中,可以直接通过readconfig.py文件读取获得。appium_port有StartAppiumServer.py文件返回 s = Sp(deviceName) appium_port = s.main() def mydriver(): desired_caps = { 'platformName':platformName,'deviceName':deviceName, 'platformVersion':platformVersion, 'appPackage':appPackage,'appActivity':appActivity, 'unicodeKeyboard':True,'resetKeyboard':True,'noReset':True } try: driver = webdriver.Remote('http://127.0.0.1:%s/wd/hub'%appium_port,desired_caps) time.sleep(4) log.info('获取driver成功') return driver except WebDriverException: print 'No driver' if __name__ == "__main__": mydriver() 重新封装find等命令,BaseOperate.py里面主要是一些上滑、返回、find等一些基础操作 #coding=utf-8 #author='Shichao-Dong' from selenium.webdriver.support.ui import WebDriverWait from logs import log import os import time ''' 一些基础操作:滑动、截图、点击页面元素等 ''' class BaseOperate: def __init__(self,driver): self.driver = driver def back(self): ''' 返回键 :return: ''' os.popen("adb shell input keyevent 4") def get_window_size(self): ''' 获取屏幕大小 :return: windowsize ''' global windowSize windowSize = self.driver.get_window_size() return windowSize def swipe_up(self): ''' 向上滑动 :return: ''' windowsSize = self.get_window_size() width = windowsSize.get("width") height = windowsSize.get("height") self.driver.swipe(width/2, height*3/4, width/2, height/4, 1000) def screenshot(self): now=time.strftime("%y%m%d-%H-%M-%S") PATH = lambda p: os.path.abspath( os.path.join(os.path.dirname(__file__), p) ) screenshoot_path = PATH('../results/screenshoot/') self.driver.get_screenshot_as_file(screenshoot_path+now+'.png') def find_id(self,id): ''' 寻找元素 :return: ''' exsit = self.driver.find_element_by_id(id) if exsit : return True else: return False def find_name(self,name): ''' 判断页面是否存在某个元素 :param name: text :return: ''' findname = "//*[@text='%s']"%(name) exsit = self.driver.find_element_by_xpath(findname) if exsit : return True else: return False def get_name(self,name): ''' 定位页面text元素 :param name: :return: ''' # element = driver.find_element_by_name(name) # return element findname = "//*[@text='%s']"%(name) try: element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(findname)) # element = self.driver.find_element_by_xpath(findname) self.driver.implicitly_wait(2) return element except: self.screenshot() log.error('未定位到元素:'+'%s')%(name) def get_id(self,id): ''' 定位页面resouce-id元素 :param id: :return: ''' try: element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_id(id)) # element = self.driver.find_element_by_id(id) self.driver.implicitly_wait(2) return element except: self.screenshot() log.error('未定位到元素:'+'%s')%(id) def get_xpath(self,xpath): ''' 定位页面xpath元素 :param id: :return: ''' try: element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath)) # element = self.driver.find_element_by_xpath(xpath) self.driver.implicitly_wait(2) return element except: self.screenshot() log.error('未定位到元素:'+'%s')%(xpath) def get_ids(self,id): ''' 定位页面resouce-id元素组 :param id: :return:列表 ''' try: # elements = self.driver.find_elements_by_id(id) elements = WebDriverWait(self.driver, 10).until(lambda x: x.find_elements_by_id(id)) self.driver.implicitly_wait(2) return elements except: self.screenshot() log.error('未定位到元素:'+'%s')%(id) def page(self,name): ''' 返回至指定页面 :return: ''' i=0 while i<10: i=i+1 try: findname = "//*[@text='%s']"%(name) self.driver.find_element_by_xpath(findname) self.driver.implicitly_wait(2) break except : os.popen("adb shell input keyevent 4") try: findname = "//*[@text='确定']" self.driver.find_element_by_xpath(findname).click() self.driver.implicitly_wait(2) except: os.popen("adb shell input keyevent 4") try: self.driver.find_element_by_xpath("//*[@text='工作台']") self.driver.implicitly_wait(2) break except: os.popen("adb shell input keyevent 4") Operate.py我认为最关键的一步了,后面没有page都是调用这个文件进行测试,主要是根据读取的yaml文件,然后进行if...else...判断,根据对应的operate_type分别进行对应的click、sendkeys等操作 #coding=utf-8 #author='Shichao-Dong' from GetYaml import getyaml from BaseOperate import BaseOperate class Operate: def __init__(self,path,driver): self.path = path self.driver = driver self.yaml = getyaml(self.path) self.baseoperate=BaseOperate(driver) def check_operate_type(self): ''' 读取yaml信息并执行 element_info:定位元素信息 find_type:属性,id、xpath、text、ids operate_type: click、sendkeys、back、swipe_up 为back就是返回,暂时就三种 上面三个必填,operate_type必填!!!!!! send_content:send_keys 时用到 index:ids时用到 times: :return: ''' for i in range(self.yaml.caselen()): if self.yaml.get_operate_type(i) == 'click': if self.yaml.get_findtype(i) == 'text': self.baseoperate.get_name(self.yaml.get_elementinfo(i)).click() elif self.yaml.get_findtype(i) == 'id': self.baseoperate.get_id(self.yaml.get_elementinfo(i)).click() elif self.yaml.get_findtype(i) == 'xpath': self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).click() elif self.yaml.get_findtype(i) == 'ids': self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click() elif self.yaml.get_operate_type(i) == 'send_keys': if self.yaml.get_findtype(i) == 'text': self.baseoperate.get_name(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i)) elif self.yaml.get_findtype(i) == 'id': self.baseoperate.get_id(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i)) elif self.yaml.get_findtype(i) == 'xpath': self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i)) elif self.yaml.get_findtype(i) == 'ids': self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].send_keys(self.yaml.get_send_content(i)) elif self.yaml.get_operate_type(i) == 'back': for n in range(self.yaml.get_backtimes(i)): self.baseoperate.back() elif self.yaml.get_operate_type(i) == 'swipe_up': for n in range(self.yaml.get_backtimes(i)): self.baseoperate.swipe_up() def back_home(self): ''' 返回至工作台 :return: ''' self.baseoperate.page('工作台') 公共部分的代码就介绍这么多,在编写这个框架的时候,大部分精力都花在这部分,所以个人觉得还是值得好好研究的 Page部分 page部分是最小用例集,一个模块一个文件夹,以客户为例,目前写了两个用例,一个新增,一个排序,文件如下: file.png 代码如下,非常的简洁, import sys reload(sys) sys.setdefaultencoding('utf8') import codecs,os from public.Operate import Operate from public.GetYaml import getyaml PATH = lambda p: os.path.abspath( os.path.join(os.path.dirname(__file__), p) ) yamlpath = PATH("../../testyaml/cm/cm-001addcm.yaml") class AddcmPage: def __init__(self,driver): self.path = yamlpath self.driver = driver self.operate = Operate(self.path,self.driver) def operateap(self): self.operate.check_operate_type() def home(self): self.operate.back_home() 运行用例 这部分用了unittest,运行所有测试用例和生成报告。一个模块一个用例,以客户为例:CmTest.py from page.cm.CmAddcmPage import AddcmPage from page.cm.CmSortcmPage import SortcmPage from public.GetDriver import mydriver driver = mydriver() import unittest,time class Cm(unittest.TestCase): def test_001addcm(self): ''' 新增客户 :return: ''' add = AddcmPage(driver) add.operateap() add.home() def test_002sortcm(self): ''' 客户排序 :return: ''' sort = SortcmPage(driver) sort.sortlist() sort.home() def test_999close(self): driver.quit() time.sleep(10) if __name__ == "__main__": unittest.main() 首先从page层将需要运行的用例都import进来,然后用unittest运行即可。如果想要运行所有的测试用例,需要用到runtest.py import time,os import unittest import HTMLTestRunner from testcase.CmTest import Cm def testsuit(): suite = unittest.TestSuite() suite.addTests([unittest.defaultTestLoader.loadTestsFromTestCase(Cm), ]) # runner = unittest.TextTestRunner(verbosity=2) # runner.run(suite) now=time.strftime("%y-%m-%d-%H-%M-%S") PATH = lambda p: os.path.abspath( os.path.join(os.path.dirname(__file__), p) ) dirpath = PATH("./results/waiqin365-") filename=dirpath + now +'result.html' fp=open(filename,'wb') runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title='waiqin365 6.0.6beta test result',description=u'result:') runner.run(suite) fp.close() if __name__ =="__main__": testsuit() 这边的思路差不多,也是先导入再装入suite即可 总结 就目前而言,暂时算是实现了数据与用例的分离,但是yaml的编写要求较高,不能格式上出错。同时也有一些其他可以优化的地方,如: 对弹窗的判断 断开后重连机制 失败后重跑机制等等,后续可以根据需求进行优化最后再贴一下开源地址Github,有兴趣的小伙伴可以去看一下,欢迎拍砖备注:完成过程中参考了Louis-me 和 auto 这两个开源项目,感谢!!! 作者:迈阿密小白 链接:https://www.jianshu.com/p/00aff8435a92 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

优秀的个人博客,低调大师

运维自动化之ansible playbook结合docker安装redis主从

上次给大家介绍了ansible结合docker安装smokeping(地址http://dl528888.blog.51cto.com/2382721/1538444),现在在介绍一下ansible结合docker安装redis主从(redis版本是2.6.17)。 目前ansible使用的人比较多,docker也最近比较流行,而且做测试的话,ansible+docker是个很好的组合。本文主要是介绍如何使用ansible的playbook安装redis主从,可以自动的做好主从,这样节省安装时间、减少问题产生。 docker版本 1 2 3 4 5 6 7 8 9 10 09:49:09 #dockerversion Clientversion:0.11.1 ClientAPIversion:1.11 Goversion(client):go1.2.1 Gitcommit(client):fb99f99 /0 .11.1 Serverversion:0.11.1 ServerAPIversion:1.11 Gitcommit(server):fb99f99 /0 .11.1 Goversion(server):go1.2.1 Laststableversion:1.1.2,pleaseupdatedocker ansible版本 1 2 09:51:55 #ansible--version ansible1.4.3 1、查看已有的docker镜像 1 2 3 4 5 09:39:26 #dockerimages REPOSITORYTAGIMAGEIDCREATEDVIRTUALSIZE ubuntu3.06cee552765289weeksago369.8MB centos53.0e08d23b091899weeksago840.9MB centos63.0e94a3b24a19b9weeksago415.9MB 2、查看当前运行的docker容器 1 2 3 4 5 6 09:39:47 #dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 846efb9e4d7aubuntu:3.0 /usr/sbin/sshd -D2weeksagoUp6days0.0.0.0:49167->22 /tcp ubuntu-test1 b9a9e6f2caedcentos6:3.0 /usr/sbin/sshd -D3weeksagoUp6days0.0.0.0:49166->22 /tcp zabbix-server 978fff134b18centos6:3.0 /usr/sbin/sshd -D5weeksagoUp6days0.0.0.0:49165->22 /tcp centos6-test5 root@ip-10-10-10-10: /etc/ansible/roles/redis_install/templates 3、加载测试容器 由于是做redis主从,所以需要2个容器 1 2 3 4 5 6 7 8 9 10 11 12 13 09:39:50 #timedockerinspect$(dockerrun-d-p22--name="redis-master"centos6:3.0/usr/sbin/sshd-D)|grep-iaddress|awk-F'"''{print$4}' 172.17.0.5 real 0m6.369s user 0m0.036s sys 0m0.049s root@ip-10-10-10-10: /etc/ansible/roles/redis_install/templates 09:40:25 #timedockerinspect$(dockerrun-d-p22--name="redis-slave"centos6:3.0/usr/sbin/sshd-D)|grep-iaddress|awk-F'"''{print$4}' 172.17.0.6 real 0m12.567s user 0m0.047s sys 0m0.060s 然后把新容器的ip加入到ansible的hosts里 1 2 3 4 5 root@ip-10-10-10-10: /etc/ansible/roles/redis_install/templates 09:40:46 #echo"172.17.0.5">>/etc/ansible/hosts root@ip-10-10-10-10: /etc/ansible/roles/redis_install/templates 09:40:58 #echo"172.17.0.6">>/etc/ansible/hosts root@ip-10-10-10-10: /etc/ansible/roles/redis_install/templates 4、ansible安装redis的信息 1 2 3 4 5 6 7 09:52:11 #cat/etc/ansible/roles/redis_install/vars/main.yml redis_dir: /data redis_version:2.6.17 redis_port:6379 redis_conf_dir: /data/redis-2 .6.17 /conf redis_db_dir: /data/redis-2 .6.17 /db redis_log_dir: /data/redis-2 .6.17 /log 5、下面是redis的playbook结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 09:55:12 #tree/etc/ansible/roles/redis_install/etc/ansible/roles/redis_delete /etc/ansible/roles/redis_install ├──files │└──redis-2.6.17. tar .gz ├──handlers ├──meta │└──main.yml ├──tasks │├──copy.yml │├──delete.yml │├── install .yml │└──main.yml ├──templates │└──redis.conf └──vars └──main.yml /etc/ansible/roles/redis_delete ├──files ├──handlers ├──meta │└──main.yml ├──tasks │├──delete.yml │└──main.yml ├──templates │└──delete_redis.sh └──vars └──main.yml 12directories,13files 6、playbook安装redis的内容是 1 2 3 4 5 6 7 8 09:57:09 #catredis_install.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -common -redis_install 7、playbook删除redis的内容是 1 2 3 4 5 6 7 09:57:31 #catredis_delete.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -redis_delete 下面是安装redis主从 8、安装redis master 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 09:43:11 #timeansible-playbookredis_install.yml--extra-vars"host=172.17.0.5user=root"-k SSHpassword: PLAY[172.17.0.5]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.5] TASK:[common|Installinitializtionrequiresoftware]*********************** changed:[172.17.0.5] TASK:[redis_install|CopyRedisSoftwareToRedhatClient]****************** ok:[172.17.0.5] TASK:[redis_install|CreateRedisInstallDir]****************************** ok:[172.17.0.5] TASK:[redis_install|UncompressionRedisSoftwareToRedhatClient]********* changed:[172.17.0.5] TASK:[redis_install|CopyRedisConfigToRedhatClient]******************** changed:[172.17.0.5] TASK:[redis_install|CreateSoftLinkInRedhatClient]********************* changed:[172.17.0.5]=>(item=redis-cli) changed:[172.17.0.5]=>(item=redis-server) TASK:[redis_install|CheckBootStartInRedhatClient]********************* failed:[172.17.0.5]=>{ "changed" : true , "cmd" : "grep-c'/usr/bin/redis-server/data/redis-2.6.17/conf/redis_6379.conf'/etc/rc.local" , "delta" : "0:00:00.007160" , "end" : "2014-08-1309:45:18.660617" , "item" : "" , "rc" :1, "start" : "2014-08-1309:45:18.653457" } stdout:0 ...ignoring TASK:[redis_install|AddBootStartInRedhatClient]*********************** changed:[172.17.0.5] TASK:[redis_install|StartRedisServiceInRedhatClient]****************** changed:[172.17.0.5] TASK:[redis_install|DeleteRediscompressionSoftwareInRedhatClient]**** changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=11changed=8unreachable=0failed=0 real 0m12.757s user 0m3.453s sys 0m0.497s 9、查看redis master安装情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 09:48:39 #ssh172.17.0.5 root@172.17.0.5'spassword: Lastlogin:WedAug1309:45:282014from172.17.42.1 root@06762530db8c:~ 09:48:43 #ps-ef|grepredis root2941009:45?00:00:00 /usr/bin/redis-server /data/redis-2 .6.17 /conf/redis_6379 .conf root343329009:48pts /0 00:00:00 grep redis root@06762530db8c:~ 09:48:46 #cat/etc/rc.local #!/bin/sh # #Thisscriptwillbeexecuted*after*alltheotherinitscripts. #Youcanputyourowninitializationstuffinhereifyoudon't #wanttodothefullSysVstyleinitstuff. touch /var/lock/subsys/local /usr/bin/redis-server /data/redis-2 .6.17 /conf/redis_6379 .conf root@06762530db8c:~ 09:48:52 #redis-cli-h172.17.0.5-p6379 redis172.17.0.5:6379>keys* (emptylistor set ) redis172.17.0.5:6379> 10、安装redis slave 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 09:45:20 #timeansible-playbookredis_install.yml--extra-vars"host=172.17.0.6user=rootredis_master_ip=172.17.0.5redis_master_port=6379"-k SSHpassword: PLAY[172.17.0.6]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.6] TASK:[common|Installinitializtionrequiresoftware]*********************** changed:[172.17.0.6] TASK:[redis_install|CopyRedisSoftwareToRedhatClient]****************** changed:[172.17.0.6] TASK:[redis_install|CreateRedisInstallDir]****************************** ok:[172.17.0.6] TASK:[redis_install|UncompressionRedisSoftwareToRedhatClient]********* changed:[172.17.0.6] TASK:[redis_install|CopyRedisConfigToRedhatClient]******************** changed:[172.17.0.6] TASK:[redis_install|CreateSoftLinkInRedhatClient]********************* changed:[172.17.0.6]=>(item=redis-cli) changed:[172.17.0.6]=>(item=redis-server) TASK:[redis_install|CheckBootStartInRedhatClient]********************* failed:[172.17.0.6]=>{ "changed" : true , "cmd" : "grep-c'/usr/bin/redis-server/data/redis-2.6.17/conf/redis_6379.conf'/etc/rc.local" , "delta" : "0:00:00.006751" , "end" : "2014-08-1309:49:07.569522" , "item" : "" , "rc" :1, "start" : "2014-08-1309:49:07.562771" } stdout:0 ...ignoring TASK:[redis_install|AddBootStartInRedhatClient]*********************** changed:[172.17.0.6] TASK:[redis_install|StartRedisServiceInRedhatClient]****************** changed:[172.17.0.6] TASK:[redis_install|DeleteRediscompressionSoftwareInRedhatClient]**** changed:[172.17.0.6] PLAYRECAP******************************************************************** 172.17.0.6:ok=11changed=9unreachable=0failed=0 real 1m48.579s user 0m6.781s sys 0m0.654s 11、查看redis slave安装情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 09:59:24 #ssh172.17.0.6 root@172.17.0.6'spassword: root@dfec766fbaa7:~ 09:59:28 #ll total0 root@dfec766fbaa7:~ 09:59:31 #ps-ef|grepredis root1971009:49?00:00:00 /usr/bin/redis-server /data/redis-2 .6.17 /conf/redis_6379 .conf root227212009:59pts /0 00:00:00 grep redis 09:59:49 #grepslave/data/redis-2.6.17/conf/redis_6379.conf|egrep-v"^#" slaveof172.17.0.56379 slave-serve-stale-data yes slave- read -only yes slave-priority100 client-output-buffer-limitslave256mb64mb60 root@dfec766fbaa7:~ 10:00:09 #redis-cli-h172.17.0.6-p6379 redis172.17.0.6:6379>keys* (emptylistor set ) redis172.17.0.6:6379>info #Server redis_version:2.6.17 redis_git_sha1:00000000 redis_git_dirty:0 redis_mode:standalone os:Linux2.6.32-431.17.1.el6.x86_64x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.4.7 process_id:197 run_id:81207df2727abe534ae606afc0cb80016f75a422 tcp_port:6379 uptime_in_seconds:685 uptime_in_days:0 hz:10 lru_clock:280339 #Clients connected_clients:2 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 #Memory used_memory:878072 used_memory_human:857.49K used_memory_rss:7569408 used_memory_peak:877280 used_memory_peak_human:856.72K used_memory_lua:31744 mem_fragmentation_ratio:8.62 mem_allocator:jemalloc-3.2.0 #Persistence loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1407894548 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok #Stats total_connections_received:1 total_commands_processed:70 instantaneous_ops_per_sec:0 rejected_connections:0 expired_keys:0 evicted_keys:0 keyspace_hits:0 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:0 #Replication role:slave master_host:172.17.0.5 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_priority:100 slave_read_only:1 connected_slaves:0 #CPU used_cpu_sys:0.24 used_cpu_user:0.10 used_cpu_sys_children:0.00 used_cpu_user_children:0.00 #Keyspace 可以从上面的Replication里看到主从做好了,信息如下图 然后去redis master里查看主从信息 12、redis 主从测试 A.redis master插入key 1 2 3 4 5 6 7 8 redis172.17.0.5:6379> set master1 OK redis172.17.0.5:6379> set slave0 OK redis172.17.0.5:6379>getmaster "1" redis172.17.0.5:6379>getslave "0" B.redis slave读取key 1 2 3 4 5 6 7 redis172.17.0.6:6379>keys* 1) "master" 2) "slave" redis172.17.0.6:6379>getmaster "1" redis172.17.0.6:6379>getslave "0" 可以看到主从建立完成 下面是redis slave的日志情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 10:08:04 #cat/data/redis-2.6.17/log/redis_6379.log _._ _.-``__ '' -._ _.-```.`_. '' -._Redis2.6.17(00000000 /0 )64bit .-``.-```.```\/_.,_ '' -._ (',.-`|`,)Running in standalonemode |`-._`-...-`__...-.``-._| '`_.-' |Port:6379 |`-._`._/_.-'|PID:197 `-._`-._`-./_.- '_.-' |`-._`-._`-.__.- '_.-' _.-'| |`-._`-.__.- '_.-' |http: //redis .io `-._`-._`-.__.- '_.-' _.-' |`-._`-._`-.__.- '_.-' _.-'| |`-._`-.__.- '_.-' | `-._`-._`-.__.- '_.-' _.-' `-._`-.__.- '_.-' `-.__.-' `-.__.-' [197]13Aug09:49:08.878 #Serverstarted,Redisversion2.6.17 [197]13Aug09:49:08.879 #WARNINGovercommit_memoryissetto0!Backgroundsavemayfailunderlowmemorycondition.Tofixthisissueadd'vm.overcommit_memory=1'to/etc/sysctl.confandthenrebootorrunthecommand'sysctlvm.overcommit_memory=1'forthistotakeeffect. [197]13Aug09:49:08.879*Theserverisnowreadytoacceptconnectionsonport6379 [197]13Aug09:49:09.879*ConnectingtoMASTER172.17.0.5:6379 [197]13Aug09:49:09.879*MASTER<->SLAVE sync started [197]13Aug09:49:09.881*Nonblockingconnect for SYNCfiredtheevent. [197]13Aug09:49:09.881*MasterrepliedtoPING,replicationcan continue ... [197]13Aug09:49:10.035*MASTER<->SLAVE sync :receiving18bytesfrommaster [197]13Aug09:49:10.035*MASTER<->SLAVE sync :LoadingDB in memory [197]13Aug09:49:10.035*MASTER<->SLAVE sync :Finishedwithsuccess [197]13Aug10:04:56.980*1changes in 900seconds.Saving... [197]13Aug10:04:56.982*Backgroundsavingstartedbypid233 [233]13Aug10:04:57.226*DBsavedondisk [233]13Aug10:04:57.227*RDB:6MBofmemoryusedbycopy-on-write [197]13Aug10:04:57.293*Backgroundsavingterminatedwithsuccess 13、删除redis安装 无论redis主从,删除都是一样的命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 09:57:32 #timeansible-playbookredis_delete.yml--extra-vars"host=172.17.0.5user=root"-k SSHpassword: PLAY[172.17.0.5]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.5] TASK:[redis_delete|StopRedisServiceInRedhatClient]******************** changed:[172.17.0.5] TASK:[redis_delete|DeleteRedisSoftLineInRedhatClient]**************** changed:[172.17.0.5]=>(item=redis-cli) changed:[172.17.0.5]=>(item=redis-server) TASK:[redis_delete|DeleteRedisDirInRedhatClient]********************** changed:[172.17.0.5] TASK:[redis_delete|DeleteBootStartInRedhatClient]********************* changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=5changed=4unreachable=0failed=0 real 0m6.929s user 0m1.942s sys 0m0.250s root@ip-10-10-10-10: /etc/ansible 10:09:18 #timeansible-playbookredis_delete.yml--extra-vars"host=172.17.0.6user=root"-k SSHpassword: PLAY[172.17.0.6]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.6] TASK:[redis_delete|StopRedisServiceInRedhatClient]******************** changed:[172.17.0.6] TASK:[redis_delete|DeleteRedisSoftLineInRedhatClient]**************** changed:[172.17.0.6]=>(item=redis-cli) changed:[172.17.0.6]=>(item=redis-server) TASK:[redis_delete|DeleteRedisDirInRedhatClient]********************** changed:[172.17.0.6] TASK:[redis_delete|DeleteBootStartInRedhatClient]********************* changed:[172.17.0.6] PLAYRECAP******************************************************************** 172.17.0.6:ok=5changed=4unreachable=0failed=0 real 0m5.897s user 0m1.726s sys 0m0.258s 15、删除后测试 A.redis master上 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 10:09:55 #ifconfig eth0Linkencap:EthernetHWaddrC6:3A:D2:D9:DD:D9 inetaddr:172.17.0.5Bcast:0.0.0.0Mask:255.255.0.0 inet6addr:fe80::c43a:d2ff:fed9:ddd9 /64 Scope:Link UPBROADCASTRUNNINGMTU:1500Metric:1 RXpackets:13236errors:0dropped:0overruns:0frame:0 TXpackets:12843errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:1000 RXbytes:26106313(24.8MiB)TXbytes:906412(885.1KiB) loLinkencap:LocalLoopback inetaddr:127.0.0.1Mask:255.0.0.0 inet6addr:::1 /128 Scope:Host UPLOOPBACKRUNNINGMTU:16436Metric:1 RXpackets:196errors:0dropped:0overruns:0frame:0 TXpackets:196errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:0 RXbytes:9665(9.4KiB)TXbytes:9665(9.4KiB) root@06762530db8c:~ 10:09:56 #ps-ef|grepredis root431329010:09pts /0 00:00:00 grep redis root@06762530db8c:~ 10:09:59 #cat/etc/rc.local #!/bin/sh # #Thisscriptwillbeexecuted*after*alltheotherinitscripts. #Youcanputyourowninitializationstuffinhereifyoudon't #wanttodothefullSysVstyleinitstuff. touch /var/lock/subsys/local root@06762530db8c:~ 10:10:01 #ll/data/ total4 drwxr-xr-x2rootroot4096Jun510:21soft root@06762530db8c:~ B. redis slave上 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 10:08:09 #ifconfig eth0Linkencap:EthernetHWaddrBE:97:0C:B2:02:D9 inetaddr:172.17.0.6Bcast:0.0.0.0Mask:255.255.0.0 inet6addr:fe80::bc97:cff:feb2:2d9 /64 Scope:Link UPBROADCASTRUNNINGMTU:1500Metric:1 RXpackets:13062errors:0dropped:0overruns:0frame:0 TXpackets:12704errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:1000 RXbytes:25967216(24.7MiB)TXbytes:842881(823.1KiB) loLinkencap:LocalLoopback inetaddr:127.0.0.1Mask:255.0.0.0 inet6addr:::1 /128 Scope:Host UPLOOPBACKRUNNINGMTU:16436Metric:1 RXpackets:86errors:0dropped:0overruns:0frame:0 TXpackets:86errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:0 RXbytes:5288(5.1KiB)TXbytes:5288(5.1KiB) root@dfec766fbaa7:~ 10:10:32 #ps-ef|grepredis root319212010:10pts /0 00:00:00 grep redis root@dfec766fbaa7:~ 10:10:37 #cat/etc/rc.local #!/bin/sh # #Thisscriptwillbeexecuted*after*alltheotherinitscripts. #Youcanputyourowninitializationstuffinhereifyoudon't #wanttodothefullSysVstyleinitstuff. touch /var/lock/subsys/local root@dfec766fbaa7:~ 10:10:39 #ll/data/ total4 drwxr-xr-x2rootroot4096Jun510:21soft root@dfec766fbaa7:~ 如果大家想使用我的例子,可以从github里下载(地址是https://github.com/dl528888/ansible-examples/tree/master/redis_install),然后放到/etc/ansible目录里,下面是内容 本文转自 reinxu 51CTO博客,原文链接:http://blog.51cto.com/dl528888/1539251,如需转载请自行联系原作者

优秀的个人博客,低调大师

关于项目自动化测试架构的改良计划 - DataProviderEngine架构

为了基于上文我们的xml文件的架构,对其进行解析,我自己写了一个DataProviderEngine作为解析xml文件的引擎,它主要的架构如下图: 具体细节如下,为了节省时间,我直接复制我的英文邮件内容了: Step 1: The XMLReader read the raw test suite xml file (now we adopt the xml file ,since it is not binary file and easy to edit and version control) Step 2: After reading ,XMLReader store the xml string into a string variable named “ originalXmlString “, this is our starting point. Step 3: The XIncludeConverter read the originalXmlString ,and resolve the XInclude namespace ,when it resolve this file ,it will replace all the <xi:include href> element with the actual xml fragments one by one. Step 4: After replacing all <xi:include> ,XIncludeConverter will store the new xml string into string variable named “convertedXmlString”. Step 5: The XMLManipulator read the convertedXmlString ,and remove all the user configuration part from such as <add_elements>,<update_elements>,<remove_elements> ,since these information is used for letting test case end user configure how to operate the base data to meet special requirements,so these part shouldn’t exist in final data. Step 6:After removing all config elements ,The XMLManipulator store the xml string into a new string variable named “ removeAllConfXmlString” Step 7:Since the configuration information are removed in Step 5-6 ,but they still exist in original xml string ,so XMLModifyInfoExtractor read all the <add_elements>,<update_elements>,<remove_elements> part from original xml string ,and smartly match which corresponding testcase data it will operate . Step 8:After analyzing all the user modification requirement ,the XMLModifyInfoExtractor store these modification info into 3 arraylists , addElementInfoList,updateElementInfoList,removeElementInfoList. Step 9:Now it is time to begin modifying the xml ,so the XMLManipulator read the “removeAllConfXmlString” in Step 6 . Step 10:Then XMLManipulator use all the modification info in Step 8 ,and do modification operation one by one : addElementToXML() ,updateElementFromXML(),removeElementFromXML() Step 11: after finish all the modification ,XMLManipulator store the final xml string into string variable named “modifiedXmlString” Step 12: Finally it convert the xml formatted string to a jsonobject and it now can be used as a data provider which can be consumed in each test case. 本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1221708,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册