从群辉存储设备上传图片到阿里云OSS方案

版权声明: https://blog.csdn.net/zhuangzi123456/article/details/81451955

一,需求

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()

猜你喜欢

转载自blog.csdn.net/zhuangzi123456/article/details/81451955