• fabric运维


    fabric中文文档:http://fabric-chs.readthedocs.io/zh_CN/chs/

    视频教程:http://study.163.com/course/courseMain.htm?courseId=1003852044

    安装:    pip3 install fabric3 (注:python3对应要装fabric3)

    检查安装情况:fab --version

           进入python3,

           >>> import fabric

           >>> dir(fabric)

    新建目录:  cd /usr/local/fabric

    命令行命令:

    fab -u 用户名 -p 密码 -H ‘10.0.0.202’ -- ‘netstat -anptu | grep 22'

    fab -u 用户名 -p 密码 -H '10.0.0.202,10.0.0.203,10.0.0.204' -- 'uname-a'

    fab -u 用户名 -p 密码 -H '10.0.0.203,10.0.0.204' -- 'yum clean all & yum repolist all'

    fab -u 用户名 -p 密码 -H '10.0.0.203.10.0.0.204' -P(并行) --'reboot'

    fab -u 用户名 -p 密码 -H '10.0.0.203,10.0.0.204' -P --'yum clean all & yum repolist all'

    fab -u 用户名 -p 密码 -H '10.0.0.203,10.0.0.204' -- 'system stop firewalld.service' 

    fab -u 用户名 -p 密码 -H '10.0.0.202,10.0.0.203,10.0.0.204' -P -- 'yum -y install gpm* && service gpm start &&systemctl enable gpm.service'

    fab -u用户名 -p 密码 -H '10.0.0.204' -- 'yum -y install httpd && systemctl start httpd.service && systemctl enable httpd.service'

    浏览器输入10.0.0.204,可以进入apache界面,为安装正常

    fab -u用户名 -p 密码 -H '10.0.0.204' -- 'netstat -anptu | grep 80'

    备注:CentOS7服务使用方法

    服务使用方法
    systemctl start [服务文件名]
    systemctl restart [服务文件名]
    systemctl stop [服务文件名]
    systemctl status [服务文件名]
    设置开机启动
    systemctl enable [服务文件名]
    systemctl disable [服务文件名]

    fabfile文件:

    env.hosts = ['10.0.0.203','10.0.0.204'] 定义Ip或主机名列表

    env.user = 'root'          定义用户名

    env.port = 22            定义端口

    env.password = '密码'         定义密码

    env.password={'root@10.0.0.203:22':"密码",

           'root@10.0.0.204:22':“密码”}  定义用户名、ip、端口、密码

    env.gateway = '10.0.0.254'     定义网关

    env.roledefs = {"webservice":["10.0.0.203","10.0.0.204"],

           "dbservice":["10.0.0.210","10.0.0.211"]  定义角色分租

    函数 定义:

    from fabric.api import *
    local    #执行本地命令,如local('uname -s')
    lcd      #切换本地目录,如lcd('/home')
    cd       #切换远程目录,如cd('/var/logs')
    run      #执行远程命令,如run('free -m')
    sudo     #sudo方式执行远程命令,如sudo('/etc/init.d/httpd start')
    put      #上次本地文件导远程主机,如put('/home/user.info','/data/user.info')
    get      #从远程主机下载文件到本地,如:get('/data/user.info','/home/user.info')
    prompt   #获得用户输入信息,如:prompt('please input user password:')
    confirm  #获得提示信息确认,如:confirm('Test failed,Continue[Y/N]?')
    reboot   #重启远程主机,如:reboot()
    @task    #函数修饰符,标识的函数为fab可调用的,非标记对fab不可见,纯业务逻辑
    @runs_once   #函数修饰符,标识的函数只会执行一次,不受多台主机影响
    @roles() #运行指定的角色组里,通过env.roledefs里的定义
    
    from fabric.colors import *
    print blue(text)
    print cyan(text)
    print green(text)
    print magenta(text)
    print red(text)
    print white(text)
    print yellow(text)

    新建文件:  vi fabfile.py  (fab自动调用文档,其定义的每一个函数,就是一个命令)

           fabfile.py中可写入文档如下:

             from fabric.api import *

             def host_type():

                run('uname -s')

                run('hostname')

           fab -H localhost host_tpye  (-H localhost指定本机运行)

             env.hosts=[

             'root@10.0.0.2:22',

             'root@10.0.0.3:22']

             env.password = '密码'

             def host_type():

              run('uname -s')

          fab host_typt

    新建文件  c.py

    from fabric.api import *
    
    env.hosts = ["10.0.0.203","10.0.0.204"]
    env.passwords = {
        'root@10.0.0.203:22':'z',
        'root@10.0.0.204:22':'z'}
    env.roledefs = {
        'webserver':['10.0.0.204'],
        'dbserver':['10.0.0.203']}
    
    
    @task
    def show():
        run("hostname")
        #run("netstat -anput | grep 22")
        #run("ls /root/")
    @task
    @roles('webserver')
    def install_httpd():
        print('install webserver')
    
    @task
    @roles('dbserver')
    def install_mysql():
        print('install_mysql')
    
    @task
    def run_all():
        execute(show)
        execute(install_httpd)
        execute(install_mysql)
    if __name__ == '__main__': execute(run_all)

    fab -f c.py -l

    fab -f c.py show

    fab -f c.py run_all

    python3 c.pu  (对应文中if判断)

    新建文件  d.py

    from fabric.api import *
    from fabric.colors import *
    
    env.hosts = ["10.0.0.203","10.0.0.204"]
    env.passwords = {
        'root@10.0.0.203:22':'z',
        'root@10.0.0.204:22':'z'}
    env.roledefs = {
        'webserver':['10.0.0.204'],
        'dbserver':['10.0.0.203']}
    @task
    def local_cmd():
        local('ls -la')
        with lcd('/usr/local'):
            local("ls -la")
    
    @task
    def runsudo1():
        run('free -m')
        sudo('cat /etc/passwd')
    
    @task
    def cd1():
        with cd('/etc'):
            run('ls -la')
    
    @task
    def put1():
        put('d.py','/usr/local/')
        run('ls -la /usr/local/')
    
    @task
    def get1():
        get('/usr/local/d.py','dd.py')
        local('ls -la')
    
    @task
    def prompt1():
        content1 = prompt("请输入字符:")
        print(content1)
    
    @task    
    def color1():
        print(white('hello world!'))
        print(yellow('hello world!'))
        print(red('hello world!'))
        print(blue('hello world!'))
        print(green('hello world!'))
        print(cyan('hello world!'))
        print(magenta('hello world!'))

     confirm

    (env1) [root@centos7-3 env1]# python3
    >>> from fabric.contrib.console import confirm
    >>> content = confirm('continue[Y/N]?')
    continue[Y/N]? [Y/n] y
    >>> content
    True
    >>> content = confirm('continue[Y/N]?')
    continue[Y/N]? [Y/n] n
    >>> content
    False

    文件的打包 、上传、校验、下载:

    打包:tar -czf xxx.tar.gz.xxx

    解包:tar -zxf xxx.tar.gz -C 路径

    上传:put('本地文件路径',‘远程文件路径’)

    下载:get(‘远程文件路径’,‘本地文件路径’)

     新建文件  e.py

     1 from fabric.api import*
     2 from fabric.contrib.console import confirm
     3 from fabric.colors import *
     4 
     5 env.hosts =['10.0.0.204']
     6 env.user = 'root'
     7 
     8 env.passwords = {
     9     'root@10.0.0.203:22':'z',
    10     'root@10.0.0.204:22':'z'}
    11 
    12 @task
    13 def upload_file():
    14     with settings(warn_only=True):
    15         local('tar -czf b.tar.gz b.py')
    16         result = put('b.tar.gz','/usr/local/')
    17     if result.failed and not confirm('continue[Y/N]?'):
    18         abort('put b.tar.gz failed!')
    19     with settings(warn_only=True):
    20         local_file = local('md5sum b.tar.gz',capture=True).split(" ")[0]
    21         remote_file = run('md5sum /usr/local/b.tar.gz').split(" ")[0]
    22     if local_file == remote_file:
    23         print(green('local == remote'))
    24     else:
    25         print(red('local != remote'))
    26     run('mkdir /usr/local/test')
    27     run('tar -zxf /usr/local/b.tar.gz -C /usr/local/test/')
    28 
    29 @task
    30 def download_file():
    31     with settings(warn_only=True):
    32         get('/usr/local/b.tar.gz','/usr/local/b1.tar.gz')
    33         local('mkdir /usr/local/test1')
    34         local('tar -zxf /usr/local/b1.tar.gz -C /usr/local/test1')    

    多主机并行运维:

    新建文件夹  f.py

    @parallel  #并行

    from fabric.api import *
    env.user = "root"
    host1 = "10.0.0.202"
    host2 = "10.0.0.203"
    host3 = "10.0.0.204"
    env.hosts = [host1,host2,host3]
    env.passwords ={
        "root@10.0.0.202:22":"z",
        "root@10.0.0.203:22":"z",
        "root@10.0.0.204:22":"z"}
    
    @task
    @parallel
    @hosts(host1,host2,host3)
    def install_ftp():
        run("yum clean all")
        run("yum repolist all")
        run("yum -y install vsftpd")
        run("systemctl start vsftpd.service")
        run("systemctl enable vsftpd.service")
        run("systemctl status vsftpd.service")

     以下文档转载自:http://blog.51cto.com/lizhenliang/1880856

    第十八章 Python批量管理主机(paramiko、fabric与pexpect)

    本章节主要讲解运维工程师比较感兴趣的知识,那就是运维批量管理,在Python下有paramiko、fabric和pexpect这三个模块可帮助运维实现自动化部署、批量执行命令、文件传输等常规任务,接下来一起看看它们的使用方法吧!

    18.1 paramiko

    paramiko模块是基于Python实现的SSH远程安全连接,用于SSH远程执行命令、文件传输等功能。

    默认Python没有,需要手动安装:pip install paramiko

    如安装失败,可以尝试yum安装:yum install python-paramiko

    18.1.1 SSH密码认证远程执行命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import paramiko
    import sys
    hostname = '192.168.1.215'
    port = 22
    username = 'root'
    password = '123456'
    client = paramiko.SSHClient()  # 绑定实例
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(hostname, port, username, password, timeout=5)
    stdin, stdout, stderr = client.exec_command('df -h')   # 执行bash命令
    result = stdout.read()
    error = stderr.read()
    # 判断stderr输出是否为空,为空则打印执行结果,不为空打印报错信息
    if not error:
       print result
    else:
       print error
    client.close()

    18.1.2 私钥认证远程执行命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import paramiko
    import sys
    hostname = '192.168.1.215'
    port = 22
    username = 'root'
    key_file = '/root/.ssh/id_rsa'
    cmd = " ".join(sys.argv[1:])
    def ssh_conn(command):
        client = paramiko.SSHClient()
        key = paramiko.RSAKey.from_private_key_file(key_file)
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(hostname, port, username, pkey=key)
        stdin, stdout, stderr = client.exec_command(command)  # 标准输入,标准输出,错误输出
        result = stdout.read()
        error = stderr.read()
        if not error:
            print result
        else:
            print error
        client.close()
    if __name__ == "__main__":
        ssh_conn(cmd)

    18.1.3 上传文件到远程服务器

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os, sys
    import paramiko
    hostname = '192.168.1.215'
    port = 22
    username = 'root'
    password = '123456'
    local_path = '/root/test.txt'
    remote_path = '/opt/test.txt'
    if not os.path.isfile(local_path):
        print local_path + " file not exist!"
        sys.exit(1)
    try:
        = paramiko.Transport((hostname, port))
        s.connect(username = username, password=password)
    except Exception as e:
        print e
        sys.exit(1)
    sftp = paramiko.SFTPClient.from_transport(s)
    # 使用put()方法把本地文件上传到远程服务器
    sftp.put(local_path, remote_path)       
    # 简单测试是否上传成功
    try:
        # 如果远程主机有这个文件则返回一个对象,否则抛出异常               
        sftp.file(remote_path) 
        print "上传成功."
    except IOError:
        print "上传失败!"
    finally:
        s.close()

    18.1.4 从远程服务器下载文件

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os, sys
    import paramiko
    hostname = '192.168.1.215'
    port = 22
    username = 'root'
    password = '123456'
    local_path = '/root/test.txt'
    remote_path = '/opt/test.txt'
    try:
        = paramiko.Transport((hostname, port))
        s.connect(username=username, password=password)
        sftp = paramiko.SFTPClient.from_transport(s)
    except Exception as e:
        print e
        sys.exit(1)
    try:
        # 判断远程服务器是否有这个文件
        sftp.file(remote_path)
        # 使用get()方法从远程服务器拉去文件
        sftp.get(remote_path, local_path)       
    except IOError as e:
        print remote_path + "remote file not exist!"
        sys.exit(1)
    finally:
        s.close()
    # 测试是否下载成功
    if os.path.isfile(local_path):
        print "下载成功."
    else:
        print "下载失败!"

    18.1.5 上传目录到远程服务器

    paramiko模块并没有实现直接上传目录的类,已经知道了如何上传文件,再写一个上传目录的代码就简单了,利用os库的os.walk()方法遍历目录,再一个个上传:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os, sys
    import paramiko
    hostname = '192.168.1.215'
    port = 22
    username = 'root'
    password = '123456'
    local_path = '/root/abc'
    remote_path = '/opt/abc'
    # 去除路径后面正斜杠
    if local_path[-1== '/':
        local_path = local_path[0:-1]
    if remote_path[-1== '/':
        remote_path = remote_path[0:-1]
    file_list = []
    if os.path.isdir(local_path):
        for root, dirs, files in os.walk(local_path):
            for file in files:
                # 获取文件绝对路径
                file_path = os.path.join(root, file
                file_list.append(file_path)
    else:
        print path + "Directory not exist!"
        sys.exit(1)
    try:
        = paramiko.Transport((hostname, port))
        s.connect(username=username, password=password)
        sftp = paramiko.SFTPClient.from_transport(s)
    except Exception as e:
        print e
    for local_file in file_list:
        # 替换目标目录
        remote_file = local_file.replace(local_path, remote_path)
        remote_dir = os.path.dirname(remote_file)
        # 如果远程服务器没目标目录则创建
        try:
            sftp.stat(remote_dir)
        except IOError:
            sftp.mkdir(remote_dir)
        print "%s -> %s" % (local_file, remote_file)
        sftp.put(local_file, remote_file)
    s.close()

    sftp是安全文件传输协议,提供一种安全的加密方法,sftp是SSH的一部分,SFTPClient类实现了sftp客户端,通过已建立的SSH通道传输文件,与其他的操作,如下:

    sftp.getcwd() 返回当前工作目录
    sftp.chdir(path) 改变工作目录
    sftp.chmod(path, mode) 修改权限
    sftp.chown(path, uid, gid) 设置属主属组
    sftp.close() 关闭sftp
    sftp.file(filename, mode='r', bufsize=-1) 读取文件
    sftp.from_transport(s) 创建SFTP客户端通道
    sftp.listdir(path='.') 列出目录,返回一个列表
    sftp.listdir_attr(path='.') 列出目录,返回一个SFTPAttributes列表
    sftp.mkdir(path, mode=511) 创建目录
    sftp.normalize(path) 返回规范化path
    sftp.open(filename, mode='r', bufsize=-1) 在远程服务器打开文件
    sftp.put(localpath, remotepath, callback=None) localpath文件上传到远程服务器remotepath
    sftp.get(remotepath, localpath, callback=None) 从远程服务器remotepath拉文件到本地localpath
    sftp.readlink(path) 返回一个符号链接目标
    sftp.remove(path) 删除文件
    sftp.rename(oldpath, newpath) 重命名文件或目录
    sftp.rmdir(path) 删除目录
    sftp.stat(path) 返回远程服务器文件信息(返回一个对象的属性)
    sftp.truncate(path, size) 截取文件大小
    sftp.symlink(source, dest) 创建一个软链接(快捷方式)
    sftp.unlink(path) 删除软链接

     

    博客地址:http://lizhenliang.blog.51cto.com

    QQ群:323779636(Shell/Python运维开发群)

    18.2 fabric

    fabric模块是在paramiko基础上又做了一层封装,操作起来更方便。主要用于多台主机批量执行任务。

    默认Python没有,需要手动安装:pip install fabric

    如安装失败,可以尝试yum安装:yum install fabric

    Fabric常用API:

    API类

    描述

    示例

    local 执行本地命令 local('uname -s')
    lcd 切换本地目录 lcd('/opt')
    run 执行远程命令 run('uname -s')
    cd 切换远程目录 cd('/opt')
    sudo sudo方式执行远程命令 sudo('/etc/init.d/httpd start')
    put 上传本地文件或目录到远程主机 put(remote_path, local_path)
    get 从远程主机下载文件或目录到本地 put(local_path, remote_path)
    open_shell 打开一个shell,类似于SSH连接到了远程主机 open_shell("ifconfig eth0")
    prompt 获得用户输入信息 prompt('Please input user password: ')
    confirm 获得提示信息确认 confirm('Continue[Y/N]?')
    reboot 重启远程主机 reboot()
    @task 函数装饰器,引用说明函数可调用,否则不可见  
    @runs_once 函数装饰器,函数只会执行一次  

    当我们写好fabric脚本后,需要用fab命令调用执行任务。

    命令格式:fab [options] <command>[:arg1,arg2=val2,host=foo,hosts='h1;h2',...] ...

    fab命令有以下常用选项:

    选项

    描述

    -l 打印可用的命令(函数)
    --set=KEY=VALUE,... 逗号分隔,设置环境变量
    --shortlist 简短打印可用命令
    -c PATH 指定本地配置文件
    -D 不加载用户known_hosts文件
    -f PATH 指定fabfile文件
    -g HOST 逗号分隔要操作的主机
    -i PATH 指定私钥文件
    -k 不加载来自~/.ssh下的私钥文件
    -p PASSWORD 使用密码认证and/or sudo
    -P 默认为并行执行方法
    --port=PORT 指定SSH连接端口
    -R ROLES 根据角色操作,逗号分隔
    -s SHELL 指定新shell,默认是'/bin/bash -l -c'
    --show=LEVELS 以逗号分隔的输出
    --ssh-config-path=PATH SSH配置文件路径
    -t N 设置连接超时时间,单位秒
    -T N 设置远程命令超时时间,单位秒
    -u USER 连接远程主机用户名
    -x HOSTS 以逗号分隔排除主机
    -z INT 并发进程数

    18.2.1 本地执行命令

    1
    2
    3
    4
    5
    6
    7
    from fabric.api import local
    def command():
        local('ls')
    # fab command
    [localhost] local: ls
    fabfile.py  fabfile.pyc  tab.py  tab.pyc
    Done.

    使用fab命令调用,默认寻找当前目录的fabfile.py文件。

    18.2.2 远程执行命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from fabric.api import run
    def command():
        run('ls')
    # fab -H 192.168.1.120 -u user command
    [192.168.1.120] Executing task 'command'
    [192.168.1.120] run: ls
    [192.168.1.120] Login password for 'user':
    [192.168.1.120] out: access.log  a.py
    [192.168.1.120] out:
    Done.
     
    Disconnecting from 192.168.1.120... done.

    如果在多台主机执行,只需要-H后面的IP以逗号分隔即可。

    18.2.3 给脚本函数传入位置参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from fabric.api import run
    def hello(name="world"):
        print("Hello %s!" % name)
    # fab -H localhost hello
    [localhost] Executing task 'hello'
    Hello world!
    Done.
    # fab -H localhost hello:name=Python
    [localhost] Executing task 'hello'
    Hello Python!
    Done.

    18.2.4 主机列表组

    1
    2
    3
    4
    5
    6
    from fabric.api import run, env
    env.hosts = ['root@192.168.1.120:22''root@192.168.1.130:22']
    env.password = '123.com'
    env.exclude_hosts = ['root@192.168.1.120:22']   # 排除主机
    def command():
       run('ls')

    env作用是定义fabfile全局设定,类似于变量。还有一些常用的属性:

    env属性

    描述

    示例

    env.hosts 定义目标主机 env.hosts = ['192.168.1.120:22']
    env.exclude_hosts 排除指定主机 env.exclude_hosts = '[192.168.1.1]'
    env.user 定义用户名 env.user='root'
    env.port 定义端口 env.port='22'
    env.password 定义密码 env.password='123'
    env.passwords 定义多个密码,不同主机对应不同密码 env.passwords = {'root@192.168.1.120:22': '123'}
    env.gateway 定义网关 env.gateway='192.168.1.2'
    env.roledefs 定义角色分组 env.roledef = {'web':['192.168.1.11'], 'db':['192.168.1.12']}
    env.deploy_release_dir 自定义全局变量,格式:env.+ '变量名' env.var

    18.2.5 定义角色分组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # vi install.py
    from fabric.api import run, env
    env.roledefs = {
        'web': ['192.168.1.10''192.168.1.20'],
        'db': ['192.168.1.30''192.168.1.40']
    }
    env.password = '123'
    @roles('web')
    def task1():
       run('yum install httpd -y')
    @roles('db')
    def task2():
       run('yum install mysql-server -y')
    def deploy():
       execute(task1)
       execute(task2)
    # fab -f install.py deploy

    18.2.6 上传目录到远程主机

    1
    2
    3
    4
    5
    6
    7
    8
    from fabric.api import *
    env.hosts = ['192.168.1.120']
    env.user = 'user'
    env.password = '123.com'
    def task():
       put('/root/abc''/home/user')
       run('ls -l /home/user')
    # fab task

    18.2.7 从远程主机下载目录

    1
    2
    3
    4
    5
    6
    7
    8
    from fabric.api import *
    env.hosts = ['192.168.1.120']
    env.user = 'user'
    env.password = '123.com'
    def task():
       get('/home/user/b''/opt')
       local('ls -l /opt')
    # fab task

    18.2.8 打印颜色,有助于关键地方醒目

    1
    2
    3
    4
    5
    6
    from fabric.colors import *
    def show():
       print green('Successful.')
       print red('Failure!')
       print yellow('Warning.')
    # fab show

    经过上面演示fabric主要相关功能,是不是觉得很适合批量自动部署呢!没错,通过编写简单的脚本,即可完成复杂的操作。

    博客地址:http://lizhenliang.blog.51cto.com

    QQ群:323779636(Shell/Python运维开发群)

    18.3 pexpect

    pexpect是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的Python模块。暂不支持Windows下的Python环境执行。

    这里主要讲解run()函数和spawn()类,能完成自动交互,下面简单了解下它们使用。

    18.3.1 run()

    run()函数用来运行bash命令,类似于os模块中的system()函数。

    参数:run(command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None)

    1
    2
    3
    4
    5
    1:执行ls命令
    >>> import pexpect
    >>> pexpect.run("ls"
    2:获得命令状态返回值
    >>> command_output, exitstatus = pexpect.run("ls", withexitstatus=1)

    command_outout是执行结果,exitstatus是退出状态值。

    18.3.2 spawn()

    spawn()是pexpect模块主要的类,实现启动子程序,使用pty.fork()生成子进程,并调用exec()系列函数执行命令。

    参数:spawn(command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None)

    spawn()类几个常用函数:

    expect(pattern, timeout=-1, searchwindowsize=None) 匹配正则表达式,pattern可以是正则表达式。
    send(s) 给子进程发送一个字符串
    sendline(s='') 就像send(),但添加了一个换行符(os.lineseq)
    sendcontrol(char) 发送一个控制符,比如ctrl-c、ctrl-d

    例子:ftp交互

    用ftp命令登录是这样的,需要手动输入用户名和密码,才能登录进去。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # ftp 192.168.1.10
    Connected to 192.168.1.10 (192.168.1.10).
    220-FileZilla Server version 0.9.46 beta
    220-written by Tim Kosse (tim.kosse@filezilla-project.org)
    220 Please visit http://sourceforge.net/projects/filezilla/
    Name (192.168.1.10:root): yunwei
    331 Password required for yunwei
    Password:
    230 Logged on
    Remote system type is UNIX.
    ftp>

    下面我们用pexpect帮我们完成输入用户名和密码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import pexpect
    child = pexpect.spawn('ftp 192.168.1.10')
    child.expect('Name .*: ')
    child.sendline('yunwei')
    child.expect('Password:')
    child.sendline('yunweipass')
    child.expect('ftp> ')
    child.sendline('ls')
    child.sendline('bye')
    child.expect(pexpect.EOF)   # pexpect.EOF程序打印提示信息
    print child.before   # 保存命令执行结果

    手动输入时,是来自键盘的标准输入,而pexpect是先匹配到关键字,再向子进程发送字符串。

    pexpect.EOF打印提示信息,child.before保存的是命令执行结果。

    通过上面的例子想必你已经知道pexpect主要功能了,在交互场景下很有用,这里就讲解这么多了,目的是给大家提供一个自动交互实现思路。

    小结:

    通过对Python下paramiko、fabric和pexpect模块使用,它们各有自己擅长的一面。

    paramiko:方便嵌套系统平台中,擅长远程执行命令,文件传输。

    fabric:方便与shell脚本结合,擅长批量部署,任务管理。

    pexpect:擅长自动交互,比如ssh、ftp、telnet。

  • 相关阅读:
    阻止表单重复提交的办法以及支付成功后页面后退重复提交的解决方案
    jsp页面的共用
    空间谱专题02:波束形成(Beamforming)
    空间谱专题01:信号模型
    空间谱专题00:综述
    BP神经网络
    fdatool的滤波器设计
    Testbench
    Cordic算法简介
    快速删除注释
  • 原文地址:https://www.cnblogs.com/jackyzm/p/9105739.html
Copyright © 2020-2023  润新知