paramiko 实现Linux文件操作

=
# --*-- coding:utf-8 --*--
import os
import sys
import paramiko

class SSHManager:
    def __init__(self, host, user, password):
        self.host = host
        self.user = user
        self.password = password
        self.ssh = None
        self.sftp = None
        self.sftp_connect()
        self.ssh_connect()

    def __del__(self):
        if self.ssh:
            self.ssh.close()
        if self.sftp:
            self.sftp.close()

    def sftp_connect(self):
        """sftp连接"""
        try:
            transport = paramiko.Transport((self.host, 22))
            transport.connect(username=self.user, password=self.password)
            self.sftp = paramiko.SFTPClient.from_transport(transport)
        except Exception as e:
            raise RuntimeError("sftp connect failed {}".format(str(e)))

    def ssh_connect(self):
        """ssh连接"""
        try:
            # 创建ssh对象
            self.ssh = paramiko.SSHClient()
            # 允许连接不在know_hosts文件中的主机
            self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # 连接服务器
            self.ssh.connect(hostname=self.host,
                              port=22,
                              username=self.user,
                              password=self.password,
                              timeout=5)
        except Exception:
            raise RuntimeError("ssh connected to [host:{}, user:{}, password:{}] failed".format(self.host, self.user, self.password))

    # def exec_command(self, cmd):
    #     """
    #     通过ssh执行远程命令
    #     :param cmd:
    #     :return:
    #     """
    #     try:
    #         stdin, stdout, stderr = self.ssh.exec_command(cmd)
    #         return stdout.read().decode("utf-8")
    #     except Exception as e:
    #         raise RuntimeError('Exec command {} failed'.format(str(cmd)))
    #
    # def ssh_exec_cmd(self, cmd, path='~/1'):
    #     """
    #     通过ssh连接到远程服务器,执行给定的命令
    #     :param cmd: 执行的命令
    #     :param path: 命令执行的目录
    #     :return: 返回结果
    #     """
    #     try:
    #         result = self.exec_command('cd ' + path + ';' + cmd)
    #         return result
    #     except Exception as e:
    #         raise RuntimeError('Exec command {} failed'.format(str(cmd)))

    def list_directory(self,remote_directory_path):
        """
            列出指定目录下的文件和目录
        :param remote_path: 远程目录路径
        :return:
        """
        try:
            # 进入该目录
            self.sftp.chdir(remote_directory_path)
            result = []
            directory_data = []
            file_data = []
            cmd = 'ls --file-type ' + remote_directory_path
            stdin, stdout, stderr = self.ssh.exec_command(cmd)
            data = stdout.read().decode().split('\n')
            for file_or_directory in data:
                # 去除""
                if file_or_directory :
                    # 如果后缀有/,则是目录
                    if file_or_directory[-1] == "/":
                        directory_data.append(file_or_directory[:-1])
                    # 否则为文件
                    else:
                        file_data.append(file_or_directory)
            for directory in directory_data:
                result.append({"name":directory,"type":"directory"})
            for file in file_data:
                result.append({"name": file,"type":"file"})
            return result
        except FileNotFoundError as e:
            raise  FileNotFoundError("No such file or directory:{}".format(remote_directory_path))
        except Exception as e:
            raise Exception("List directory {} failed:{}".format(remote_directory_path,str(e)))



    def rename(self,before_remote_path,now_remote_path):
        """
             重命名文件或者文件名
        :param before_remote_path:  改名之前的远程文件或目录路径
        :param now_remote_path:     改名之后的远程文件或目录路径
        :return:
        """
        try:
            self.sftp.rename(before_remote_path,now_remote_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{}".format(before_remote_path))
        except Exception as e:
            raise Exception("Rename {} failed:{}".format(before_remote_path,str(e)))

    def create_file(self,remote_file_path):
        """
            创建文件
        :param remote_file_path: 远程文件路径
        :return:
        """
        # TODO 待完成


    def remove_file(self,remote_file_path):
        """
            删除文件
        :param remote_file_path: 远程文件路径
        :return:
        """
        try:
            self.sftp.remove(remote_file_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{}".format(remote_file_path))
        except OSError as e:
            raise  OSError("Currently deleting directory, should be a file:{}".format(remote_file_path))
        except Exception as e:
            raise Exception("Remove file {} failed:{}".format(remote_file_path,str(e)))


    def create_directory(self,remote_directory_path):
        """
            创建目录
        :param remote_directory_path: 远程目录路径
        :return:
        """
        try:
            self.sftp.mkdir(remote_directory_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{}".format(remote_directory_path))
        except Exception as e:
            raise Exception("Create directory {} failed:{}".format(remote_directory_path,str(e)))

    def remove_directory(self,remote_directory_path):
        """
            删除目录
        :param remote_directory_path: 远程目录路径
        :return:
        """
        try:
            self.sftp.rmdir(remote_directory_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{}".format(remote_directory_path))
        except Exception as e:
            raise Exception("Remove directory {} failed:{}".format(remote_directory_path,str(e)))




    def download_file(self, local_file_path,remote_file_path):
        """
           下载文件
            注:
                下载和上传文件的参数顺序相反,不一样
        :param remote_file_path: 远程文件路径
        :param local_file_path:  本地文件路径
        :return:
        """
        try:
            self.sftp.get(remote_file_path,local_file_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{} or {}".format(local_file_path,remote_file_path))
        except Exception as e:
            raise Exception("Download file {} failed:{}".format(remote_file_path,str(e)))

    def upload_file(self, local_file_path, remote_file_path):
        """
          上传文件
        :param local_file_path: 本地文件路径
        :param remote_file_path: 远程文件路径
        :return:
        """
        try:
            self.sftp.put(local_file_path, remote_file_path)
        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{} or {}".format(local_file_path, remote_file_path))
        except Exception as e:
            raise Exception("Upload file {} failed:{}".format(local_file_path,str(e)))

    def download_directory(self,init_local_directory_path,init_remote_directory_path,current_remote_directory_path):
        """
             下载文件夹
        :param init_local_directory_path:  初始本地文件夹  (!!!初始本地文件夹让前端切割加上初始远程文件夹名称,最后结尾都不要\)
        :param init_remote_directory_path:  初始远程文件夹
        :param current_remote_directory_path:  当前远程文件夹
        :return:
        """
        try:
            # 没有最后面的/ 加上
            if len(init_local_directory_path) > 0 and init_local_directory_path[-1] != '/':
                init_local_directory_path += '/'
            if len(init_remote_directory_path) > 0 and init_remote_directory_path[-1] != '/':
                init_remote_directory_path += '/'
            if len(current_remote_directory_path) > 0 and current_remote_directory_path[-1] != '/':
                current_remote_directory_path += '/'
            list_dir =  self.list_remote_dir(current_remote_directory_path)
            # 如果是文件夹,且其下没有文件,那么也要创建该文件夹
            if list_dir == [""]:
                save_path = init_local_directory_path + current_remote_directory_path.split(init_remote_directory_path)[-1]
                if not os.path.exists(save_path):
                    os.makedirs(save_path)
            # 去掉'',linux获取目录文件,最后总是有一个''
            nodes = list(item for item in list_dir if len(item) > 0)
            for node in nodes:
                # 如果该节点是文件夹,继续遍历
                if node.endswith('/'):
                    self.download_directory(init_local_directory_path,init_remote_directory_path,current_remote_directory_path+ node)
                else:
                    # 如果该节点是文件  则保存该文件
                    self.save_file(init_local_directory_path,init_remote_directory_path,current_remote_directory_path,node)
        except Exception as e:
            raise Exception("Download directory {} failed:{}".format(init_remote_directory_path, str(e)))

    def list_remote_dir(self, remote_directory_path):
        """
            获取远程服务器指定目录下的文件(仅供download_directory函数使用)
        :param remote_directory_path:  远程路径
        :return:
        """
        cmd = 'ls --file-type ' + remote_directory_path
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        result = stdout.read()
        return result.decode().split('\n')

    def save_file(self,init_local_directory_path,init_remote_directory_path,current_remote_directory_path, name):
        """
            保存文件(仅供download_directory函数使用)
        :param init_local_directory_path: 初始保存的本地文件夹路径
        :param init_remote_directory_path: 初始下载的远程文件夹路径
        :param current_remote_directory_path: 当前远程文件夹路径
        :param name: 当前远程文件夹下的文件名
        :return:
        """
        try:
            # 本地保存路径
            save_path = init_local_directory_path + current_remote_directory_path.split(init_remote_directory_path)[-1]
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            save_file_path = save_path + name
            # 查看远程文件内容
            cmd = 'cat ' + current_remote_directory_path + name
            stdin, stdout, stderr = self.ssh.exec_command(cmd)
            result = stdout.read()
            if not result:
                return
            # 保存文件
            with open(save_file_path, 'wb+') as fd:
                fd.write(result)
        except:
            print('save path:' + save_file_path)
            print("Unexpected error:", sys.exc_info()[0])



    def upload_directory(self, local_directory_path, remote_directory_path):
        """
            上传文件夹
        :param local_directory_path:  本地文件夹路径
        :param remote_directory_path:  远程文件夹路径
        :return:
        """
        try:
            self.sftp.chdir(remote_directory_path)
            project = local_directory_path.split("\\")[-1]
            current_dir = ''
            for root, dirs, files in os.walk(local_directory_path):
                # 创建目录
                create_remote_dirs = root.split(local_directory_path)[-1].split("\\") # 创建远程目录的后缀 \a\c\d
                create_remote_dir_path = remote_directory_path + "/" + project # 创建远程目录路径
                for create_remote_dir in create_remote_dirs:
                    if create_remote_dir:
                        create_remote_dir_path = create_remote_dir_path + "/" + create_remote_dir
                # 进入目录,如果报错就创建该目录
                try:
                    self.sftp.chdir(create_remote_dir_path)
                except  Exception as e:
                    self.sftp.mkdir(create_remote_dir_path)

                # 上传文件
                for file in files:
                    if root.split('\\')[-1] not in current_dir:
                        current_dir = '{}/{}'.format(current_dir, root.split('\\')[-1])
                        try:
                            # 切换到目录
                            self.sftp.chdir('{}{}'.format(remote_directory_path, current_dir))
                            # 上传文件
                            self.sftp.put(os.path.join(root, file), file)
                        except:
                            self.sftp.mkdir(root.split('\\')[-1])
                            self.sftp.chdir('{}{}'.format(remote_directory_path, current_dir))
                            self.sftp.put(os.path.join(root, file), file)
                    else:
                        self.sftp.chdir('{}{}'.format(remote_directory_path, current_dir))
                        self.sftp.put(os.path.join(root, file), file)

        except FileNotFoundError as e:
            raise FileNotFoundError("No such file or directory:{} or {}".format(local_directory_path, remote_directory_path))
        except Exception as e:
            raise Exception("Upload directory {} failed:{}".format(local_directory_path, str(e)))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值