python使用paramiko之连接、发送命令(1)

0.前言

之前部署环境,一个命令一个命令的敲;
然后是写shell脚本——但是我不会在执行shell脚本的时候输入需要的信息——要不然命令本身不支持要不然需要装插件
然后我想,能不能用py搞一个一键自动部署!
然后百度(谷歌除了镜像,还有真正的谷歌么?)发现了paramiko,他可以让你的命令在需要输入信息的时候,自动输入信息,最让人兴奋的是,他可以根据你之前命令的返回值,进行if判断,发送新的需要输入的信息,比如是否输入‘yes’,这是一个可能选项。
——一切皆有可能,亚斯蒂大帝如是说。

1.连接he断开连接

两种连接方式,paramiko.SSHClient()和paramiko.Transport()我选择后一种。第一种cd后会回到连接的初始状态,第二种不会。

#初始化
def __init__(self):
    self._transport = None
    self._channel = None
#连接
#info是list,【"某IP地址",port,"用户名", "口令"】
def transport_connect(self,info):
    self._transport = paramiko.Transport((info[0], int(info[1])))  # 建立一个加密的管道
    self._transport.start_client()
    # 用户名密码方式
    self._transport.auth_password(info[2], info[3])
    # 打开一个通道
    self._channel = self._transport.open_session()
    self._channel.settimeout(7200)
    # 获取一个终端
    self._channel.get_pty()
    # 激活器
    self._channel.invoke_shell()
    return self._transport,self._channel
#断开连接
def transport_disconnect(self):
    if self._channel:
        self._channel.close()
    if self._transport:
        self._transport.close()

2.发送命令

打开我的linux,执行命令开始是:[root@emsmain version]#
执行完以后,也是这种。
那么在我看来,发送命令有两种状态,一种是最后显示 [.*]# 命令完全执行完毕,另一种是命令在执行中,需要你输入一些参数信息。
所以发送命令也分为两种:

命令会执行完,参数cmd是命令,末尾不需要带回车\r,
返回值是这个命令的所有执行信息,
到时候可以根据里面的信息判断需不需要再次发送命令
def send(self,cmd,channel):
    commod = cmd
    cmd += '\r'
    # 通过命令执行提示符来判断命令是否执行完成
    p = re.compile(r']#')
    result = ''
    # 发送要执行的命令
    channel.send(cmd)
    # 回显很长的命令可能执行较久,通过循环分批次取回回显
    while True:
        sleep(0.2)
        ret = channel.recv(65535)
        ret = ret.decode('utf-8')
        result += ret
        print ret
        if p.search(ret):
            break
    # print(commod+'结束')
    return result

命令执行到一半需要输入信息,输入完成后继续
def sendMiddle(self,cmd,channel):
    commod = cmd
    cmd += '\r'
    # 通过命令执行提示符来判断命令是否执行完成
    # 发送要执行的命令
    channel.send(cmd)
    # 回显很长的命令可能执行较久,通过循环分批次取回回显
    sleep(0.5)
    ret = channel.recv(65535)
    ret = ret.decode('utf-8')
    # printLine(commod + '结束')
    print ret
    return ret

(8-31更新)今天突然想到了一个问题,万一linux的字符编码不是utf-8咋整?会报错停止啊。我要不先获取一下?可是我都发不出去echo $LANG;恩,处理异常吧。

        try:
            ret = ret.decode('utf-8')
        except:
            ret = ret.decode('gbk')

不得不说,老子太他喵的哼哼哼了!

3.测试

用scp测试

info = ['ip','22','root','passwd']
#类名是operator_shell_command()
transport = operator_shell_command()
channel = transport.transport_connect(info)[1]
transport.send('cd /home/version',channel)
transport.send('rm -f or.sh',channel)
transport.send('ls -l',channel)
str1 = transport.sendMiddle('scp root@ip:/home/version/or.sh  /home/version',channel)
#可能会出现的用if判断
if ('Are you sure you want to continue connecting (yes/no)' in str1):
    transport.sendMiddle('yes',channel)
str1 = transport.sendMiddle('passwd',channel)
if('Permission denied, please try again'  in  str1):
    str1 = transport.sendMiddle('passwd',channel)
transport.send('ls -l', channel)

部分运行结果

[root@emsmain version]#
n #这个可能是scp的命令,但是不知道为什么没有打印完整
Authorized uses only. All activity may be monitored and reported.
[email protected]’s password:

or.sh 100% 594 0.6KB/s 00:00
[root@emsmain version]#
ls -l
total 2773832

4.完结撒花——欢呼吧,为了蓝色的天空!

参考网页:
https://www.cnblogs.com/haigege/p/5513759.html
使用paramiko执行远程linux主机命令
https://www.cnblogs.com/haigege/p/5517422.html
使用paramiko的SFTP get或put整个目录
当然还有paramiko的官网,用谷歌翻译看。。。

猜你喜欢

转载自blog.csdn.net/qq_29778641/article/details/82186438