• pysftp-tools


    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
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    import pysftp
    import paramiko
    import os
    import unittest
    import json
    import warnings
    warnings.filterwarnings("ignore")
     
    class SftpUtils(object):
        """
        cmd: execute shell command on  remote  linux server.
        exist_file : if remote path exists on remote return True ,else return False.
        exist_dir : if remote path exists on remote return True ,else return False.
        is_dir: if remote path is dir return True ,else return False.
        is_file : if remote path is file return True ,else return False.
        remove:  remove the remote file on remote linux .
        rm:  remove dir and all files/dir under remote dir and dir it self.
        mkdir: mkdir dir on remote linux but it parent dir must exists ,if it already exist delete remote dir exists first and mkdir remote dir .
        makedirs: mkdir the dir on remote linux , if it parent dir and dir self  not exists,
        it will mkdir parent dir and dir, else mkdir dir.
        get:  get remote linux  file  to local ,local filename  and remote filename must absolute filepath.
        put:  upload local file to remote linux local filename  and remote filename must absolute filepath.
        rename:
            rename a file or directory on the remote host
            :param str remote_src: the remote file/directory to rename
            :param str remote_dest: the remote file/directory to put it
        open: read remote file content and return readlines list
        cwd : cd  curdir to newdir
        getcwd: get remote linux cursor current dir path and return it
        chmod : change file r,w,x grants.
        chown: change file or dir owner
        opens: read and write  file on remote linux ,if remote file not exists it will create it first  when write .
        exists: if  dir or file exists on remote linux  return True ,else return  False .
        list_dir: query all files  under dir ,the same with shell ls -l -a dir/ .
        ger_recursive:
            recursive copy  remote files or dir under remote dir to localdir
     
     
        put_recursive: recursive copy  localdir's all file or dir under it to remote dir
        """
     
        def __init__(self, ip, port, user, pwd):
            self.ip = ip
            self.port = port
            self.user = user
            self.pwd = pwd
            self.sftp = self.sftp_client()
     
        def sftp_client(self):
            # https://pysftp.readthedocs.io/en/release_0.2.9/cookbook.html#pysftp-cnopts
            # private_key="/home/app/privatekey_file"
            cnopts = pysftp.CnOpts()
            cnopts.hostkeys = None
            sftp = pysftp.Connection(host=self.ip, username=self.user, password=self.pwd, port=self.port, cnopts=cnopts)
            return sftp
     
        def cmd(self, shell_cmd: str):
            """get stdout or err"""
     
            std = self.sftp.execute(shell_cmd)
            if std:
                readlines = ''
                for line in std:
                    readlines = readlines + line.decode("utf-8")
                return readlines
     
        def exists_file(self, filepath):
            try:
                self.sftp.stat(filepath)
            except Exception:
                return False
            else:
                return True
     
        def exists_dir(self, dirpath):
            try:
                self.sftp.stat(dirpath)
            except Exception:
                return False
            else:
                return True
     
        def is_dir(self, dirpath):
     
            return True if self.sftp.isdir(remotepath=dirpath) else False
     
        def is_file(self, filepath):
            return True if self.sftp.isfile(remotepath=filepath) else False
     
        def remove(self, filepath):
            """remove remote file"""
            if self.exists_file(filepath):
                self.sftp.remove(filepath)
            else:
                raise FileNotFoundError("%s file not find on remote ! " % filepath)
     
        def rm(self, dirpath):
            """ rmdir just delete  empty dirs  """
            if self.exists_dir(dirpath):
                files = self.sftp.listdir(dirpath)
                for file in files:
                    filepath = os.path.join(dirpath, file).replace("\",'/')
                    if self.is_dir(filepath):
                        self.rm(filepath)
                    else:
                        self.remove(filepath)
                self.sftp.rmdir(dirpath)
            else:
                raise FileNotFoundError("%s dir not find on remote !" % dirpath)
     
        def mkdir(self, remote_dir):
            """parent dir must exists"""
            if self.exists(remote_dir):
                self.rm(remote_dir)
                self.sftp.mkdir(remotepath=remote_dir)
            else:
                self.sftp.mkdir(remotepath=remote_dir)
     
        def mkdirs(self, remote_dir):
            """mkdir -p /usr/local/mkdir,it can create dir that parent dirs not exists,if exists,it can also create"""
            self.sftp.makedirs(remotedir=remote_dir)
     
        def get(self, remote_path, local_path):
            """sftp get,download """
            self.sftp.get(remotepath=remote_path, localpath=local_path, callback=None)
     
        def put(self, local_path, remote_path):
            """sftp put,upload """
            self.sftp.put(localpath=local_path, remotepath=remote_path)
     
        def rename(self, remote_path, new_name_path):
            """rename file or dir  on remote """
            self.sftp.rename(remote_src=remote_path, remote_dest=new_name_path)
     
        def open(self, remote_filepath, mode):
            """open 'r+' or 'r' file ,return str"""
            readlines = self.sftp.open(remote_file=remote_filepath, mode=mode)
            return list(readlines)
     
        def getcwd(self):
            return self.sftp.getcwd()
     
        def cwd(self, remote_path):
            """change dir to given remote_path"""
            return self.sftp.cwd(remotepath=remote_path)
     
        def chmod(self, remote_path, mode: int):
            """ change file grants for w,r,x"""
            self.sftp.chmod(remotepath=remote_path, mode=mode)
     
        def chown(self, remote_path, uid: int, gid: int):
            """change owner of user and group """
            self.sftp.chown(remote_path, uid, gid)
     
        def chdir(self, remote_path):
            """cwd()== chdir()"""
            self.sftp.chdir(remote_path)
     
        def touch(self, filepath):
            """if exists ,pass it or raise exception """
            if self.exists_file(filepath):
                self.remove(filepath)
                self.sftp_client().execute("touch %s" % filepath)
            else:
                self.sftp_client().execute("touch %s" % filepath)
     
        def close(self):
            self.sftp.close()
     
        def opens(self, filepath, mode, file_data=None):
            """file remote read and write ,return str"""
            tp = paramiko.Transport(self.ip, self.port)
            tp.connect(username=self.user, password=self.pwd)
            pipe = paramiko.sftp_client.SFTPClient.from_transport(tp)
            if mode == "w" or mode == "w+":
                with pipe.open(filepath, mode) as f:
                    f.write(file_data)
            else:
                if mode == "r" or mode == "r+":
                    with pipe.open(filepath, mode)as f:
                        return f.read().decode("utf-8")
        def exists(self,remotepath):
            return True if self.sftp.exists(remotepath)  else False
     
     
        def list_dir(self,dir):
            return self.sftp.listdir(dir)
     
        def get_recursive(self,remote_dir,localpdir,):
            """
            preserve modification time on files if True keep modify file or dir last operate time ,else False
            localpdir : the parent dir path of local receive linux dir
            remote_dir : the target of copy remote_dir ,the result dir name is same with remote
            """
            remote_pdir=os.path.dirname(remote_dir)
            # local_pdir = os.path.dirname(localdir)
            remote_target_dir=os.path.split(remote_dir)[-1]
            self.sftp.chdir(remote_pdir) #cd remote_pdir
            if self.exists(localpdir):
                self.sftp.get_r(remote_target_dir,localpdir,preserve_mtime=False)
            else:
                #local create localdir pdir that not exisit
                os.makedirs(localpdir)
                self.sftp.get_r(remote_target_dir, localpdir, preserve_mtime=False)
     
        def put_recursive(self,localdir,remote_pdir,preserve_mtime=False):
            """
            remote_pdir: the parent dir of receive local targetdir ,if parent exists copy target same
            target dirname diredctly to remote_dir,if parent dir not exists ,first makedirs parent dir of remote_pdir,then copy same name
            target dirname to remote_pdir
            localdir: local target dir absolute dir path
            """
            local_targetdir = os.path.split(localdir)[-1]
            remote_receivedir = os.path.join(remote_pdir, local_targetdir)
            local_pdir=os.path.dirname(localdir)
     
            os.chdir(local_pdir) #cd  local pdir
            if self.sftp.exists(remote_receivedir):
                self.sftp.put_r(local_targetdir,remote_receivedir)
            else:
                #remote create pdir not exists
     
                self.sftp.makedirs(remote_receivedir)
                self.sftp.put_r( local_targetdir,remote_receivedir,preserve_mtime)
    def local_rm(dirpath):
        if os.path.exists(dirpath):
            files = os.listdir(dirpath)
            for file in files:
                filepath = os.path.join(dirpath, file).replace("\",'/')
                if os.path.isdir(filepath):
                    local_rm(filepath)
                else:
                    os.remove(filepath)
            os.rmdir(dirpath)
     
    class TestSftp(unittest.TestCase):
     
     
        @classmethod
        def setUpClass(cls):
            cls.sftp=SftpUtils(ip="192.168.110.151",port=22,user="root",pwd="admin")
        @classmethod
        def  tearDownClass(cls):
            pass
     
     
        def  test_cmd(self):
            shell="ip addr "
            readlines=self.sftp.cmd(shell)
            self.assertIn("192.168.110.151",readlines)
     
        def  test_touch(self):
            path="/usr/local/test.txt"
            self.sftp.touch(path)
            res=self.sftp.exists(path)
            self.assertEqual(res,True)
            r=self.sftp.is_file(path)
            self.assertEqual(r,True)
            self.sftp.remove(path)
            res2 = self.sftp.exists(path)
            self.assertEqual(res2, False)
        def test_isdir(self):
            r=self.sftp.is_dir("/usr/local")
            self.assertEqual(r,True)
            k=self.sftp.is_dir("/fff/fcdh")
            self.assertEqual(k,False)
        def  test_isfile(self):
            r="/usr/tets.txt"
            res=self.sftp.is_file(r)
            self.assertEqual(res,False)
        def test_mkdir(self):
            self.sftp.mkdir("/usr/local/testmkdir")
            r=self.sftp.exists("/usr/local/testmkdir")
            self.assertEqual(r,True)
            # self.sftp.rm("/usr/local/testmkdir")
     
        def test_makedirs(self):
            path="/usr/local/makedirs/mk1"
            self.sftp.mkdirs(path)
            r=self.sftp.exists(path)
            self.assertEqual(r,True)
     
        def test_rm(self):
            path="/usr/local/testrm/rmdir/"
            self.sftp.mkdirs(path)
            files=self.sftp.list_dir("/usr/local/testrm")
            self.assertIn('rmdir',files)
     
            self.sftp.touch(path+"test.txt")
            self.sftp.rm("/usr/local/testrm")
            r=self.sftp.exists(path)
            self.assertEqual(r,False)
        def test_opens(self):
            path="/usr/local/test.txt"
            data={"k":99,"v":{"a":9990},"dd":0,"oo":6556}
            self.sftp.opens(path,'w+',json.dumps(data))
            lines=self.sftp.open(path,'r')
     
     
     
        def test_get_r(self):
            remote="/usr/local/listdir"
            local="/usr/local/ttt"
            # self.sftp.chdir("/usr/local")
            # get current dir
            # print(self.sftp.getcwd())
            self.sftp.get_recursive(remote,local)
            local_rm(local)
     
     
        def test_put_r(self):
            local="/usr/local/upload/listdir"
            remote="/usr/local/rrre"
            self.sftp.put_recursive(local,remote)
            self.sftp.rm(remote)
     
     
     
    if __name__ == '__main__':
        unittest.main(verbosity=2)

     测试:

    python   -m  unittest  sftp_tools.TestSftp

    [root@hostuser local]# sh sftptool.sh
    ..........
    ----------------------------------------------------------------------
    Ran 10 tests in 3.017s

    OK

  • 相关阅读:
    POJ 2749
    POJ 3422
    POJ 3621
    SQLSERVER 2005 重新安装过程中的疑难解决
    可遇不可求的Question之MySqlClient访问字段返回System.Byte[]篇
    可遇不可求的Question之odbc驱动无法加载
    可遇不可求的BUG之采用MYSQL odbc 3.51访问数据库返回值缺失
    可遇不可求的Bug之Convert.Int32(<未定义的值>)等于0
    可遇不可求的Question之数据库操作超时篇
    可遇不可求的Question之数据库 'tempdb' 的日志已满。
  • 原文地址:https://www.cnblogs.com/presleyren/p/14215682.html
Copyright © 2020-2023  润新知