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.
root@10.92.249.26’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的官网,用谷歌翻译看。。。