Python 连接Linux服务器完成上传下载和执行命令及查询目录下的文件

Python 连接Linux服务器完成上传下载和执行命令及查询目录下的文件

记录一些用于连接linux获取远端文件或者上传文件的小工具,另外还有执行shell命令和查找linux目录下文件是否存在

# -*- coding: utf-8 -*-
"""
@Time    : 2021/7/22 10:31
@Author  : chenhj
@File    : sshclient.py
@Software: PyCharm 
@Comment : 
"""
import osfrom stat 
import S_ISDIR
import re
import paramikofrom paramiko.ssh_exception 
import NoValidConnectionsError, AuthenticationException, SSHException

class SshRemoteConnection:
	def __init__(self, hostname, port, user, password):
		self.hostname = hostname
		self.port = port
		self.user = user
		self.password = password
	def do_connect(self, conn):    
		"""创建连接"""    
		if conn == "SSHClient":        
			client = paramiko.SSHClient()        
			client.set_missing_host_key_policy(paramiko.AutoAddPolicy())        
			try:            
				client.connect(hostname=self.hostname,port=self.port,username=self.user,password=self.password)
				print("正在连接 {}".format(self.hostname).center(100, '*'))       
			except NoValidConnectionsError as e:            
				print(f"连接失败:{e}".center(100, '*'))        
			except AuthenticationException as e:            
				print(f"密码错误:{e}".center(100, '*'))        
			return client    
		elif conn == "Transport":        
			# 获取Transport实例        
			tran = paramiko.Transport(self.hostname, int(self.port))        
			try:            
			# 连接SSH服务端            
				tran.connect(username=self.user, password=self.password)        
			except SSHException as e:            
				print(f'连接失败:{e}'.center(100, '*'))        
			return tran
	def do_cmd(self, cmd):    
		"""执行shell命令,多条命令以分号‘;’隔开"""    
		# 连接    
		conn = self.do_connect('SSHClient')    
		# 执行操作    
		stdin, stdout, stderr = conn.exec_command(cmd, get_pty=True)    
		# 获取命令执行的结果    
		res, err = stdout.read().decode('utf-8'), stderr.read().decode('utf-8')    
		result = res if res else err    
		print('执行成功'.center(100, '*'))    
		print(result)    
		return result
	def do_put_file(self, local_path, remote_path):    
		"""上传单个文件"""
		print('正在上传文件...'.center(100, '*'))
		conn = self.do_connect('Transport')
		sftp = paramiko.SFTPClient.from_transport(conn)
		try:
			sftp.put(local_path, remotepath=remote_path) 
			print(f'{local_path}文件上传到{self.hostname}主机的{remote_path}')
		except SSHException as e:        
			print(f'上传失败:{e}'.center(100, '*'))    
			conn.close()
	def __get_all_local_files(self, local_dir):    
		"""获取需要批量上传目录下的所有文件"""    
		all_files = list()    
		files = os.listdir(local_dir)    
		for i in files:       
			local_filename = os.path.join(local_dir, i)        
			if os.path.isdir(i):            
				all_files.extend(self.__get_all_local_files(local_filename))        
			else:            
				all_files.append(local_filename)    
			return all_files
	def do_put_all_files(self, local_path, remote_path):    
		"""批量上传所有文件"""    
		print('正在上传文件...'.center(100, '*'))    
		conn = self.do_connect('Transport')    
		sftp = paramiko.SFTPClient.from_transport(conn)    
		# 去掉路径字符串最后的字符'/',如果有的话    
		if remote_path[-1] == '/':        
		remote_path = remote_path[0:-1]    
		# 获取本地目录下的所有文件    
		all_files = self.__get_all_local_files(local_path)    
		try:        
			for file in all_files:            
				local_filename = os.path.split(file)[-1]            
				remote_filename = remote_path + '/' + local_filename            
				print('{} 文件正在传输中...'.center(100, '*').format(remote_filename))            
				sftp.put(file, remote_filename)            
				print('文件传输成功...'.center(100, '*').format(remote_filename))    
		except SSHException as e:        
			print(f'上传失败:{e}'.center(100, '*'))    
		conn.close()
	def do_get_file(self, remote_path, local_path):    
		"""下载文件"""    
		print('正在下载文件...'.center(100, '*'))    
		conn = self.do_connect('Transport')    
		sftp = paramiko.SFTPClient.from_transport(conn)    
		try:        
			sftp.get(remotepath=remote_path, localpath=local_path)        
			print(f'{remote_path}文件从{self.hostname}主机下载到{local_path}成功')    
		except SSHException as e:        
			print(f'下载失败:{e}'.center(100, '*'))    
		conn.close()
	def __get_all_remote_files(self, sftp, remote_dir):    
		"""获取需要批量下载目录下的所有文件"""    
		all_files = list()    
		# 去掉路径字符串最后的字符'/',如果有的话    
		if remote_dir[-1] == '/':        
		remote_path = remote_dir[0:-1]    
		files = sftp.listdir_attr(remote_dir)    
		for i in files:
			remote_filename = remote_dir + '/' + i.filename        
			# 判断是不是路径,是路径的话,遍历路径下的文件        
			if S_ISDIR(i.st_mode): 
			all_files.extend(self.__get_all_remote_files(sftp, remote_filename))        
			else:            
				all_files.append(remote_filename)    
				return all_files
	def do_get_all_files(self, remote_path, local_path):   
		"""批量下载目录下所有文件"""    
		print('正在批量下载文件...'.center(100, '*'))    
		conn = self.do_connect('Transport')    
		sftp = paramiko.SFTPClient.from_transport(conn)    
		all_files = self.__get_all_remote_files(sftp, remote_path)    
		# 依次下载每一个文件    
		for file in all_files:        
			filename = file.split('/')[-1]        
			local_filename = os.path.join(local_path, filename)        
			print(f'{filename} 文件正在传输中...'.center(100, '*'))        
			sftp.get(file, local_filename)    
		print('传输完成...'.center(100, '*'))    
		conn.close()
	def do_search_file(self, check_dir, checkup=None, fuzzy=True):    
		"""校验目录下的文件,默认模糊查询fuzzy=True,匹配忽略大小写"""    
		res = self.do_cmd(f'cd {check_dir};ls')    
		dir_list = [i for i in res.split('\r\n') if i != '']    
		num = 0    
		all_file = []    
		print('正在获取检索结果...'.center(100, '*'))    
		for file in dir_list:        
			if fuzzy:            
				ma = re.compile(f'{checkup}', flags=re.IGNORECASE).findall(f'{file}')        
			else:            
				ma = re.compile(f'{checkup}').findall(f'{file}')        
			if ma:            
				print(file)            
				all_file.append(file)            
				num += 1       
			else:            
				print('...')    
		print(f'检索完毕...找到{num}个结果'.center(100, '*'))    
		return all_file
	def do_review_contents(self):    
		pass


	if __name__ == "__main__":    
		s = SshRemoteConnection('99.99.45.123', 22, 'user', "123!@#")    
		s.do_cmd('pwd;ls -l')    
		localpath = 'D:\\00_data\\test'    
		filename = '111.DAT'    
		remotepath = '/data/20210719'    
		remote_filename = filename    
		# s.do_put_all_files(f'{localpath}', f'{remotepath}')    
		# s.do_put_file(f'{localpath}\\{filename}', f'{remotepath}\\{remote_filename}')    
		s.do_get_all_files(remotepath, localpath)    
		s.do_search_file('/data/20210719', 'txt')

你可能感兴趣的:(Python,python)