脚本将文件从本地计算机同步到外部主机(sftp或ssh)

时间:2016-02-09 14:52:50

标签: python ssh synchronization sftp

对于我的项目,我需要能够使用脚本将程序(HTML)的输出复制到我的服务器,因此只需启动脚本即可完成,无需进一步处理。 只应对内容已更改的文件进行上传,因为在我的程序中新发布后,日期总是会更改。

我在网上发现了一个能够通过一些细微的改动做我想做的事情的脚本。现在,当我在计算机上的两个文件夹之间发布时,它可以工作,但我应该可以用sFTP或SSH连接替换我的目的地......

import os
import filecmp
import shutil

'''
Version: Python 3.3.2
Using python SyncFolder in CMD
Origin: https://gist.github.com/aortbals/5096365
Modified by Louisdj_15
'''
class Dispatch:
    ''' This class represents a synchronization object '''

def __init__(self, name=''):
    self.name=name
    self.node_list=[]
    self.file_copied_count=0
    self.folder_copied_count=0
    self.file_removed_count=0
    self.folder_removed_count=0

def add_node(self, node):
    self.node_list.append(node)


def compare_nodes(self):
    ''' This method takes the nodes in the node_list and compares them '''
    nodeListLength = len(self.node_list)
    # For each node in the list
    for node in self.node_list:
        # If the list has another item after it, compare them
        if self.node_list.index(node) + 1 < len(self.node_list):
            node2 = self.node_list[self.node_list.index(node) + 1]
            '''print(str('\nComparing node ') + str(self.node_list.index(node)) + str(' and Node ') + str(self.node_list.index(node) + 1) + ':')'''
            print('Comparing localhost to server')
            # Pass the two root directories of the nodes to the recursive _compare_directories
            self._compare_directories(node.root_path, node2.root_path)

def _compare_directories(self, left, right):
    ''' This method compares directories. If there is a common directory, the
        algorithm must compare what is inside of the directory by calling this
        recursively.
    '''
    comparison = filecmp.dircmp(left, right)
    if comparison.common_dirs:
       for d in comparison.common_dirs:
           self._compare_directories(os.path.join(left, d), os.path.join(right, d))
    if comparison.left_only:
        self._copy(comparison.left_only, left, right)
    if comparison.right_only:
        self._remove(comparison.right_only, right)
    left_newer = []
    right_newer = []
    if comparison.diff_files:
        for d in comparison.diff_files:
            l_modified = os.stat(os.path.join(left, d)).st_mtime
            r_modified = os.stat(os.path.join(right,d)).st_mtime
            if l_modified > r_modified:
                left_newer.append(d)
            else:
                right_newer.append(d)
    self._copy(left_newer, left, right)
    self._copy(right_newer, right, left)

def _copy(self, file_list, src, dest):
    ''' This method copies a list of files from a source node to a destination node '''
    for f in file_list:
        srcpath = os.path.join(src, os.path.basename(f))
        if os.path.isdir(srcpath):
            shutil.copytree(srcpath, os.path.join(dest, os.path.basename(f)))
            self.folder_copied_count = self.folder_copied_count + 1
            print('Copied directory \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath) + '\" to \"' + dest + '\"')
        else:
            shutil.copy2(srcpath, dest)
            self.file_copied_count = self.file_copied_count + 1
            print('Copied \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath) + '\" to \"' + dest + '\"')

def _remove(self, file_list, src):
    ''' This method removes a list of files from a destionation node if doesn't exist any longer on source '''
    for f in file_list:
        srcpath = os.path.join(src, os.path.basename(f))
        if os.path.isdir(srcpath):
            shutil.rmtree(srcpath)
            self.folder_removed_count = self.folder_removed_count + 1
            print('Removed directory \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath))
        else:
            os.remove(srcpath)
            self.file_removed_count = self.file_removed_count + 1
            print('Removed file \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath))


class Node:
    ''' This class represents a node in a dispathc synchronization '''
    def __init__(self, path, name=''):
        self.name=name
        self.root_path = os.path.abspath(path)
        self.file_list = os.listdir(self.root_path)


if __name__=="__main__":
    node_source = Node('C:\\source_folder', 'source')
    dispatch = Dispatch('Dispatcher')
    node_dest = Node('HERE I NEED AN SFTP OR SSH LINK', 'dest')
    dispatch.add_node(node_source)
    dispatch.add_node(node_dest)
    count=0
    os.system('color 2')
    os.system('cls')
    print('------------------------------------')
    print('| DISPATCHER:  |')
    print('------------------------------------')
    while (count < 1):
        dispatch.compare_nodes()
        print('')
        print('Total files copied ' + str(dispatch.file_copied_count))
        print('Total folders copied ' + str(dispatch.folder_copied_count))
        print('Total files removed ' + str(dispatch.file_removed_count))
        print('Total folders removed ' + str(dispatch.folder_removed_count))
        print('')
        print('Dispatcher is done! Closing connections!')
        count = count + 1

1 个答案:

答案 0 :(得分:0)

您可以使用fabrics put命令轻松sftp文件。

from fabric.api import *
env.hosts = [<hosts>]
with cd('/tmp'):
    put('/path/to/local/test.txt', 'files')