84 lines
2.8 KiB
Bash
Executable File
84 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
umask 077
|
||
|
||
# 由宿主机 cron 每分钟调用。调度配置来自后台 system_configs,实际执行仍在宿主机,
|
||
# Web 后端不接触 Docker socket、备份载荷或客户端加密密码。
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
# shellcheck source=backup-common.sh
|
||
source "${SCRIPT_DIR}/backup-common.sh"
|
||
|
||
config_value() {
|
||
local key="$1" fallback="$2" value
|
||
value="$(backup_mysql_root_query "SELECT value FROM system_configs WHERE \`key\` = '${key}' LIMIT 1;" 2>/dev/null || true)"
|
||
value="${value//$'\n'/}"
|
||
printf '%s' "${value:-${fallback}}"
|
||
}
|
||
|
||
write_job_state() {
|
||
local status_dir="$1" type="$2" status="$3" message="$4"
|
||
mkdir -p "${status_dir}"
|
||
{
|
||
printf 'job_type=%q\n' "${type}"
|
||
printf 'job_status=%q\n' "${status}"
|
||
printf 'job_at=%q\n' "$(date -Iseconds)"
|
||
printf 'job_message=%q\n' "${message}"
|
||
} > "${status_dir}/last-job.env"
|
||
chmod 600 "${status_dir}/last-job.env"
|
||
}
|
||
|
||
run_job() {
|
||
local status_dir="$1" type="$2" script="$3"
|
||
shift 3
|
||
if "${script}" "$@"; then
|
||
write_job_state "${status_dir}" "${type}" success '执行成功'
|
||
"${SCRIPT_DIR}/backup-status.sh" write || true
|
||
return
|
||
fi
|
||
local code=$?
|
||
write_job_state "${status_dir}" "${type}" failed "执行失败(退出码 ${code})"
|
||
"${SCRIPT_DIR}/backup-status.sh" write || true
|
||
return "${code}"
|
||
}
|
||
|
||
main() {
|
||
backup_require_cmd docker
|
||
backup_require_cmd flock
|
||
local backup_dir status_dir enabled hour minute interval now_hour now_minute
|
||
backup_dir="$(backup_require_env BACKUP_DIR)"
|
||
status_dir="${BACKUP_STATUS_DIR:-${backup_dir}/status}"
|
||
backup_validate_dir "${status_dir}"
|
||
backup_lock_or_exit "${backup_dir}/.scheduler.lock"
|
||
|
||
enabled="$(config_value 'backup.schedule_enabled' 'true')"
|
||
hour="$(config_value 'backup.full_hour' '4')"
|
||
minute="$(config_value 'backup.full_minute' '30')"
|
||
interval="$(config_value 'backup.binlog_interval_minutes' '1')"
|
||
[[ "${enabled}" == true || "${enabled}" == false ]] || { backup_error 'backup.schedule_enabled 必须为 true 或 false'; exit 1; }
|
||
[[ "${hour}" =~ ^[0-9]+$ && "${hour}" -le 23 && "${minute}" =~ ^[0-9]+$ && "${minute}" -le 59 ]] || {
|
||
backup_error '备份全量时间配置无效'
|
||
exit 1
|
||
}
|
||
[[ "${interval}" =~ ^[0-9]+$ && "${interval}" -ge 1 && "${interval}" -le 5 ]] || {
|
||
backup_error 'binlog 归档间隔必须为 1-5 分钟'
|
||
exit 1
|
||
}
|
||
if [[ "${enabled}" == false ]]; then
|
||
"${SCRIPT_DIR}/backup-status.sh" write || true
|
||
exit 0
|
||
fi
|
||
|
||
now_hour="$((10#$(date +%H)))"
|
||
now_minute="$((10#$(date +%M)))"
|
||
if ((now_minute % interval == 0)); then
|
||
run_job "${status_dir}" binlog "${SCRIPT_DIR}/archive-binlog.sh" archive
|
||
fi
|
||
if ((now_hour == hour && now_minute == minute)); then
|
||
run_job "${status_dir}" full "${SCRIPT_DIR}/backup-online.sh" full
|
||
fi
|
||
"${SCRIPT_DIR}/backup-status.sh" write || true
|
||
}
|
||
|
||
main "$@"
|