• fexpect 源码


    通过fabric 调用执行需要人机交互,输入确认信息时,一般有两种方案:

    1、fabric 自身 with settings(prompts=prompt_restore)。
    2、pexpect组件解决。

    这里的fexpect,其实是对pexpect的包装。只是使用方式上与fabric 配搭起来更加灵活。其主要源码如下:

    1、ilogue/fexpect/api.py
    ####################################
    import fabric.api
    from ilogue.fexpect.internals import wrapExpectations, wrapExpectationsLocal, ExpectationContext
    
    
    def expect(promptexpr, response, exitAfter=-1):
        if not exitAfter == -1:
            return [(promptexpr, response, exitAfter)]
        return [(promptexpr, response)]
    
    # Use inside an expect(), like:  `expect('>>>', controlchar('D'))`
    def controlchar(char):
        char = char.lower()
        a = ord(char)
        if a >= 97 and a <= 122:
            a = a - ord('a') + 1
            return chr(a)
        d = {'@': 0, '`': 0,
            '[': 27, '{': 27,
            '\': 28, '|': 28,
            ']': 29, '}': 29,
            '^': 30, '~': 30,
            '_': 31,
            '?': 127}
        if char not in d:
            return 0
        return chr(d[char])
    
    def expecting(e):
        return ExpectationContext(e)
    
    def run(cmd, **kwargs):
        #run wrapper 
        if 'expectations' in fabric.state.env and 
            len(fabric.state.env.expectations) > 0:
            cmd = wrapExpectations(cmd)
        return fabric.api.run(cmd, **kwargs)
    
    def sudo(cmd, **kwargs):
        #sudo wrapper
        if 'expectations' in fabric.state.env and 
            len(fabric.state.env.expectations) > 0:
            cmd = wrapExpectations(cmd)
        return fabric.api.sudo(cmd, **kwargs)
    
    def local(cmd, **kwargs):
        #local wrapper
        if 'expectations' in fabric.state.env and 
            len(fabric.state.env.expectations) > 0:
            cmd = wrapExpectationsLocal(cmd)
        return fabric.api.local(cmd, **kwargs)
    
    
    2、ilogue/fexpect/internals.py
    #####################################
    import shortuuid
    from StringIO import StringIO
    import fabric
    
    class ExpectationContext(object):
        def __init__(self,expectations):
            self.expectations = expectations
        def __enter__(self):
            fabric.state.env.expectations = self.expectations
        def __exit__(self, type, value, tb):
            fabric.state.env.expectations = []
    
    def wrapExpectations(cmd):
        script = createScript(cmd)
        remoteScript = '/tmp/fexpect_'+shortuuid.uuid()
        import pexpect
        pexpect_module = pexpect.__file__
        if pexpect_module.endswith('.pyc'):
            pexpect_module = pexpect_module[:-1]
        # If mode not set explicitly, and this is run as a privileged user, 
        # later command from an unpriviliged user will fail due to the permissions
        # on /tmp/pexpect.py
        fabric.api.put(pexpect_module,'/tmp/', mode=0777) 
        fabric.api.put(StringIO(script),remoteScript)
        wrappedCmd = 'python '+remoteScript
        return wrappedCmd
    
    def wrapExpectationsLocal(cmd):
        script = createScript(cmd)
        remoteScript = '/tmp/fexpect_'+shortuuid.uuid()
        with open(remoteScript, 'w') as filehandle:
            filehandle.write(script)
        wrappedCmd = 'python '+remoteScript
        return wrappedCmd
    
    def createScript(cmd):
        useShell =fabric.state.env.shell
        to = 30*60 # readline timeout 8 hours
        #write header:
        s = '#!/usr/bin/python
    '
        s+= 'import sys
    '
        s+= 'from time import sleep
    '
        s+= 'import pexpect
    '
        #write expectation list:
        s+= 'expectations=['
        for e in fabric.state.env.expectations:
            s+= '"{0}",'.format(e[0])
        s+= ']
    '
        #start
        spwnTem = """child = pexpect.spawn("""{shellPrefix}{shell} "{cmd}" """,timeout={to})
    """
        s+= spwnTem.format(shell=useShell,cmd=cmd,to=to,shellPrefix=('' if useShell.startswith('/') else '/bin/'))
        s+= "child.logfile = sys.stdout
    "
        s+= "while True:
    "
        s+= "	try:
    "
        s+= "		i = child.expect(expectations)
    "
        i = 0
        for e in fabric.state.env.expectations:
            ifkeyw = 'if' if i == 0 else 'elif'
            s+= "		{0} i == {1}:
    ".format(ifkeyw,i)
            s+= "			child.sendline('{0}')
    ".format(e[1])
            s+= "			expectations[i]="__MANGLE__"
    
    "
            if len(e)>2:
                s+= "			sleep({0})
    ".format(e[2])
                s+= "			print('Exiting fexpect for expected exit.')
    "
                s+= '			break
    '
            i += 1
        s+= '	except pexpect.EOF:
    '
        s+= "		print('Exiting fexpect for EOF.')
    "
        s+= '		break
    '
        s+= '
    '
        return s
  • 相关阅读:
    Java线上应用故障排查之一:高CPU占用【转】
    JAVA 之 Tomcat知识框架【转】
    FileZilla 配置备份与还原【转】
    linux删除第几天日志【原创】
    sar命令使用【转】
    Mysql Group Replication 简介及单主模式组复制配置【转】
    grep 中的正则表达式【转】
    java程序out of memory【转】
    Java笔记18:JUnit单元测试
    Java笔记17:导出可执行jar包
  • 原文地址:https://www.cnblogs.com/husbandmen/p/12360541.html
Copyright © 2020-2023  润新知