linux中使用expect完成自动化登陆等操作非常方便,但是python调用linux执行expect的相关指导非常少。

下面写了一个python调用expect脚本完成主机向其他不同主机间拷贝和自动化免密码ssh登陆的实现。

#!/usr/bin/python
#coding:utf-8
import sys,re
import os
import subprocess

#scp file to remote node.
def scpFileToRemoteNode(user,ip,password,fileName,filePath,port=22):
    '''
    拷贝软件包到远程节点,默认使用root用户22号端口传输
    :param ip:
    :param password:
    :param sourceFileName:
    :return: 0 表示执行成功
    '''
    SCP_CMD_BASE = r"""
            expect -c "
            set timeout 10 ;
            spawn scp -P {port} {filePath}/{{filename}} {username}@{host}:{filePath}/{{filename}}  ;
            expect *assword* {{{{ send {password}\r }}}}  ;
            expect *\r ;
            expect \r ;
            expect eof
            "
    """.format(username=user,password=password,host=ip,filePath=filePath,port=port)
    SCP_CMD = SCP_CMD_BASE.format(filename = fileName)
    print "execute SCP_CMD:  ",SCP_CMD
    p  = subprocess.Popen( SCP_CMD , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    (output, err) = p.communicate()
    #status = os.system(SCP_CMD)
    print "execute SCP_CMD status: ",output
    return output

#ssh connect node ,then execute shell commands.
def sshCommandExecute(user,ip,password,command):
    '''
    使用ssh命令连接远程服务虚拟机,然后执行command命令,默认使用root用户
    :param user:默认使用root用户
    :param ip:
    :param paasword:
    :param command:
    :return:
    '''
    SSH_CMD=r"""
        expect -c "
        set timeout 10;
        spawn ssh {user}@{ip} ;
        expect {{
            \"*yes/no*\" {{ send "yes\r"; exp_continue }}
            \"*assword*\" {{ send {password}\r }}
        }} ;
        send \" {command} \r\";
        expect "]*"
        send \"exit\r\"
        "
    """.format(user=user,ip=ip,password=password,command=command)
    print "execute SSH_CMD:  ",SSH_CMD
    #status = os.system(SSH_CMD)
    p  = subprocess.Popen( SSH_CMD , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    (output, err) = p.communicate()
    print "execute SSH_CMD status: ",output
    return output





有相关需求的可以直接拿去用。 expect 语句是放在python原始字符串中传递的,脚本在原始字符串中涉及到语句转义和参数传递。 每一次send语句执行最好使用expect上一条指令已经执行完成。