Python: 监视文件夹,并通过sftp协议自动上传到服务器(结合freesshd)

功能介绍

写个python脚本,对某文件夹进行监视,查看是否有文件/文件夹新建、删除、移动、更改,对不同的操作进行不同的处理,对于新产生的文件,监视到之后通过sftp协议立刻上传到服务器。

前期准备工作

配置sftp服务器

通过使用freesshd 软件轻松配置sftp服务器,关于具体配置看以下博客
freesshd安装使用教程 windows下安装sftp

相应的python库

watchdog
os
stat
paramiko
traceback

具体实现

实现主要是分为两个模块,监视文件夹,实现上传。

python:对文件夹进行监视

# coding=gbk
from watchdog.observers import Observer
from watchdog.events import *
import time
from upload import SSH    # upload 为上传的python文件名
import time

class FileEventHandler(FileSystemEventHandler):
	
    def __init__(self):
        FileSystemEventHandler.__init__(self)

		
    def on_moved(self, event):
        if event.is_directory:
            print("directory moved from {0} to {1}".format(event.src_path,event.dest_path))
        else:
            print("file moved from {0} to {1}".format(event.src_path,event.dest_path))
    
			
    def on_created(self, event):
        if event.is_directory:
            print("directory created:{0}".format(event.src_path))
        else:
            print("file created:{0}".format(event.src_path))
            a=str(event.src_path)
            #time.sleep(20)
            ssh = SSH(ip='xxx.xxx.xxx.xxx', username='root', password='1111')  # 创建一个ssh类对象
            ssh.connect() # 连接远程服务器
#            ssh.sftp_put_dir('C:\MyFile\Pictures\share\\')  # 上传整个文件夹
            ssh.sftp_put_singleFile(a)                #仅仅上传该单个文件
            ssh.close()
            

    def on_deleted(self, event):
        if event.is_directory:
            print("directory deleted:{0}".format(event.src_path))
        else:
            print("file deleted:{0}".format(event.src_path))

    def on_modified(self, event):
        if event.is_directory:
            print("directory modified:{0}".format(event.src_path))
        else:
            print("file modified:{0}".format(event.src_path))

if __name__ == "__main__":
    observer = Observer()
    event_handler = FileEventHandler()
    observer.schedule(event_handler,"C:\MyFile\Pictures\share",True) #监视的文件夹地址
    observer.start() 开始监视
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

python :上传文件到服务器

# coding=gbk

import os
import stat
import paramiko
import traceback

class SSH(object):

    def __init__(self,ip, port=22, username=None, password=None, timeout=30):
        self.ip = ip
        self.port = port
        self.username = username
        self.password = password
        self.timeout = timeout

        self.ssh = paramiko.SSHClient()

        self.t = paramiko.Transport(sock=(self.ip, self.port))


    def _password_connect(self):

        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(hostname=self.ip, port=22, username=self.username, password=self.password)
        self.t.connect(username=self.username, password=self.password)  # sptf 远程传输的连接

    def _key_connect(self):
        # 建立连接
        self.pkey = paramiko.RSAKey.from_private_key_file('/id', )
        # self.ssh.load_system_host_keys()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(hostname=self.ip, port=22, username=self.username, pkey=self.pkey)

        self.t.connect(username=self.username, pkey=self.pkey)

    def connect(self):
        try:
            self._key_connect()
        except:
            print('ssh key connect failed, trying to password connect...')
            try:
                self._password_connect()
            except:
                print('ssh password connect faild!')

    def close(self):
        self.t.close()
        self.ssh.close()
        
    def execute_cmd(self, cmd):

        stdin, stdout, stderr = self.ssh.exec_command(cmd)

        res, err = stdout.read(), stderr.read()
        result = res if res else err

        return result.decode()

    # 从远程服务器获取文件到本地
    def _sftp_get(self, remotefile, localfile):

        sftp = paramiko.SFTPClient.from_transport(self.t)
        sftp.get(remotefile, localfile)

    # 从本地上传文件到远程服务器
    def _sftp_put(self, localfile, remotefile):

        sftp = paramiko.SFTPClient.from_transport(self.t)
        sftp.put(localfile, remotefile)

    # 递归遍历远程服务器指定目录下的所有文件
    def _get_all_files_in_remote_dir(self, sftp, remote_dir):
        all_files = list()
        if remote_dir[-1] == '/':
            remote_dir = remote_dir[0:-1]

        files = sftp.listdir_attr(remote_dir)
        for file in files:
            filename = remote_dir + '/' + file.filename

            if stat.S_ISDIR(file.st_mode):  # 如果是文件夹的话递归处理
                all_files.extend(self._get_all_files_in_remote_dir(sftp, filename))
            else:
                all_files.append(filename)

        return all_files

    def sftp_get_dir(self, remote_dir, local_dir):
        try:

            sftp = paramiko.SFTPClient.from_transport(self.t)

            all_files = self._get_all_files_in_remote_dir(sftp, remote_dir)

            for file in all_files:

                local_filename = file.replace(remote_dir, local_dir)
                local_filepath = os.path.dirname(local_filename)

                if not os.path.exists(local_filepath):
                    os.makedirs(local_filepath)

                sftp.get(file, local_filename)
        except:
            print('ssh get dir from master failed.')
            print(traceback.format_exc())

    # 递归遍历本地服务器指定目录下的所有文件
    def _get_all_files_in_local_dir(self, local_dir):
        all_files = list()
        print(local_dir+"\nbegin")
		
        for root, dirs, files in os.walk(local_dir, topdown=True):
            for file in files:
                print( file )
                all_files.append(file)
#                filename = os.path.join(root, file)
#                all_files.append(filename)
#                print(filename)

        return all_files

    def sftp_put_dir(self, local_dir):
        try:
            sftp = paramiko.SFTPClient.from_transport(self.t)
            '''
            if remote_dir[-1] == "/":
                remote_dir = remote_dir[0:-1]
                print(remote_dir)
'''
            all_files = self._get_all_files_in_local_dir(local_dir)
            for file in all_files:
                '''
                remote_filename = file.replace(local_dir, remote_dir)
                remote_path = os.path.dirname(remote_filename)
                print(remote_path)

                try:
                    sftp.stat(remote_path)
                except:
                    # os.popen('mkdir -p %s' % remote_path)
                    self.execute_cmd('mkdir -p %s' % remote_path) # 使用这个远程执行命令
'''                    
                sftp.put(local_dir+file, '/'+file)
                print("end put")

        except:
            print('ssh get dir from master failed.')
            print(traceback.format_exc())
	#上传单个文件
    def sftp_put_singleFile(self, local_dir):
        try:
            sftp = paramiko.SFTPClient.from_transport(self.t)
 
            filename=local_dir.split('\\')[-1]     
            sftp.put(local_dir, '/'+filename)
            print("end put one file")
 

        except:
            print('ssh get dir from master failed.')
            print(traceback.format_exc())

    def sftp_put_dir2(self, local_dir):
        try:
            sftp = paramiko.SFTPClient.from_transport(self.t)
            filename=local_dir.split("/")[-1]
            print(filename)
            sftp.put(local_dir, '/'+filename)
            print("end put")

        except:
            print('ssh get dir from master failed.')
            print(traceback.format_exc())


if __name__ == "__main__":

    ssh = SSH(ip='121.36.23.121', username='root', password='1111')  # 创建一个ssh类对象
    ssh.connect() # 连接远程服务器
    print("connect successful!")
#    cmd = 'ls -lh'
#    ssh.execute_cmd(cmd)  # 执行命令
#    remotefile, local_file = 'xxx', 'xxx'
#    ssh.sftp_get(remotefile, local_file)  # 下载文件
    remotedir, localdir = '/', 'C:\MyFile\Pictures\share\\'
    ssh.sftp_put_dir(localdir)  # 上传文件夹
    
    ssh.close()



总结

至此 完成,打开监视的python脚本即可,当文件新建,就会自动将新建的文件进行上传。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值