上一個腳本剛寫完,第二天不用了。。。需要傳到linux服務(wù)器上。。。
So,下一個腳本開始:
1. 這次選擇用的paramiko模塊
pip install paramiko
2. 整體思路
- 遍歷本地目錄放入集合
- 讀取上次上傳到linux的文件信息(existsfile.log)放入另一個集合
- 兩個集合取補集(好像叫對稱差集吧)
- 上傳補集內(nèi)的文件
遠程目錄必須存在,
put方法的遠程目錄才有效。而且必須是文件的絕對路徑,不能是文件夾路徑,否則也會失??;mkdir方法一樣,不可以遞歸地創(chuàng)建目錄,在這兩個地方坑了好久。
3. 代碼實現(xiàn)
syncfiles.py
# -*- coding: utf-8 -*-
__author__ = "hand"
import os
import paramiko
import settings
import platform
from datetime import datetime
class SyncFiles(object):
"""
復(fù)制本機文件到遠端
"""
def __init__(self):
self.f = open("existsfile.log", "a+")
self.remote_host = settings.REMOTE_HOST
self.remote_port = settings.REMOTE_PORT
self.remote_user = settings.REMOTE_USER
self.remote_pwd = settings.REMOTE_PWD
if settings.REMOTE_PATH[-1] == '/' or settings.REMOTE_PATH[-1] == '\\':
self.remote_path = settings.REMOTE_PATH[0:-1]
else:
self.remote_path = settings.REMOTE_PATH
if settings.LOCAL_PATH[-1] == '/' or settings.LOCAL_PATH[-1] == '\\':
self.local_path = settings.LOCAL_PATH[0:-1]
else:
self.local_path = settings.LOCAL_PATH
def get_upload_files(self):
"""獲取待上傳的所有文件"""
local_path_set = set() # 本地文件
file_transfered_set =set() # 已經(jīng)上傳過的文件
for root, dirs, files in os.walk(self.local_path):
for file in files:
local_file = os.path.join(root, file) # 完整的文件路徑:/A/B/C/1.txt
local_path_set.add(local_file)
self.f.seek(0,0) # 將記錄文件指針放在文件頭,用于讀文件
for line in self.f.readlines():
file_transfered = line.split("-")[-1].strip()
file_transfered_set.add(file_transfered)
ready_upload_set = local_path_set ^ file_transfered_set # 待上傳的文件
return list(ready_upload_set)
def record_log(self, path):
now = datetime.now()
# if platform.platform().startswith("Windows"):
# self.f.write(now.strftime('%Y/%M/%d %H:%M:%S %A ') + ' - ' + path + '\\r\\n')
# else:
self.f.write(now.strftime('%Y/%M/%d %H:%M:%S %A ') + ' - ' + path + '\n')
def transfile(self):
"""上傳文件"""
try:
# 實例化Transport
trans = paramiko.Transport((self.remote_host, 22))
# 建立連接
trans.connect(username=self.remote_user, password=self.remote_pwd)
# 實例化一個sftp對象
sftp = paramiko.SFTPClient.from_transport(trans)
ready_upload_list = self.get_upload_files()
already_dir = [] # 存放遠端新建的目錄
if ready_upload_list:
for local_file_path in ready_upload_list:
if platform.platform().startswith("Windows"):
file_need = local_file_path.replace(self.local_path, '').replace('\\','/') # 取出本地路徑后,需要同步到遠端的部分:B/C/1.txt
else:
file_need = local_file_path.replace(self.local_path, '')
remote_file_path = self.remote_path + file_need
try:
# 上傳文件,必須是文件的完整路徑,遠端的目錄必須已經(jīng)存在
sftp.put(localpath=local_file_path, remotepath=remote_file_path)
self.record_log(local_file_path)
except Exception as e:
# 如果目錄不存在就創(chuàng)建,但是不支持遞歸創(chuàng)建
dir_need_list = os.path.split(file_need)[0].split("/") # B、C
dir1 = ''
print dir_need_list
for dir in dir_need_list[1:]:
if dir not in already_dir:
# 目錄存在會報錯,所以把新建過的目錄存在一個全局列表中
if platform.platform().startswith("Windows"):
sftp.mkdir(os.path.join(self.remote_path, dir1, dir).replace('\\','/'))
else:
sftp.mkdir(os.path.join(self.remote_path, dir1, dir))
dir1 = dir
already_dir.append(dir) # 新建過的目錄存在一個全局列表中
# 再次執(zhí)行
sftp.put(localpath=local_file_path, remotepath=remote_file_path)
self.record_log(local_file_path)
except Exception as e:
pass
finally:
trans.close()
if __name__ == "__main__":
sf = SyncFiles()
sf.transfile()
settings.py
# -*- coding: utf-8 -*-
__author__ = "hand"
REMOTE_HOST = 'X.X.X.X'
REMOTE_PORT = 22
REMOTE_USER = '用戶名'
REMOTE_PWD = '密碼'
REMOTE_PATH = '/storage/zhaoning/ttt'
LOCAL_PATH = '/Users/smallcaff/Desktop/filetest'
4. 參考
看過其他一些人的代碼,也拉下來測試過,有的好像在創(chuàng)建遠端目錄時有問題,不知道跟版本有關(guān)系沒
這篇博客關(guān)于paramiko用法寫的很詳細,paramiko用法沒有看官方教程,參考了這個:python模塊之 paramiko