Docker文件数据备份 该脚本运行需要要求环境有 scp 应用, 配置好远端及本地备份路径后, 直接运行即可,
配置文件目录: config.sh
功能: 1 拉取远端服务器文件到本脚本所在目录:File_Bak
常用命令 1 2 docker build --no-cache -t file_back_up . docker run --name c_file_back_up -v [主机备份目录]:/File/[配置容器备份目录] -d file_back_up
容器自启动 1 docker update --restart=always c_file_back_up
查看crond日志详情
自定义逻辑 1 2 3 4 5 6 1.备份日志为/File/log.txt 2.crond定时任务日志在/var/log/crond.log 3.最新一次拉取日志debug信息在/File/currentlog.txt 4.备份文件在/File/File_Bak, 可以通过修改config.sh中[local_path]更改 5.ssh证书密钥请放在env文件中, 并修改config.sh读取路径 6.当前设置为每5分钟定时拉取一次, 失败尝试三次, 三次后放弃, 需要请修改时长
Dockerfile文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 FROM alpine:3.12 .1 WORKDIR File COPY . . RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories; \ apk add --no-cache openssh tzdata; \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; \ apk del tzdata; \ apk add --no-cache dos2unix curl; \ dos2unix *.sh; \ dos2unix config; \ apk del dos2unix; \ chmod 600 ./env/id_rsa_190; \ sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config; \ ssh-keygen -t dsa -P "" -f /etc/ssh/ssh_host_dsa_key; \ ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key; \ ssh-keygen -t ecdsa -P "" -f /etc/ssh/ssh_host_ecdsa_key; \ ssh-keygen -t ed25519 -P "" -f /etc/ssh/ssh_host_ed25519_key; \ echo "root:admin" | chpasswd; \ echo "*/2 * * * * cd /File && /bin/sh ./scp_back_up.sh > currentlog.txt" >> /var/spool/cron/crontabs/root; EXPOSE 22 CMD crond -L /var/log /crond.log -f
scp_back_up.sh脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 # ! /bin/sh # sendMsg(){ if [ ${production} -eq 'true' ]; then MessageUrl=${alert_notice_product} else MessageUrl=${alert_notice_debug} fi PostData="{\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"### 项目: 文件备份\n >${IP}${NAME}\n${1}\n${2}\"}}" echo -e "\n ${current_time}" >> ${notice_file} echo "curl -H \"Content-Type: application/json;charset=utf-8\" -X POST -d \"${PostData}\" \"${MessageUrl}\"" >> ${notice_file} curl -H "Content-Type: application/json;charset=utf-8" -X POST -d "${PostData}" "${MessageUrl}" >> ${notice_file} } # 获取远端文件夹内创建时间在规定期间的文件 getFile(){ echo "ssh -i ${identify_file} -o StrictHostKeyChecking=no -p ${PORT} ${USER}@${IP} \"find ${back_up_file_path} -type f -ctime ${back_time}\"" ssh -i ${identify_file} -o StrictHostKeyChecking=no -p ${PORT} ${USER}@${IP} "find ${back_up_file_path} -type f -ctime ${back_time}" > ${current_time}.txt } # # 引入配置文件 source config # 当前时间 current_time=`date "+%Y-%m-%d_%H:%M:%S"` # 创建文件夹 if [[ ! -d ${local_tmp_path} ]]; then mkdir -p ${local_tmp_path} fi if [[ ! -d ${local_path} ]]; then mkdir -p ${local_path} fi if [[ ! -f ${log_file} ]]; then touch ${log_file} fi if [[ ! -f ${notice_file} ]]; then touch ${notice_file} fi if [[ ! -f ${current_time}.txt ]]; then touch ${current_time}.txt fi if [[ ! -f ${current_time}false.txt ]]; then touch ${current_time}false.txt fi getFile if [ ! -s ${current_time}.txt ]; then rm -f ${current_time}.txt rm -f ${current_time}false.txt sendMsg "${IP}:${file_path}" "${current_time}备份文件为空,备份失败" exit 0 fi cat ${current_time}.txt | while read LINE ; do file_path=${LINE} file_name=`basename ${LINE}` # 普通ssh登录 # scp -r -v -p -P ${PORT} -l ${transfer_speed} ${USER}@${IP}:${back_up_file_path}${back_up_file_name} ${local_path} # 使用密钥文件登录 count_times=0 # 尝试最多三次拉取远端文件 while [[ ${count_times} -lt 3 ]]; do count_times=`expr ${count_times} + 1` # echo "scp -r -v -p -i ${identify_file} -P ${PORT} -l ${transfer_speed} ${USER}@${IP}:${back_up_file_path}${back_up_file_name} ${local_tmp_path}" echo "scp -r -v -p -i ${identify_file} -o StrictHostKeyChecking=no -P ${PORT} -l ${transfer_speed} ${USER}@${IP}:${file_path} ${local_tmp_path}" scp -r -v -p -i ${identify_file} -o StrictHostKeyChecking=no -P ${PORT} -l ${transfer_speed} ${USER}@${IP}:${file_path} ${local_tmp_path} cmd_result=$? # 拉取成功后跳出 if [[ ${cmd_result} -eq 0 ]]; then sh -c "echo '${current_time}第${count_times}次拉取数据${file_path}成功' >> ${log_file}" break fi sleep 5 done # 判读是否成功移动,写入日志 if [[ ${cmd_result} -eq 0 ]]; then echo "${current_time}移动文件到缓存目录 ${local_tmp_path} 成功" sh -c "echo '${current_time}移动文件到缓存目录 ${local_tmp_path} 成功' >> ${log_file}" else echo "${cmd_result}" > ${current_time}false.txt echo "!!! ${current_time}拉取远端文件到缓存目录 ${local_tmp_path} 失败" sh -c "echo '!!! ${current_time}拉取远端文件到缓存目录 ${local_tmp_path} 失败' >> ${log_file}" # 调用通知函数发送失败通知 sendMsg "${IP}${file_path}" "!!!${current_time}拉取远端文件到缓存目录${local_tmp_path}失败" fi # 从缓存目录移动文件到实际备份文件夹 mv ${local_tmp_path}/${file_name} ${local_path} mv_result=$? if [[ ${mv_result} -ne 0 ]]; then echo "${mv_result}" > ${current_time}false.txt echo "!!! ${current_time}移动文件${local_tmp_path}${file_name} 到目录 ${local_path} 失败" sh -c "echo '!!! ${current_time}移动文件${local_tmp_path}${file_name} 到目录 ${local_path} 失败' >> ${log_file}" sendMsg "${IP}${file_name}" "!!!${current_time}移动文件${local_tmp_path}${file_name}到目录${local_path}失败" else echo "!!! ${current_time}移动文件${local_tmp_path}${file_name} 到目录 ${local_path} 成功" fi echo 'end' done # 删除文件清单 rm -r ${current_time}.txt if [ ! -s ${current_time}false.txt ]; then sendMsg "${IP}:${file_path}" "${current_time}备份文件成功" else sendMsg "${IP}:${file_path}" "!!!${current_time}备份文件有错误,请查看日志详情" fi rm -r ${current_time}false.txt
config配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 远端配置 NAME='日常备份' # 项目名称 USER='[使用用户]' # 用户名 IP='xxx.xxx.xxx.xxx' # IP地址 PORT='[端口]' # 端口 # 功能配置 identify_file='./env/[公钥文件名]' # 登录公钥文件 transfer_speed='200000' # 最大传输速度 kb/s # 项目文件配置 back_up_file_path='/var/www/[备份文件夹名]/' # 远端备份路径 local_tmp_path='/var/www/LocalCFS/temp' # 本地缓存路径 local_path='/File/File_Bak/[项目名]/' # 本地存储路径 back_time='-1' # 遵循find命令格式,-1代表一天之内的文件 # 日志文件/通知配置 alert_notice_product='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx' alert_notice_debug='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx' log_file='log.txt' # 日志名称 notice_file='notice.txt' # 消息日志名称 production=false # 消息发送环境设定