6-10 5 views
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Author : Eric Winn # @Email : eng.eric.winn@gmail.com # @Time : 19-5-30 下午1:32 # @Version : 1.0 # @File : sftp # @Software : PyCharm import os import time import paramiko from stat import S_ISDIR from common.utils import get_logger logger = get_logger() BUF_SIZE = 32 * 1024 class SSH(object): def __init__(self, asset, timeout=30): ''' 请将asset封装成一个namedtuple :param asset: :param timeout: ''' self.ip = asset.ip self.username = asset.username self.password = asset.password self.timeout = timeout self.chan = '' self.sftp = '' # 如果只是做文件的上传和下载,ssh可以不需要 self.ssh = paramiko.SSHClient() self.Transport = paramiko.Transport(sock=(self.ip, 22)) # 连接远程主机 def connect(self): logger.debug('Connecting to {}'.format(self.ip)) self.Transport.connect(username=self.username, password=self.password) self.sftp = paramiko.SFTPClient.from_transport(self.Transport) # 如果只是做文件的上传和下载,ssh可以不需要 self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(self.ip, port=22, username=self.username, password=self.password, timeout=6) self.chan = self.ssh.invoke_shell(term='xterm') # 断开连接 def close(self): logger.debug('Disconnecting to {}'.format(self.ip)) self.Transport.close() self.chan.close() self.ssh.close() # 重启服务 def service_restart(self, service_name): logger.debug('开始重启{}'.format(service_name)) self.command('systemctl restart {}'.format(service_name)) # 发送命令 def command(self, cmd): self.chan.send('{}\n'.format(cmd)) time.sleep(5) def get_msg(self): msg = self.chan.recv(BUF_SIZE) logger.debug(msg.decode('utf-8')) # 递归创建目录 def mkdir(self, remote_dir): self.command('mkdir -p {}'.format(remote_dir)) time.sleep(0.3) # 获取目录下所有的文件 def __get_all_files_from_remote_dir(self, remote_dir): all_files = list() if remote_dir[-1] == '/': remote_dir = remote_dir[0:-1] # 获取当前指定目录下的所有目录及文件,包含属性值 files = self.sftp.listdir_attr(remote_dir) for x in files: # remote_dir目录中每一个文件或目录的完整路径 filename = remote_dir + '/' + x.filename # 如果是目录,则递归处理该目录 if S_ISDIR(x.st_mode): all_files.extend(self.__get_all_files_from_remote_dir(filename)) else: all_files.append(filename) return all_files # 获取本地指定目录下的所有文件 def __get_all_files_from_local_dir(self, local_dir): # 保存所有文件的列表 all_files = list() # 获取当前指定目录下的所有目录及文件,包含属性值 files = os.listdir(local_dir) for x in files: # local_dir目录中每一个文件或目录的完整路径 filename = os.path.join(local_dir, x) # 如果是目录,则递归处理该目录 if os.path.isdir(filename): all_files.extend(self.__get_all_files_from_local_dir(filename)) else: all_files.append(filename) return all_files # get单个文件 def get_file(self, remote_file, local_file): logger.debug('') # 获取remote_file的属性值 r_file = self.sftp.lstat(remote_file) if S_ISDIR(r_file.st_mode): logger.debug('{} is a directory'.format(remote_file)) return if os.path.isdir(local_file): filename = remote_file.split('/')[-1] local_file = os.path.join(local_file, filename) logger.debug('file {} is downloading...'.format(remote_file)) self.sftp.get(remote_file, local_file) # put单个文件 def put_file(self, local_file, remote_file): r_file = self.sftp.lstat(remote_file) if S_ISDIR(r_file.st_mode): filename = local_file.split('/')[-1] remote_file = os.path.join(remote_file, filename) if os.path.isdir(local_file): logger.debug('{} is a directory'.format(local_file)) return logger.debug('file {} is uploading...'.format(local_file)) self.sftp.put(local_file, remote_file) # get 目录 def get_dir(self, remote_dir, local_dir): all_files = self.__get_all_files_from_remote_dir(remote_dir) for x in all_files: filename = x.split('/')[-1] r_d = os.path.dirname(x).split('/') base_d = remote_dir.split('/') l_d = os.path.join(local_dir, '/'.join(list(set(r_d) ^ set(base_d)))) if not os.path.exists(l_d): os.mkdir(l_d) local_filename = os.path.join(l_d, filename) logger.debug('file {} is downloading...'.format(filename)) self.sftp.get(x, local_filename) # put目录 def put_dir(self, local_dir, remote_dir): # 去掉路径字符穿最后的字符'/',如果有的话 if remote_dir[-1] == '/': remote_dir = remote_dir[0:-1] # 获取本地指定目录及其子目录下的所有文件 all_files = self.__get_all_files_from_local_dir(local_dir) # 依次put每一个文件 for x in all_files: filename = os.path.split(x)[-1] if os.path.isdir(x): l_d = x.split('/') else: l_d = os.path.dirname(x).split('/') base_d = local_dir.split('/') r_dir = os.path.join(remote_dir, '/'.join(list(set(l_d) ^ set(base_d)))) try: self.sftp.lstat(r_dir) except Exception as e: self.mkdir(r_dir) if os.path.isdir(x): continue remote_filename = os.path.join(r_dir, filename) logger.debug('file {} is uploading...'.format(x)) self.sftp.put(x, remote_filename) |
如果想赏钱,可以用微信扫描下面的二维码,一来能刺激我写博客的欲望,二来好维护云主机的费用; 另外再次标注博客原地址 itnotebooks.com 感谢!