從群輝儲存裝置上傳圖片到阿里雲OSS方案
阿新 • • 發佈:2018-11-08
一,需求
1,大量圖片需要做異地災備,大約有上百萬張圖片,而且還會往上增加,每張圖片大小在5M-10M左右;
2,環境說明:伺服器是群輝儲存,作業系統功能受限制,跟centos系統使用有諸多不同;
二,實施方案
1,設定crontab任務
#backup data to Aliyun OSS
30 00 * * * root /bin/bash /volume1/scripts/findWithOSS_new.sh 5 #這裡的數字5表示啟用5個python上傳圖片的後臺程序
50 00 * * * root source /etc/profile && /bin/bash /volume1/scripts/backupToOSScrontab_new.sh
2,shell+python
findWithOSS_new.sh:查詢前一天00:00-24:00變動(包括新增和修改)的圖片列表;本來考慮過使用inotify+python,但經過測試發現,群輝儲存作業系統上沒法用,然後改成了find命令來查詢;
backupToOSScrontab_new.sh:圖片上傳程序實現多程序;
backupToOSS_new.py:圖片上傳指令碼,基於阿里雲提供的oss操作python的模組;
3,python版本:2.7.3
三,指令碼程式碼
1,指令碼findWithOSS_new.sh:
#!/bin/bash #Filename: findWithOSS_new.sh #Author: XXXXXX set -m monitoredDir='/volume1/存檔/[存檔]2018新' outputDir='/volume1/scripts/datadir' osslogDir='/volume1/scripts/osslogs' dataFile=filelist.log fnum="$1" #當天開始時間00:00:00 todayDate=$(date -d " " +"%Y%m%d") yesterDate=$(date -d "yesterday" +"%Y%m%d") #每天生成前一天的變動檔名稱列表檔案 find ${monitoredDir} -daystart -ctime 1 -type f | grep -v 'Thumbs.db' &>> ${outputDir}/${dataFile}-${yesterDate} #把上面生成的完整檔案列表拆分成fnum個檔案 /bin/split -n l/${fnum} -d "${outputDir}/${dataFile}-${yesterDate}" "${outputDir}/${dataFile}-${yesterDate}-" #清除60天前的檔案 find ${outputDir} -mtime +60 -type f -exec rm -rf {} \; find ${osslogDir} -mtime +60 -type f -exec rm -rf {} \;
2,指令碼backupToOSScrontab_new.sh:
#!/bin/bash #Filename: backupToOSScrontab.sh #Author: XXXXXXXX #Description:該指令碼用來執行多個python指令碼來上傳檔案到阿里雲的OSS,可以立即為一個排程指令碼; #除錯用 set -m monitoredDir='/volume1/存檔/[存檔]2018新' scriptsDir='/volume1/scripts' outputDir="${scriptsDir}/datadir" osslogDir="${scriptsDir}/osslogs" dataFile=filelist.log yesterDate=$(date -d "yesterday" +"%Y%m%d") cd ${osslogDir} #對拆分後的小檔名稱列表做個遍歷,然後對應每一個檔案分別啟動一個python指令碼上傳對應的檔名稱列表 for i in $(ls ${outputDir}/${dataFile}-${yesterDate}-*) do inum=${i##*-} /bin/python ${scriptsDir}/backupToOSS_new.py "${i}" "${inum}" & done
3,指令碼backupToOSS_new.py:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
#Filename: backupToOSS_new.py
#Author:XXXXXX
#Description:該指令碼用於把給定的檔案傳輸到阿里雲的OSS中,程式碼中判斷,如果出現異常斷開,則會嘗試重新建立連線傳輸。
import os
import datetime
import time
import commands
import oss2
import logging
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
cmdYsd = 'date -d "yesterday" +"%Y%m%d"'
oYsd = commands.getoutput(cmdYsd)
ossError = "/volume1/scripts/osslogs/ossError.log"
ossTransferedFiles = "/volume1/scripts/osslogs/ossTransferedFiles.log"
#findWithOSS.sh指令碼生成的前一天變動檔案的名稱列表檔案拆分出來的一個小檔案
dataFile = sys.argv[1]
logging.basicConfig(filename=ossError + "-" + oYsd + "-" + sys.argv[2], level=logging.ERROR)
#把要傳輸的檔名稱列表匯入為python列表
fileListFile = open(dataFile, 'r')
fileList = fileListFile.readlines()
fileListFile.close()
def login():
# 首先初始化AccessKeyId、AccessKeySecret、Endpoint等資訊。
# 通過環境變數獲取,或者把諸如“<你的AccessKeyId>”替換成真實的AccessKeyId等。
#
# 以杭州區域為例,Endpoint可以是:
# http://oss-cn-hangzhou.aliyuncs.com
# https://oss-cn-hangzhou.aliyuncs.com
# 分別以HTTP、HTTPS協議訪問。
access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', 'XXXXXXXXXX')
access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', 'YYYYYYYYYY')
bucket_name = os.getenv('OSS_TEST_BUCKET', 'ZZZZZZZZ')
endpoint = os.getenv('OSS_TEST_ENDPOINT', 'AAAAAAAAA')
# 確認上面的引數都填寫正確了
for param in (access_key_id, access_key_secret, bucket_name, endpoint):
assert '<' not in param, '請設定引數:' + param
# 建立Bucket物件,所有Object相關的介面都可以通過Bucket物件來進行
global bucket
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
def transFer():
#把本地檔案上傳到OSS,新的Object名稱儲存在變數"ossName”中,ossName的命名規則:1,使用UTF-8編碼;2,長度必須在1-1023位元組之間;3,不能以“/”或者“\”字元開頭。
with open(ossTransferedFiles + "-" + oYsd + "-" + sys.argv[2], 'a+', buffering=1024) as transLog:
for tfile in fileList:
tfile = tfile.strip()
ossName = tfile.lstrip('/')
#fexist = bucket.object_exists(ossName)
#判斷檔案在oss上是否存在,如果不存在則上傳,這樣可以避免檔案重傳浪費時間,可以考慮根據情況判斷是否啟用,如果都是新圖片,則要關閉,因為會增加執行程式碼;
#if not fexist:
nowTime = datetime.datetime.now().strftime('%Y%m%d_%T')
status = 1
while status < 4:
try:
bucket.put_object_from_file(ossName, tfile)
transLog.write("{0} {1}\n".format(nowTime, tfile))
status = 4
except RequestError:
logging.exception("###### {0} {1} {2} times ######\n".format(nowTime, tfile, status))
status += 1
time.sleep(80)
except:
logging.exception("###### {0} {1} {2} times ######\n".format(nowTime, tfile, status))
status += 1
time.sleep(3)
if __name__ == '__main__':
login()
transFer()