Python SSH 批量上传文件

运行环境:

    本地:Window7 64位,Python 2.7.6,paramiko 1.12.1

    远端:RedHat Linux, Ubuntu 14.04


# coding:utf8

import os
import sys
import time
import paramiko
import logging


def svnFilter(file_path):
    if '.svn' in file_path: 
        return False
    return True

def gitFilter(file_path):
    if '.git' in file_path: 
        return False
    return True

def settingFilter(file_path):
    if '.setting' in file_path: 
        return False
    return True

class SSHFileUpload:
    """docstring for SSHFileUpload"""

    def __init__(self, hostname, port, username, password):
        self.hostname = hostname
        self.port = port
        self.username = username
        self.password = password
        # self._candidate_dirs = []
        self.__ssh = None
        self._transport = None
        self._sftp = None
        

    def connect(self):
        self.close()
        self.__ssh_connect()
        self._sftp = self.__ssh.open_sftp()

    def reconnect(self):
        self.connect()
        logging.info("SSH session reconnected")

    def is_connected(self):
        transport = self.__ssh.get_transport() if self.__ssh else None
        return transport and transport.is_active()

    def __ssh_connect(self):
        if (not self.__ssh):
            self.__ssh = paramiko.SSHClient()
            self.__ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.__ssh.connect(self.hostname, self.port, self.username, self.password)
            self._transport = self.__ssh.get_transport()

    
    def __ssh_exec(self, command):
        sin, sout, serr = self.__ssh.exec_command(command)
        logging.info("SSH exec_command: %s ", command)
        # if sout.readlines():
        #     logging.info('stdout: %s', sout.readlines())
        # if serr.readlines():
        #     logging.info('stderr: %s', serr.readlines())
            # raise SystemExit
            # sys.exit(1)
        # return sin, sout, serr
        

    def exec_command(self, command):
        if not self.is_connected():
            self.reconnect()
            
        return self.__ssh_exec(command)

    def invoke_shell(self, command='', password='abc123!@#'):
        channel = self.__ssh.invoke_shell()
        return channel
        
        
    def __ssh_close(self):
        if (self.__ssh):
            self.__ssh.close()


    def closeTransport(self):
        if self._transport and self._transport.is_active():
            self._transport.close()


    def closeSFTP(self):
        if self._sftp:
            self._sftp.close()


    def close(self):
        self.closeTransport()
        self.closeSFTP()
        self.__ssh_close()


    def run(self):
        pass


    def copyFile(self, local_path, remote_path):
        if not self.is_connected():
            self.reconnect()
            
        try:
            self._sftp.put(local_path, remote_path)
        except Exception, e:
            r_dir = os.path.split(remote_path)[0]
            cmd = "mkdir -p %s" % r_dir
            self.__ssh_exec(cmd)
            time.sleep(0.5)
            self._sftp.put(local_path, remote_path)
        logging.info("copy [%s] to remote [%s]", local_path, remote_path)


    def copyDir(self, local_dir, remote_dir, filters=[gitFilter, svnFilter, settingFilter]):
        logging.info("Coping [%s] to [%s]\n" % (local_dir, remote_dir))
        candidate_dirs = self._walkLocalDirs(local_dir)
        candidate_dirs = self.__doFilters(candidate_dirs, filters)
        local_dir = local_dir.replace('\\', '/')

        for i, candidate_path in enumerate(candidate_dirs):
            local_file = candidate_dirs[i]
            remote_file = candidate_dirs[i].replace(local_dir, remote_dir).replace('\\', '/').replace('//', '/')
            # print local_file, " : ", remote_file
            remote_file = unicode(remote_file, 'cp936').encode('utf8')
            self.copyFile(local_file, remote_file)
        logging.info("Copied [%s] to [%s]\n" % (local_dir, remote_dir))


    def doUpload(self, local_dir, remote_dir, filters=[]):
        candidate_dirs = self._walkLocalDirs(local_dir)
        candidate_dirs = self.__doFilters(candidate_dirs, filters)

        local_dir = os.path.split(local_dir)[0].replace('\\', '/')

        for i, candidate_path in enumerate(candidate_dirs):
            local_file = candidate_dirs[i]
            remote_file = candidate_dirs[i].replace(local_dir, remote_dir).replace('\\', '/').replace('//', '/')
            
            try:
                self._sftp.put(local_file, remote_file)
            except Exception, e:
                r_dir = os.path.split(remote_file)[0]
                cmd = "mkdir -p %s" % r_dir
                self.__ssh_exec(cmd)
                time.sleep(0.5)
                self._sftp.put(local_file, remote_file)
                # print e
            logging.info("upload [%s] to remote [%s]", local_file, remote_file)


    def _walkLocalDirs(self, local_dir): 
        ''' Get all file path in local_dir and RETURN _candidate_dirs list'''
        _candidate_dirs = []
            
        if os.path.isfile(local_dir):
            _candidate_dirs.append(local_dir.replace('\\', '/'))
            return _candidate_dirs

        for dir_name, sub_dirs, files in os.walk(local_dir):
            dir_name = dir_name.replace('\\', '/')
            for filename in files:
                _candidate_dirs.append(dir_name + '/' + filename)
        return _candidate_dirs


    def __doFilters(self, candidate_dirs, filters=[]):
        for func in filters:
            candidate_dirs = filter(func, candidate_dirs)
        return candidate_dirs


hostname='your_ip'
username='test'
password='test'
port=22

if __name__ == '__main__':
    local_dir = r'E:/workspace/static/images'
    remote_dir = "temp/aaa"
    sfu = SSHFileUpload(hostname, port, username, password)
    # Test
    # sfu.run()
    sfu.connect()
    sfu.copyDir(local_dir, remote_dir)

    local_dir = r'E:/workspace/static/images'
    remote_dir = "temp/bbb"
    sfu.doUpload(local_dir, remote_dir, filters=[svnFilter, vipFilter])    

    sfu.close()



转载于:https://my.oschina.net/dexterman/blog/201926

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值