首页 文章 精选 留言 我的

精选列表

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

python linux 系统管理与自动化运维

pypdf2 图片:pillow 邮件:smtplib yagmail:简单发送邮件 image.png image.png 接收邮件:imapclient image.png settools打包 python-nmap image.png image.png ipy。。。。。。 dnspython... 同时处理多台服务器:polysh wget http://guichaz.free.fr/polysh/files/polysh-0.4.tar.gz tar -zxvf polysh-0.4.tar.gz cd polysh-0.4 python setup.py install 获取用户输入:pexcept paramiko:https://blog.csdn.net/l1028386804/article/details/79029041 脚本操作ssh fabric from fabric.api import * #导入fabric.api模块 env.hosts= ['192.168.122.101','192.168.122.102','192.168.122.103'] #指定远端服务器的ip地址。如果有dns解析的也可以写主机名。 env.password='indionce' #指定远端主机的密码,如果各个密码不相同可以使用一个字典指定,例如:env.password={“root@192.168.122.101”:"indionce"} @runs_once def local_uname(): #定义一个本地任务的函数 local('uname -r') def remote_uname(): #定义一个远程任务的函数 run('uname -r') def uname(): #定义一个函数,将本地与远端组合起来使用 local_uname() remote_uname() 查看列表 from fabric.api import * @runs_once #一定要指定这一条,否则会让你输入多次路径 def input(): return prompt("input path:") #prompt函数,让用户输入自己想要的路径,将输入的值返回到函数。 def ls_path(dirname): #在定义函数的时候指定形参。 run("ls -l "+dirname) def go(): ls_path(input()) #使用input返回的值,用于ls_path()的参数 处理异常 from fabric.api import * from fabric.contrib.console import * #这个模块中包含confirm def backup(): with settings(warn_only=True): #with命令表示执行这句后,执行下面的命令。使用settings命令来设置警告模式 state=local('mkdir /root/zz') #创建一个文件夹 if state.failed and not confirm("/root/zz is already exist,continue?"): #使用failed来判断state这条命令是否失败,失败了为真。confirm向用户确认是否继续,继续为真。如果命令失败了,并且用户希望停止,便通过if判断。 abort("退出任务") #abort是退出任务,有些类似python的exit。退出并且时返回给用户一串字符串 local('tar cavf /root/zz/etc.tar.gz /etc') #将etc的文件备份到/root/zz文件夹中 并行执行与顺序执行 @parallel #将下面的函数设为并行执行。 def runs_parallel(): run('uname -r') @serial #将下面的函数设为顺序执行(默认即为顺序执行 ) def runs_serially(): pass @parallel(pool_size=5) #将下面的函数设为并行执行,并且限制最多5个线程。 def runs_parallel(): pass

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

Docker 实战案例解析,实现自动化数据库迁移

出品丨Docker公司(ID:docker-cn)编译丨小东每周一、三、五晚6点10分 与您不见不散! 在 Phorest Salon Software 公司,我们是在 AWS 上运行我们的平台。该平台由 VPC 内的许多 AWS 资源(实例,数据库)组成。我们的大部分服务都运行在由亚马逊 ECS 管理的 Docker 容器上。 迁移的挑战 我们有三个专用环境:开发、分段构建和生产。每个环境都有自己的专用 VPC,因此 VPC 中的资源不能直接从外部访问,通常来说这是很好的。 问题是我们有时需要修改某些组件的模式结构,例如:添加一个新的表或列。在 Java-ish 中,我们使用 Liquibase 来管理 DDL / DML 的更改。同样的,通常来说这是很好的。但是我们要如何才能使这些更改通过持续交付的方式应用到各个不同的环境中呢? 我们针对上述问题,提出了几种解决方法: 1、在启动时执行 您可以让您的组件执行此操作。例如,您可以将应用程序配置为在启动时应用它。对于 Spring Boot 应用程序来说,这非常简单。您只需将 liquibase jar 添加到环境变量并配置一些配置属性即可实现此目的。 这种方法对于在本地的开发或开发环境来说可能是很好的,但是对于分段构建或生产呢?问题在于,您的数据库迁移脚本可能很慢,执行它们可能需要几分钟、几个小时甚至几天的时间。 对于上述情况,使用 ECS 的效果就不太理想了,因为在那里部署服务时,您定义了 ECS 将用于验证组件的运行状态,在执行数据库迁移脚本的情况下启动它,会导致整个迁移过程被认为是不健康的。而且 ECS 可能会在迁移过程中杀死您的容器。您可以为 ECS 服务配置一个宽限期,但这可能很难预测到它的值,因为每个迁移都可能不同。 2、手动应用 另一种选择是 SSH 连接到与服务在同一个 VPC 中运行的EC2实例,并从那里手动运行迁移脚本(你可能知道这种做法有多糟糕)。 3、使用 docker 容器 另一个选择是创建一个专用的 docker 镜像来运行迁移脚本。我们选择了这个选项: 定义 docker 镜像: 我们使用了一个开源的基础镜像,它为我们提供了一种执行 Liquibase 更改日志的方法。我们所要做的就是定义一些环境变量并将 Liquibase 更改日志复制过去。空变量是故意放进去的,以便大家在运行容器时记得替换掉它们。 我们将镜像定义文件与我们的代码库一起存储,因此在发布时会对其进行版本控制和标记。有了这一点,我们更新了 Jenkins 的工作,作为工作流程的一部分来构建和推动新的 docker 镜像。 下一步是更新 Jenkins 的工作来触发使用我们的新镜像迁移数据库的 ECS 任务。为此,我们使用了自己的框架,但您可以使用 Terraform 或K8s,或者您甚至可以使用以下命令手动运行它(请不要在生产中执行!) docker run your-image-tag liquibase update 使用新步骤构建管道 这种方法的好处 由于我们不在容器启动时运行迁移,所以我们不再有与长时间运行的迁移相关的问题,从而导致 ECS 运行状况检查失败。但好处是,我们的迁移现在已经与我们的部署分离了(这是一篇很好的文章,解释了从应用程序部署中分离数据库迁移的好处)。 使用这种新方法,我们必须确保我们的迁移始终与当前在生产中运行的代码兼容。它需要一些额外的工作,但现在意味着我们可以毫不费力地回滚我们的版本。 解决这个问题可能还有许多其他(也许更好)的方法,但是这种方法对我们更有效。如果你对这个话题有任何想法或想法可以在文尾处留言与我们探讨。

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

CrazyWing:Python自动化运维开发实战 十七、Python异常

导语: 在写代码的时候,经常会遇到异常。python提供了两个功能来处理程序在运行中出现的异常和错误,可以使用该功能来调试python程序。 异常处理 断言(Assertions) 常用异常: Exception 它可以捕获任意(绝大部分)异常。 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类),代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的 python标准异常: 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。 一般情况下,在Python无法正常处理程序时就会发生一个异常,异常是Python对象,表示一个错误。 当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。 #!/usr/bin/env python try: print "%d" % (5 / 0) except ZeroDivisionError: print "除数不能为零" else: print "没有报错" print "这是异常之后的代码" #如果没有上面的异常处理,下面的代码是不会执行的 for i in range(10): print i 捕捉异常: try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。 如果你不想在异常发生时结束你的程序,只需在try里捕获它。 语法: try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了'name'异常 except <名字>,<数据>: <语句> #如果引发了'name'异常,获得附加的数据 else: <语句> #如果没有异常发生 try的工作原理 当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。 1. 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的 except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异 常)。 2. 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的 try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。 3. 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的 话),然后控制流通过整个try语句。 例 打开一个文件,在该文件中的写入内容,且并未发生异常: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close() 结果: # python test.py 内容写入文件成功 # cat testfile # 查看写入的内容 这是一个测试文件,用于测试异常!! 例 打开一个文件,在该文件中的内容写入内容,但文件没有写入权限,发生了异常: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close() 在执行代码前为了测试方便,先去掉 testfile 文件的写权限 再执行以上代码: $ python test.py #注意这里用的是普通用户 Error: 没有找到文件或读取文件失败 使用except不带任何异常类型 你可以不带任何异常类型使用except,如下实例: try: 正常的操作 ...................... except: 发生异常,执行这块代码 ...................... else: 如果没有异常执行这块代码 以上方式try-except语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。 使用except带多种异常类型 也可以使用相同的except语句来处理多个异常信息: try: 正常的操作 ................ except(Exception1[, Exception2[,...ExceptionN]]]): 发生以上多个异常中的一个,执行这块代码 ...................... else: 如果没有异常执行这块代码 try-finally 语句 try-finally 语句无论是否发生异常都将执行最后的代码。 try: <语句> finally: <语句> #退出try时总会执行 例1: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") finally: print "Error: 没有找到文件或读取文件失败" 例2: import time try: f=file("文件.py") while True: line = f.read() if len(line)==0: break time.sleep(2) print line, finally: f.close() print "hello" 例3: try: fh = open("testfile", "w") try: fh.write("这是一个测试文件,用于测试异常!!") finally: print "关闭文件" fh.close() except IOError: print "Error: 没有找到文件或读取文件失败" 异常的参数: 一个异常可以带上参数,可作为输出的异常信息参数。你可以通过except语句来捕获异常的参数,如下所示: try: 正常的操作 ...................... except ExceptionType, Argument: 你可以在这输出 Argument 的值... 变量接收的异常值通常包含在异常的语句中。在元组的表单中变量可以接收一个或者多个值。元组通常包含错误字符串,错误数字,错误位置。 例以下为单个异常的实例: #!/usr/bin/python def temp_convert(var): try: return int(var) except ValueError, Argument: print "参数没 有包含数字\n", Argument # 调用函数 temp_convert("xyz") 以上程序执行结果如下: $ python test.py 参数没有包含数字 invalid literal for int() with base 10: 'xyz' 触发异常 可以使用raise语句自己触发异常raise语法格式: raise [Exception [, args [, traceback]]] 语句中Exception是异常的类型(例如,NameError)参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是"None"。最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。 例一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。定义一个异常: def functionName( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行 注意:为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。例如我们捕获以上异常,"except"语句如下: try: 正常逻辑 except "Invalid level!": 触发自定义异常 else: 其余代码 例 #!/usr/bin/python def mye( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行 try: mye(0) # 触发异常 except "Invalid level!": print 1 else: print 2 输出结果: $ python test.py Traceback (most recent call last): File "test.py", line 11, in <module> mye(0) File "test.py", line 7, in mye raise Exception("Invalid level!", level) Exception: ('Invalid level!', 0) 用户自定义异常: 通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例。 class Networkerror(RuntimeError): def __init__(self, arg): self.args = arg 在你定义以上类后,你可以触发该异常,如下所示: try: raise Networkerror("Bad hostname") except Networkerror,e: print e.args 万能异常 在python的异常中,有一个万能异常:Exception,它可以捕获任意异常。例: #cat aa.py s1 = 'hello' try: int(s1) except Exception,e: print e 执行结果: #python aa.py invalid literal for int() with base 10: 'hello' 既然有这个万能异常,其他异常是不是就可以忽略了?当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。例: s1 = 'hello' try: int(s1) except KeyError,e: print '键错误' except IndexError,e: print '索引错误' except Exception, e: print '错误' ====================================== assert断言 使用assert断言是学习python一个非常好的习惯,assert断言句语格式及用法很简单。在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助。 assert断言的作用 assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。assert断言语句的语法格式assert expression 一些assert用法的语句供参考: assert 1==1 assert 2+2==2*2 assert len(['my boy',12])<10 assert range(4)==[0,1,2,3] 如何为assert断言语句添加异常参数 assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下: assert expression [, arguments] 何时使用断言 Python的assert是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。例如: py> x = 23 py> assert x > 0, "x is not zero or negative" py> assert x%2 == 0, "x is not an even number" Traceback (most recent call last): File "", line 1, in .... AssertionError: x is not an even number 很多人用assert作为一个很快和容易的方法来在参数错误的时候抛出异常。但这样做是错的,非常错误,有两个原因。首先AssertError不是在测试参数时应该抛出的错误。你不应该像这样写代码: if not isinstance(x, int): raise AssertionError("not an int") 你应该抛出TypeError的错误,assert会抛出错误的异常。 但是,更危险的是,有一个关于assert的困扰:它可以被编译好然后从来不执行,如果你用 –O 或 –oo 选项运行Python,结果不保证assert表达式会运行到。当适当的使用assert时,这是未来,但是当assert不恰当的使用时,它会让代码用-O执行时出错。 那什么时候应该使用assert?没有特定的规则,断言应该用于: 防御型的编程 运行时检查程序逻辑 检查约定 程序常量 检查文档 (在测试代码的时候使用断言也是可接受的,是一种很方便的单元测试方法,你接受这些测试在用-O标志运行时不会做任何事。我有时在代码里使用assert False来标记没有写完的代码分支,我希望这些代码运行失败。尽管抛出NotImplementedError可能会更好。) 关于断言的意见有很多,因为它能确保代码的正确性。如果你确定代码是正确的,那么就没有用断言的必要了,因为他们从来不会运行失败,你可以直接移除这些断言。如果你确定检查会失败,那么如果你不用断言,代码就会通过编译并忽略你的检查。 在以上两种情况下会很有意思,当你比较肯定代码但是不是绝对肯定时。可能你会错过一些非常古怪的情况。在这个情况下,额外的运行时检查能帮你确保任何错误都会尽早地被捕捉到。 另一个好的使用断言的方式是检查程序的不变量。一个不变量是一些你需要依赖它为真的情况,除非一个bug导致它为假。如果有bug,最好能够尽早发现,所以我们为它进行一个测试,但是又不想减慢代码运行速度。所以就用断言,因为它能在开发时打开,在产品阶段关闭。 一个非变量的例子可能是,如果你的函数希望在它开始时有数据库的连接,并且承诺在它返回的时候仍然保持连接,这就是函数的不变量: def some_function(arg): assert not DB.closed() ... # code goes here assert not DB.closed() return result 断言本身就是很好的注释,胜过你直接写注释: # when we reach here, we know that n > 2 你可以通过添加断言来确保它: assert n > 2 断言也是一种防御型编程。你不是让你的代码防御现在的错误,而是防止在代码修改后引发的错误。理想情况下,单元测试可以完成这样的工作,可是需要面对的现实是,它们通常是没有完成的。人们可能在提交代码前会忘了运行测试代码。有一个内部检查是另一个阻挡错误的防线,尤其是那些不明显的错误,却导致了代码出问题并且返回错误的结果。 加入你有一些if…elif 的语句块,你知道在这之前一些需要有一些值: # target is expected to be one of x, y, or z, and nothing else. if target == x: run_x_code() elif target == y: run_y_code() else: run_z_code() 假设代码现在是完全正确的。但它会一直是正确的吗?依赖的修改,代码的修改。如果依赖修改成 target = w 会发生什么,会关系到run_w_code函数吗?如果我们改变了代码,但没有修改这里的代码,可能会导致错误的调用 run_z_code 函数并引发错误。用防御型的方法来写代码会很好,它能让代码运行正确,或者立马执行错误,即使你在未来对它进行了修改。 在代码开头的注释很好的一步,但是人们经常懒得读或者更新注释。一旦发生这种情况,注释会变得没用。但有了断言,我可以同时对代码块的假设书写文档,并且在它们违反的时候触发一个干净的错误 assert target in (x, y, z) if target == x: run_x_code() elif target == y: run_y_code() else: assert target == z run_z_code() 这样,断言是一种防御型编程,同时也是一种文档。我想到一个更好的方案: if target == x: run_x_code() elif target == y: run_y_code() elif target == z: run_z_code() else: # This can never happen. But just in case it does... raise RuntimeError("an unexpected error occurred") 按约定进行设计是断言的另一个好的用途。我们想象函数与调用者之间有个约定,比如下面的: “如果你传给我一个非空字符串,我保证传会字符串的第一个字母并将其大写。” 如果约定被函数或调用这破坏,代码就会出问题。我们说函数有一些前置条件和后置条件,所以函数就会这么写: def first_upper(astring): assert isinstance(astring, str) and len(astring) > 0 result = astring[0].upper() assert isinstance(result, str) and len(result) == 1 assert result == result.upper() return result 按约定设计的目标是为了正确的编程,前置条件和后置条件是需要保持的。这是断言的典型应用场景,因为一旦我们发布了没有问题的代码到产品中,程序会是正确的,并且我们能安全的移除检查。 建议不要用断言的场景: 不要用它测试用户提供的数据 不要用断言来检查你觉得在你的程序的常规使用时会出错的地方。断言是用来检查非常罕见的问题。你的用户不应该看到任何断言错误,如果他们看到了,这是一个bug,修复它。 有的情况下,不用断言是因为它比精确的检查要短,它不应该是懒码农的偷懒方式。 不要用它来检查对公共库的输入参数,因为它不能控制调用者,所以不能保证调用者会不会打破双方的约定。 不要为你觉得可以恢复的错误用断言。换句话说,不用改在产品代码里捕捉到断言错误。 不要用太多断言以至于让代码很晦涩。

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

运维自动化之ansible playbook结合docker安装smokeping

本次介绍ansible的paly book结合docker进行虚拟机里安装2.6.8版本smokeping(apache版本是2.4.7)。 docker版本 1 2 3 4 5 6 7 8 9 10 09:26:53 #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:28:13 #ansible--version ansible1.4.3 1、查看docker已有镜像 1 2 3 4 5 09:25:55 #dockerimages REPOSITORYTAGIMAGEIDCREATEDVIRTUALSIZE ubuntu3.06cee552765289weeksago369.8MB centos53.0e08d23b091899weeksago840.9MB centos63.0e94a3b24a19b9weeksago415.9MB 可以看到有3个镜像,1个是ubuntu,1个centos5,1个centos6.我这里打算使用centos6来弄。 2、加载新容器 1 2 3 4 5 6 09:31:01 #timedockerinspect$(dockerrun-d-p22-p80:80--name="smokeping"centos6:3.0/usr/sbin/sshd-D)|grep-iaddress|awk-F'"''{print$4}' 172.17.0.5 real 0m4.737s user 0m0.038s sys 0m0.054s 可以看到4秒就加载新容器完成,并且镜像为centos6系统,容器名为smokeping,开启了ssh服务,并且暴漏了22与80端口。 下面在从后端看看本机都运行了哪些容器 1 2 3 4 5 6 09:31:29 #dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 56b70c31a07ecentos6:3.0 /usr/sbin/sshd -DAboutaminuteagoUpAboutaminute0.0.0.0:80->80 /tcp ,0.0.0.0:49156->22 /tcp smokeping 846efb9e4d7aubuntu:3.0 /usr/sbin/sshd -D12daysagoUp4days0.0.0.0:49167->22 /tcp ubuntu-test1 b9a9e6f2caedcentos6:3.0 /usr/sbin/sshd -D3weeksagoUp4days0.0.0.0:49166->22 /tcp zabbix-server 978fff134b18centos6:3.0 /usr/sbin/sshd -D4weeksagoUp4days0.0.0.0:49165->22 /tcp centos6-test5 下面是ansible安装smokeping的部分 3、ansible安装smokeping的信息 1 2 3 4 5 09:34:06 #catsmokeping_install/vars/main.yml smokeping_dir: /usr/local/smokeping smokeping_version:2.6.8 smokeping_user:admin smokeping_passwd: '()TF%penst*&MedHU' 可以看到smokeping安装目录是/usr/local/smokeping,安装版本是2.6.8,登陆的账户是admin,登陆密码是()TF%penst*&MedHU 4、下面是安装smokeping的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 31 32 33 34 35 36 09:36:25 #treesmokeping_* smokeping_delete ├──files │└──delete_smokeping.sh ├──handlers ├──meta │└──main.yml ├──tasks │├──copy.yml │├──delete.yml │└──main.yml ├──templates └──vars ├──main.xml ├──main.yml └──vars └──main.yml smokeping_install ├──files │├──rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm │└──smokeping. tar .gz ├──handlers ├──meta │└──main.yml ├──tasks │├──copy.yml │├──delete.yml │├── install .yml │└──main.yml ├──templates │├──config │└──smokeping.conf └──vars └──main.yml 13directories,18files 5、playbook安装smokeping的内容是 1 2 3 4 5 6 7 8 9 10 09:37:27 #catsmokeping_install.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -common -pcre_install -apache_install -smokeping_install 6、playbook删除smokeping的内容是 1 2 3 4 5 6 7 8 9 09:38:01 #catsmokeping_delete.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -apache_delete -pcre_delete -smokeping_delete 下面是安装与测试过程 7、把docker新容器smokeping的ip加入到ansible的hosts里 1 echo "172.17.0.5" >> /etc/ansible/hosts 8、安装smokeping 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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 09:39:10 #timeansible-playbooksmokeping_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:[pcre_install|CopyPcreSoftwareToRedhatClient]******************** changed:[172.17.0.5] TASK:[pcre_install|UncompressionPcreSoftwareInRedhatClient]*********** changed:[172.17.0.5] TASK:[pcre_install|DeletePcreSoftwareInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|CopyApacheSoftwareToRedhatClient]**************** changed:[172.17.0.5]=>(item=httpd-2.4.7. tar .gz) changed:[172.17.0.5]=>(item=libiconv. tar .gz) TASK:[apache_install|CreateApacheUserInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|UncompressionApacheSoftwareToRedhatClient]******* changed:[172.17.0.5] TASK:[apache_install|CopyApacheConfigToRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|CopyApacheVhostConfigToRedhatClient]************ changed:[172.17.0.5] TASK:[apache_install|CopyApacheStartServiceScriptToRedhatClient]*** changed:[172.17.0.5] TASK:[apache_install|CreateLibInstallDir]******************************* ok:[172.17.0.5] TASK:[apache_install|CheckApacheIconvInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|InstallApacheIconvInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CheckLibInConfigInRedhatClient]***************** failed:[172.17.0.5]=>{ "changed" : true , "cmd" : "grep-c/usr/local/lib//etc/ld.so.conf" , "delta" : "0:00:00.006524" , "end" : "2014-08-1109:40:48.822372" , "item" : "" , "rc" :1, "start" : "2014-08-1109:40:48.815848" } stdout:0 ...ignoring TASK:[apache_install|InstallApacheIconvInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CreateApacheDir]************************************ changed:[172.17.0.5]=>(item= /data/webroot/apache ) changed:[172.17.0.5]=>(item= /data/webroot/apache/logs ) changed:[172.17.0.5]=>(item= /data/webroot/apache/vhost ) TASK:[apache_install|InstallCheckScriptInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CreateIndexHtmlToRedhatClient]******************* changed:[172.17.0.5] TASK:[apache_install|StartApacheServiceInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|AddBootStartApacheServiceInRedhatClient]******* changed:[172.17.0.5] TASK:[apache_install|DeleteApachecompressionSoftwareInRedhatClient]*** changed:[172.17.0.5] TASK:[smokeping_install|CreateSmokepingInstallDir]********************** changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingSoftwareToRedhatClient]********** changed:[172.17.0.5]=>(item=rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm) changed:[172.17.0.5]=>(item=smokeping. tar .gz) TASK:[smokeping_install|InstallEpelYumRepo]***************************** changed:[172.17.0.5] TASK:[smokeping_install|InstallRequireSoftware]************************** changed:[172.17.0.5] TASK:[smokeping_install|UncompressionSmokeping]************************** changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingConfigToRedhatClient]************ changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingHttpdConfigToRedhatClient]****** changed:[172.17.0.5] TASK:[smokeping_install|CheckBootStartInRedhatClient]***************** failed:[172.17.0.5]=>{ "changed" : true , "cmd" : "grep-c'/usr/local/smokeping/bin/smokeping--logfile=/var/log/smokeping.log2>&1&'/etc/rc.local" , "delta" : "0:00:00.007325" , "end" : "2014-08-1109:46:03.045378" , "item" : "" , "rc" :1, "start" : "2014-08-1109:46:03.038053" } stdout:0 ...ignoring TASK:[smokeping_install|AddBootStartInRedhatClient]******************* changed:[172.17.0.5] TASK:[smokeping_install|ModifySmokepingDirPermissionInRedhatClient]*** changed:[172.17.0.5] TASK:[smokeping_install|StartSmokepingServiceInRedhatClient]********** changed:[172.17.0.5] TASK:[smokeping_install|RestartApacheServiceInRedhatClient]*********** changed:[172.17.0.5] TASK:[smokeping_install|DeleteInstalledFile]***************************** changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=35changed=33unreachable=0failed=0 real 6m52.934s user 0m15.104s sys 0m1.632s 花费6分52秒完成,花费时间多的主要是yum安装基础库与使用epel安装smokeping依赖库。 9、安装后测试 查看smokeping 由于我做了安全认证,需要输入账户与密码,这个账户与密码就上文第3步的账户与密码 然后默认的其他网络监控(包括1、2、3线电信、移动、联通、铁通与教育网的节点监控已经做好) 如果有其他的监控需要自己来添加即可。 10、删除 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 09:46:08 #timeansible-playbooksmokeping_delete.yml--extra-vars"host=172.17.0.5user=root"-k SSHpassword: PLAY[172.17.0.5]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.5] TASK:[apache_delete|StopHttpdServiceInRedHatClient]******************* changed:[172.17.0.5] TASK:[apache_delete|DeleteBootStartInRedHatClient]******************** changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheDirInRedHatClient]******************** changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheServiceScriptInRedHatClient]********* changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheUser]************************************ changed:[172.17.0.5] TASK:[pcre_delete|DeletePcre]********************************************* changed:[172.17.0.5] TASK:[smokeping_delete|StopSmokepingServiceInRedhatClient]************ changed:[172.17.0.5] TASK:[smokeping_delete|DeleteSmokepingDirInRedhatClient]************** changed:[172.17.0.5] TASK:[smokeping_delete|DeleteBootStartInRedhatClient]***************** changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=10changed=9unreachable=0failed=0 real 0m9.326s user 0m2.914s sys 0m0.446s 11、删除后测试 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 09:59:45 #ssh172.17.0.5 root@172.17.0.5'spassword: root@56b70c31a07e:~ 09:59:57 #ifconfig eth0Linkencap:EthernetHWaddrA6:80:57:2D:D3:F1 inetaddr:172.17.0.5Bcast:0.0.0.0Mask:255.255.0.0 inet6addr:fe80::a480:57ff:fe2d:d3f1 /64 Scope:Link UPBROADCASTRUNNINGMTU:1500Metric:1 RXpackets:84520errors:0dropped:0overruns:0frame:0 TXpackets:86385errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:1000 RXbytes:69075188(65.8MiB)TXbytes:9400662(8.9MiB) loLinkencap:LocalLoopback inetaddr:127.0.0.1Mask:255.0.0.0 inet6addr:::1 /128 Scope:Host UPLOOPBACKRUNNINGMTU:16436Metric:1 RXpackets:2errors:0dropped:0overruns:0frame:0 TXpackets:2errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:0 RXbytes:168(168.0b)TXbytes:168(168.0b) root@56b70c31a07e:~ 09:59:59 #ps-ef|grephttpd root10171002010:00pts /0 00:00:00 grep httpd root@56b70c31a07e:~ 10:00:04 #ps-ef|grepsmokeping root10191002010:00pts /0 00:00:00 grep smokeping root@56b70c31a07e:~ 10:00:07 #ll/usr/local/ total40 drwxr-xr-x2rootroot4096Sep232011bin drwxr-xr-x2rootroot4096Sep232011etc drwxr-xr-x2rootroot4096Sep232011games drwxr-xr-x2rootroot4096Sep232011include drwxr-xr-x2rootroot4096Aug1109:40lib drwxr-xr-x2rootroot4096Sep232011lib64 drwxr-xr-x2rootroot4096Sep232011libexec drwxr-xr-x2rootroot4096Sep232011sbin drwxr-xr-x5rootroot4096Sep232011share drwxr-xr-x2rootroot4096Sep232011src root@56b70c31a07e:~ 10:00:11 #cat/etc/rc.local #!/bin/sh # #Thisscriptwillbeexecuted*after*alltheotherinitscripts. #Youcanputyourowninitializationstuffinhereifyoudon't #wanttodothefullSysVstyleinitstuff. touch /var/lock/subsys/local 如果大家想使用我的例子,可以从github里下载(地址是https://github.com/dl528888/ansible-examples/tree/master/smokeping_install),然后放到/etc/ansible目录里,下面是内容 本文转自 reinxu 51CTO博客,原文链接:http://blog.51cto.com/dl528888/1538444,如需转载请自行联系原作者

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

Android自动化测试之使用java调用monkeyrunner(补充篇)

上一篇使用java调用monkeyrunner(http://fengbohaishang.blog.51cto.com/5106297/1065647)中遗留了一个问题,就是上次用的是低版本的4个包解决的问题,使用高版本的jar包怎么调用monkeyrunner呢? 经过一位朋友的提示说,现在高版本的方法已经变了,我就按照他的提示,上网搜了一下需要的类,测试通过后,特写此补充篇总结一下。 上次使用的是android sdktools路径下的lib里面的4个包:ddmlib.jar,guavalib.jar,monkeyrunner.jar,sdklib.jar.而更新后的版本需要添加另外一个包就是:chimpchat.jar,monkerunner.jar这个包倒不是必须的了。另外,低版本中是用AdbMonkeyDevice实现IMonkeyDevice,高版本中没有这两个类了,用的AdbChimpDevice和IchimpDevice。 而通过查看AdbChimpDevice( http://code.google.com/p/aster/source/browse/src/com/android/chimpchat/adb/AdbChimpDevice.java?r=967f7f8cd6249c69e00c6de7ff1b55bd0f51d311)和IchimpDevice( http://code.google.com/p/aster/source/browse/src/com/android/chimpchat/core/IChimpDevice.java?r=967f7f8cd6249c69e00c6de7ff1b55bd0f51d311)这两个类在官方的源码,就不难发现,AdbChimpDevice实现了IchimpDevice这个接口,不过连接方法还是通过AdbBackend,通过adb方式连接模拟器,或者真机。只是Device的父类发生了变化。 下面还是用以前的测试类,进行稍微改变一下,就可以看出两者的不同: importjava.util.ArrayList; importjava.util.Collection; importjava.util.HashMap; importcom.android.chimpchat.adb.AdbBackend; importcom.android.chimpchat.adb.AdbChimpDevice; publicclassTestNewMonkeyrunner{ /** *@paramargs */ //这里有变化 privatestaticAdbChimpDevicedevice; privatestaticAdbBackendadb; publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub if(adb==null){ adb=newAdbBackend(); //参数分别为自己定义的等待连接时间和设备id //这里需要注意一下adb的类型 device=(AdbChimpDevice)adb.waitForConnection(8000,"MSM8225QRD5"); } //添加启动权限 Stringaction="android.intent.action.MAIN"; Collection<String>categories=newArrayList<String>(); categories.add("android.intent.category.LAUNCHER"); //启动要测试的主界面 device.startActivity(null,action,null,null,categories, newHashMap<String,Object>(),"cn.com.fetion/.android.ui.activities.StartActivity",0); //点击某一个坐标 //touch方法略有变化 device.touch(202,258,com.android.chimpchat.core.TouchPressType.DOWN_AND_UP); } } 从上面可以看出,高版本与低版本的变化,并不是很多。只要连接上设备,一些需要用到的操作方法,自己可以去源码里面看,也可以自己重写一些常用的方法。 源码里的注释是非常详细,比如IchimpDevice接口类中的startActivity方法: voidstartActivity(@NullableStringuri,@NullableStringaction, @NullableStringdata,@NullableStringmimeType, Collection<String>categories,Map<String,Object>extras,@NullableStringcomponent, intflags); /** *Sendabroadcastintenttothedevice. * *@paramuritheURIfortheIntent *@paramactiontheactionfortheIntent *@paramdatathedataURIfortheIntent *@parammimeTypethemimetypefortheIntent *@paramcategoriesthecategorynamesfortheIntent *@paramextrastheextrastoaddtotheIntent *@paramcomponentthecomponentoftheIntent *@paramflagstheflagsfortheIntent */ 该方法里对重要参数解释的都很清楚。所以,建议正在研究java调用monkeyrunner问题的朋友们,不要忘了源码这个最好的资源。 本文转自 风泊海上 51CTO博客,原文链接:http://blog.51cto.com/fengbohaishang/1071155

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

appium+python自动化24-滑动方法封装(swipe)

swipe介绍 1.查看源码语法,起点和终点四个坐标参数,duration是滑动屏幕持续的时间,时间越短速度越快。默认为None可不填,一般设置500-1000毫秒比较合适。 swipe(self, start_x, start_y, end_x, end_y, duration=None) Swipe from one point to another point, for an optional duration. 从一个点滑动到另外一个点,duration是持续时间 :Args: - start_x - 开始滑动的x坐标 - start_y - 开始滑动的y坐标 - end_x - 结束点x坐标 - end_y - 结束点y坐标 - duration - 持续时间,单位毫秒 :Usage: driver.swipe(100, 100, 100, 400) 2.手机从左上角开始为0,横着的是x轴,竖着的是y轴 获取坐标 1.由于每个手机屏幕的分辨率不一样,所以同一个元素在不同手机上的坐标也是不一样的,滑动的时候坐标不能写死了。可以先获取屏幕的宽和高,再通过比例去计算。 # coding:utf-8 from appium import webdriver desired_caps = { 'platformName': 'Android', 'deviceName': '30d4e606', 'platformVersion': '4.4.2', # apk包名 'appPackage': 'com.taobao.taobao', # apk的launcherActivity 'appActivity': 'com.taobao.tao.welcome.Welcome' } driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) # 获取屏幕的size size = driver.get_window_size() print(size) # 屏幕宽度width print(size['width']) # 屏幕高度width print(size['height']) 2.运行结果: {u'width': 720, u'height': 1280} 720 1280 封装滑动方法 1.把上下左右四种常用的滑动方法封装,这样以后想滑动屏幕时候就能直接调用了 参数1:driver 参数2:t是持续时间 参数3:滑动次数 2.案例参考 # coding:utf-8 from appium import webdriver from time import sleep desired_caps = { 'platformName': 'Android', 'deviceName': '30d4e606', 'platformVersion': '4.4.2', # apk包名 'appPackage': 'com.taobao.taobao', # apk的launcherActivity 'appActivity': 'com.taobao.tao.welcome.Welcome' } driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) def swipeUp(driver, t=500, n=1): '''向上滑动屏幕''' l = driver.get_window_size() x1 = l['width'] * 0.5 # x坐标 y1 = l['height'] * 0.75 # 起始y坐标 y2 = l['height'] * 0.25 # 终点y坐标 for i in range(n): driver.swipe(x1, y1, x1, y2, t) def swipeDown(driver, t=500, n=1): '''向下滑动屏幕''' l = driver.get_window_size() x1 = l['width'] * 0.5 # x坐标 y1 = l['height'] * 0.25 # 起始y坐标 y2 = l['height'] * 0.75 # 终点y坐标 for i in range(n): driver.swipe(x1, y1, x1, y2,t) def swipLeft(driver, t=500, n=1): '''向左滑动屏幕''' l = driver.get_window_size() x1 = l['width'] * 0.75 y1 = l['height'] * 0.5 x2 = l['width'] * 0.05 for i in range(n): driver.swipe(x1, y1, x2, y1, t) def swipRight(driver, t=500, n=1): '''向右滑动屏幕''' l = driver.get_window_size() x1 = l['width'] * 0.05 y1 = l['height'] * 0.5 x2 = l['width'] * 0.75 for i in range(n): driver.swipe(x1, y1, x2, y1, t) if __name__ == "__main__": print(driver.get_window_size()) sleep(5) swipLeft(driver, n=2) sleep(2) swipRight(driver, n=2) appiumQQ群:512200893

资源下载

更多资源
Nacos

Nacos

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册