使用systemd.timer定时执行Python脚本备份数据库和网站
写在前面
上一篇写了如何使用Arch
搭建Lnmp
环境,但是数据不够安全,这一篇教程使用Systemd.timer
定时器定时执行备份脚本,并且使用钉钉机器人每天定时推送备份信息!
1、脚本编写
我已经参考网上写好了备份数据库和网站的代码,如下:
#!/usr/bin/env python
# coding=utf-8
# filename : backup_ver1.py
import datetime
import json
import os
import requests
if not os.path.exists('/srv/backup/mysqldb_backup/'):
os.mkdir('/srv/backup/mysqldb_backup/')
os.chdir('/srv/backup/mysqldb_backup/')
today = datetime.date.today()
yesterday = today - datetime.timedelta(days=5)
# 数据库设置
mysql_today_file_name = "/srv/backup/mysqldb_backup/mysql-" + str(today) + ".sql"
mysql_yesterday_file_name = "/srv/backup/mysqldb_backup/mysql-" + str(yesterday) + ".sql"
# 执行mysql代码
mysql_response_code = os.system(
"mysqldump -u blog -ppasswd blog > /srv/backup/mysqldb_backup/mysql-`date +%Y-%m-%d`.sql")
mysql_file_size = int(os.path.getsize(mysql_today_file_name)) / 1024
if mysql_response_code == 0:
mysql_text = "#### Message:\n\n > - MySqlDB Backup Completed!\n\n > - SQL_file_size:" + str(
round(mysql_file_size, 4)) + "KB\n\n"
if os.path.exists(mysql_yesterday_file_name):
os.remove(mysql_yesterday_file_name)
else:
mysql_text = "#### Message:\n\n > - MySqlDB Backup Error!\n\n > - Please check the server program.\n\n"
# 网站目录备份
# 设置备份的目录
source = '/srv/http'
if not os.path.exists('/srv/backup/http_backup/'):
os.mkdir('/srv/backup/http_backup/')
os.chdir('/srv/backup/http_backup/')
# 数据库设置
http_today_file_name = "/srv/backup/http_backup/http-" + str(today) + ".tar"
http_yesterday_file_name = "/srv/backup/http_backup/http-" + str(yesterday) + ".tar"
http_file_size = int(os.path.getsize(http_today_file_name)) / 1024**2
# print(tar_command)
if tar_command == 0:
http_text = "#### Message:\n\n > - HTTP FILE Backup Completed!\n\n > - HTTP_file_size:" + str(
round(http_file_size, 4)) + "MB"
if os.path.exists(http_yesterday_file_name):
os.remove(http_yesterday_file_name)
else:
http_text = "#### Message:\n\n > - HTTP FILE Backup Error!\n\n > - Please check the server program."
#钉钉机器人api
dingding_url = "https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx"
headers = {"Content-Type": "application/json; charset=utf-8"}
post_data = {
"msgtype": "markdown",
"markdown": {
"title": "HTTP FILE Backup Message",
"text": mysql_text + http_text
}
}
info = requests.post(dingding_url, headers=headers, data=json.dumps(post_data))
自动备份数据库和网站,备份超过五次后自动删除最早的数据。
需要自己申请钉钉机器人,在钉钉网页版就可以申请。
参考:https://www.jianshu.com/p/3382cf349a4f
2、设置定时发布
定时器单元
Timers
是以 .timer
为后缀的 systemd
单元文件。Timers
和其他单元配置文件是类似的,它通过相同的路径加载,不同的是包含了 [Timer]
部分。 [Timer]
部分定义了何时以及如何激活定时事件。Timers
可以被定义成以下两种类型:
- 单调定时器 即从一个时间点过一段时间后激活定时任务。所有的单调计时器都遵循如下形式:
OnTypeSec=
。OnBootSec
和OnActiveSec
是常用的单调定时器。 - 实时定时器 (亦称"挂钟定时器") 通过日历事件激活(类似于
cronjobs
)定时任务。 使用OnCalender=
来定义实时定时器。
服务单元
每个 .timer
文件所在目录都得有一个对应的 .service
文件(如 foo.timer
和 foo.service
)。.timer
用于激活并控制 .service
文件。 .service
文件中不需要包含 [Install]
部分,因为这由 timer 单元接管。必要时通过在定时器的 [Timer]
部分指定 Unit=
选项来控制一个与定时器不同名的服务单元。
摘抄自:ArchLinuxWiki
简单来说就是需要先自己建立一个service
,然后使用timer
定时执行,下面是我的service
和timer
代码:
vim /usr/lib/systemd/system/backup.service
[Unit]
Description=Backup http files and mariadb
[Service]
ExecStart=/bin/python /srv/scripts/backup_ver1.py
ExecReload=/bin/python /srv/scripts/backup_ver1.py
可以看到,这个 Service 单元文件分成两个部分。
[Unit]
部分介绍本单元的基本信息(即元数据),Description
字段给出这个单元的简单介绍(名字叫做Backup
)。
[Service]
部分用来定制行为,Systemd 提供许多字段。
ExecStart:systemctl start所要执行的命令
ExecStop:systemctl stop所要执行的命令
ExecReload:systemctl reload所要执行的命令
ExecStartPre:ExecStart之前自动执行的命令
ExecStartPost:ExecStart之后自动执行的命令
ExecStopPost:ExecStop之后自动执行的命令
Timer部分
Service
单元只是定义了如何执行任务,要定时执行这个 Service
,还必须定义 Timer
单元。
timer
代码:
vim /usr/lib/systemd/system/backup.timer
[Unit]
Description=Backup http files and mariadb
[Timer]
OnCalendar=*-*-* 02:00:00
Unit=backup.service
[Install]
WantedBy=multi-user.target
这个 Timer 单元文件分成几个部分。
[Unit]
部分定义元数据。
[Timer]
部分定制定时器。Systemd
提供以下一些字段。
OnActiveSec:定时器生效后,多少时间开始执行任务
OnBootSec:系统启动后,多少时间开始执行任务
OnStartupSec:Systemd 进程启动后,多少时间开始执行任务
OnUnitActiveSec:该单元上次执行后,等多少时间再次执行
OnUnitInactiveSec: 定时器上次关闭后多少时间,再次执行
OnCalendar:基于绝对时间,而不是相对时间执行
AccuracySec:如果因为各种原因,任务必须推迟执行,推迟的最大秒数,默认是60秒
Unit:真正要执行的任务,默认是同名的带有.service后缀的单元
Persistent:如果设置了该字段,即使定时器到时没有启动,也会自动执行相应的单元
WakeSystem:如果系统休眠,是否自动唤醒系统
上面的脚本里面,OnCalendar=*-*-* 02:00:00
表示每天凌晨两点执行一次任务。其他的写法还有OnUnitActiveSec=Mon *-*-* 02:00:00
表示每周一凌晨两点执行。
[Install] 和 target
backup.timer
文件里面,还有一个[Install]
部分,定义开机自启动(systemctl enable
)和关闭开机自启动(systemctl disable
)这个单元时,所要执行的命令。
上面脚本中,[Install]
部分只写了一个字段,即WantedBy=multi-user.target
。它的意思是,如果执行了systemctl enable backup.timer
(只要开机,定时器自动生效),那么该定时器归属于multi-user.target
。
所谓 Target 指的是一组相关进程,有点像 init 进程模式下面的启动级别。启动某个Target 的时候,属于这个 Target 的所有进程都会全部启动。
multi-user.target
是一个最常用的 Target,意为多用户模式。也就是说,当系统以多用户模式启动时,就会一起启动backup.timer
。它背后的操作其实很简单,执行systemctl enable backup.timer
命令时,就会在multi-user.target.wants
目录里面创建一个符号链接,指向backup.timer
。
定时器相关命令
systemctl start backup.timer #启动定时器
systemctl status backup.timer #查看定时器状态
systemctl enable backup.timer #设置开机自启
定时器的操作和service
是一样的,不需要过多介绍。
参考链接: http://www.ruanyifeng.com/blog/2018/03/systemd-timer.html