背景
今天的运维大哥又双叒叕遇见的新的难题,老板叫他把几台服务器的某个日志文件夹的文件搞下来进行备份!并且更新一个配置文件。这次大哥有经验了,又再一次打开csdn!果然,天不负大哥,又一篇名为《Python搞定繁琐运维之批量上传下载文件》的文章吸引住了大哥。。。
(这个小故事接着昨天《Python搞定繁琐运维之批量执行Linux命令》文章的背景小故事哈,为的是引出今天的主题哈哈)
一、思路
还是老样子的阿,要批量上传下载文件,需要实现多个SFTP连接,然后让服务器进行上传下载操作。
二、实现
1.实现SFTP连接,这里还是延续昨天使用的paramiko模块,里面包含了SSHClient与SFTPClient两大类。SSHClient里面有一个open_sftp()方法可以用当前连接创建一个SFTPClient对象。因为我是个懒人!所以就选用这个方法哈。所以可以用昨天的代码进行修改的哈哈哈。因此首先创建多个Sftp连接
import paramiko #主要用于SSHSFTP操作 模块介绍使用方法参考https://www.cnblogs.com/xiao-apple36/p/9144092.html
def SSHLinux(ip,port,username,password,num): #程序SSH连接函数,也是本程序核心方法
a=[]
b=[]
c=[]
d=[]
e=[]
aa=[]
for i in range(num):
a.append('client' + str(i))
b.append('stdin' + str(i))
c.append('stdout' + str(i))
d.append('stderr' + str(i))
e.append('sftp' + str(i))
a[i] = paramiko.SSHClient() #创建num个连接对象
# client2 = paramiko.SSHClient()
a[i].set_missing_host_key_policy(paramiko.AutoAddPolicy) #添加num个主机名及主机密钥到本地HostKeys对象
# client2.set_missing_host_key_policy(paramiko.AutoAddPolicy)
try:
a[i].connect(hostname=ip[i],port=port[i],username=username[i],password=password[i]) #num个连接
# client2.connect(hostname=ip[1],port=port[1],username=username[1],password=password[1])
e[i] = a[i].open_sftp() #创建num个SFTP连接对象
print(f'主机{ip[i]}连接成功!')
except:
print(f'主机{ip[i]}连接失败,请确认输入信息!')
exit()
def main(): #运行函数,可以把批量ip端口账号密码对应的写入列表,然后把输入删掉运行
ip=[]
port=[]
username=[]
password = []
num = int(input('输入要进行SSH连接主机个数:'))
num2 = num
while num > 0:
a = input('输入ip:')
ip.append(a)
b = input('输入端口:')
port.append(b)
c = input('输入用户名:')
username.append(c)
d = input('输入密码:')
password.append(d)
num = num - 1
SSHLinux(ip,port,username,password,num2)
if __name__ == '__main__': #程序运行入口
main()
效果:
2.批量执行上传下载。当创建好SFTP对象后,上传下载只需要两个函数,分别是.get(远程地址,本地地址)#下载操作与.put(本地地址,远程地址)#上传操作。但是这两个方法只能上传或下载到精确文件,并且两个参数也必须包含文件的名字,但这样多不方便阿,我要下载日志文件夹里面的所有日志文件呢!那这里我们可以动下小心思,使用.listdir(path)方法遍历出path目录的所有文件名,然后再循环到下载操作里面,实现下载文件夹。因此可以用这两个方法实现很多种不同的需求,本文只是其中一种,要实现其他效果可以按照自己需求修改代码。
那就贴出完整代码啦:
import paramiko #主要用于SSHSFTP操作 模块介绍使用方法参考https://www.cnblogs.com/xiao-apple36/p/9144092.html
def SSHLinux(ip,port,username,password,num): #程序SSH连接函数,也是本程序核心方法
a=[]
b=[]
c=[]
d=[]
e=[]
aa=[]
num2 = num
ln = 0
for i in range(num):
a.append('client' + str(i))
b.append('stdin' + str(i))
c.append('stdout' + str(i))
d.append('stderr' + str(i))
e.append('sftp' + str(i))
a[i] = paramiko.SSHClient() #创建num个SSH连接对象
# client2 = paramiko.SSHClient()
a[i].set_missing_host_key_policy(paramiko.AutoAddPolicy) #添加num个主机名及主机密钥到本地HostKeys对象
# client2.set_missing_host_key_policy(paramiko.AutoAddPolicy)
try:
a[i].connect(hostname=ip[i],port=port[i],username=username[i],password=password[i]) #num个连接
# client2.connect(hostname=ip[1],port=port[1],username=username[1],password=password[1])
e[i] = a[i].open_sftp() #创建num个SFTP连接对象
print(f'主机{ip[i]}连接成功!')
except:
print(f'主机{ip[i]}连接失败,请确认输入信息!')
exit()
while True:
dowhat = int(input("上传文件(1)下载文件夹(2)退出(3):"))
if (dowhat==1):
a = input("需要上传的本地文件地址(包含文件名):")
b = input("上传到服务器地址(包含文件名):")
for i in range(num):
try :
e[i].put(a,b) #上传操作 这里只支持上传文件,还没做到上传文件夹,如果想要上传文件夹,参考下面下载的方法修改代码
print(f'{ip[i]}文件{a}上传成功,上传地址{b}')
except:
print(f'{ip[i]}文件{a}上传失败,请确认路径')
if (dowhat == 2):
fwqdz = input("服务器要下载文件的地址(文件夹路径):")
for i in range(num):
while num2 > 0:
bddz = input(f'输入{ip[ln]}文件存到本地的目录:')
aa.append(bddz)
ln = ln + 1
num2 = num2 - 1
try :
for file in e[i].listdir(fwqdz): #使用.listdir(path)方法遍历出path目录的所有文件名,然后再循环到下载操作里面,实现下载文件夹
g = fwqdz + file
h = aa[i] + file
e[i].get(g,h) #下载操作 这里只支持下载某个文件夹里面的所有文件,
print(f'{ip[i]}文件{g}下载成功,地址为{h}')
except:
print(f'{ip[i]}文件{g}下载失败,请确认路径')
aa.clear()
num2 = num
ln = 0
if (dowhat == 3):
break
exit()
def main(): #运行函数,可以把批量ip端口账号密码对应的写入列表,然后把输入删掉运行
ip=[]
port=[]
username=[]
password = []
num = int(input('输入要进行SSH连接主机个数:'))
num2 = num
while num > 0:
a = input('输入ip:')
ip.append(a)
b = input('输入端口:')
port.append(b)
c = input('输入用户名:')
username.append(c)
d = input('输入密码:')
password.append(d)
num = num - 1
SSHLinux(ip,port,username,password,num2)
if __name__ == '__main__': #程序运行入口
main()
完整效果:
(上传到远程服务器这里test.txt的文件名字可以更改)
结束
今天写这个脚本的时候突然意识到,脚本应该是怎么用的舒服怎么来,还有就是如果把脚本做到面面俱到这就不叫脚本了,应该叫工具了哈哈,所以,有需求->解决需求才是脚本的精髓。
如果有什么错误的地方或者有什么建议恳请大家指出哈。