利用linux crontab在docker中进行数据库定时自动备份 #S01

1. 创建需要定时运行的脚本

jcch200_dev_backup.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
#config begin
back_path="/hdb/webbak/hc-bak/db_bak"
back_count=7
#config end
echo $(date +%Y-%m-%d\ %H:%M:%S)" pg_dump begin"
#备份数据库文件
date=$(date +%Y-%m-%d)
docker container ls -f name=hc_postgres -q | xargs -I container_id docker exec container_id /bin/bash -c 'mkdir -p dbbak; pg_dump -U postgres -d jcch200_dev > /dbbak/jcch200_dev_backup_`date +%Y-%m-%d`.bak'
echo $(date +%Y-%m-%d\ %H:%M:%S)" pg_dump end"
#只保留最新的7个文件,删除旧的
c=0
for file in `ls ${back_path}`
do
    filelist[$c]=$file
    ((c++))
done
size=${#filelist[*]}
echo "文件数组长度:" ${size}
for value in ${filelist[@]}
do
    echo $value
done
if [ ${size} -gt ${back_count} ]
then
    echo "size>" ${back_count}
    for ((i=0; i<${size}-${back_count}; i++))
    do
        echo "要删除的过期BAK文件:" ${filelist[$i]}
        rm -rf ${back_path}${filelist[$i]}
    done
else
    echo "size<=" ${back_count}
fi
echo $(date +%Y-%m-%d\ %H:%M:%S)" task end"

crontab 备份 docker mysql 镜像的数据库不生效

Docker exec 命令

查找docker container id

由于docker container id经常会变,因此需要先查询出id,再执行下一步命令。
这里用到 xargs 命令 ,使用 -I 参数,后面跟的 container_id 作为前面执行结果参数的替代字符串

1
docker container ls -f name=hc_postgres -q | xargs -I container_id docker exec container_id /bin/bash -c 'mkdir -p dbbak; pg_dump -U postgres -d jcch200_dev > /dbbak/jcch200_dev_backup_`date +%Y-%m-%d`.bak'

xargs 命令教程

与宿主目录挂接

其中 /dbbak 是容器内部文件夹,/hdb/webbak/hc-bak/db_bak 是宿主机文件夹,两个需进行挂接,在compose.yml中配置,修改后执行 docker stack deploy -c hc-compose.yml hc 使配置生效。
compose.png

2. 创建crontab定时任务

crontab -e

1
2
# 每周六凌晨2点执行备份脚本
0 2 * * 6 . /etc/profile; /bin/sh /hdb/webbak/hc-bak/jcch200_dev_backup.sh >/hdb/webbak/hc-bak/cron.log 2>&1

注意事项:

  • 注意清理系统用户的邮件日志。每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。
    /dev/null 2>&1表示先将标准输出重定向到/dev/null,然后将标准错误重定向到标准输出,由于标准输出已经重定向到了/dev/null,因此标准错误也会重定向到/dev/null,这样日志输出问题就解决了。
  • 注意环境变量问题。有时我们创建了一个crontab,但是这个任务却无法自动执行,而手动执行这个任务却没有问题,这种情况一般是由于在crontab文件中没有配置环境变量引起的。
  • 脚本错误日志和正确的输出写入到文件
  • 新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。
  • 当crontab失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。
  • 千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
  • 在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’。

  • docker exec 后面不能加-it,否则会报“The input device is not a TTY”错误。Error “The input device is not a TTY”


crontab相关:

  1. 命令格式

    1
    crontab [-u user] file crontab [-u user] [ -e | -l | -r ]
  2. 命令参数
    -u user:用来设定某个用户的crontab服务;
    file:file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将它们载入crontab。
    -e:编辑某个用户的crontab文件内容。如果不指定用户,则表示编辑当前用户的crontab文件。
    -l:显示某个用户的crontab文件内容,如果不指定用户,则表示显示当前用户的crontab文件内容。
    -r:从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件。
    -i:在删除用户的crontab文件时给确认提示。

  3. crontab的文件格式

    1
    分 时 日 月 星期 要运行的命令

第1列分钟0~59
第2列小时0~23(0表示子夜)
第3列日1~31
第4列月1~12
第5列星期0~7(0和7表示星期天)
第6列要运行的命令

1
2
#实例:每隔两天的上午8点到11点的第3和第15分钟执行
3,15 8-11 */2 * * myCommand
  1. 重启cron服务
    1
    service cron restart