Files
Cloud-Tour-to-Libo/scripts/install_mysql_backup_systemd.sh

109 lines
4.6 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
PROJECT_DIR="$(cd -- "${SCRIPT_DIR}/.." && pwd -P)"
BACKUP_ROOT="${DATA_BACKUP_ROOT:-}"
PASSPHRASE_FILE="${DATA_BACKUP_PASSPHRASE_FILE:-}"
DATA_DIR="${MYSQL_DATA_DIR:-}"
STORAGE_ID="${MYSQL_STORAGE_ID:-}"
RETENTION_DAYS="${DATA_BACKUP_RETENTION_DAYS:-30}"
SERVICE_USER="${MYSQL_BACKUP_SERVICE_USER:-${SUDO_USER:-root}}"
DOCKER_SOCKET="${DOCKER_HOST:-}"
ENV_DIR="/etc/travel-kg"
ENV_FILE="${ENV_DIR}/mysql-backup.env"
SERVICE_FILE="/etc/systemd/system/nianxx-mysql-backup.service"
TIMER_FILE="/etc/systemd/system/nianxx-mysql-backup.timer"
fail() {
echo "错误:$*" >&2
exit 2
}
safe_path() {
[[ "$1" =~ ^/[A-Za-z0-9._/-]+$ ]]
}
[[ "${EUID}" -eq 0 ]] || fail "请使用 sudo -E 执行"
command -v systemctl >/dev/null 2>&1 || fail "服务器没有systemd,不能安装定时任务"
command -v runuser >/dev/null 2>&1 || fail "缺少runuser命令"
id "${SERVICE_USER}" >/dev/null 2>&1 || fail "备份服务用户不存在:${SERVICE_USER}"
safe_path "${PROJECT_DIR}" || fail "代码目录只能包含字母、数字、点、下划线、横线和斜线"
safe_path "${BACKUP_ROOT}" || fail "DATA_BACKUP_ROOT 必须是安全的绝对路径"
safe_path "${PASSPHRASE_FILE}" || fail "DATA_BACKUP_PASSPHRASE_FILE 必须是安全的绝对路径"
safe_path "${DATA_DIR}" || fail "MYSQL_DATA_DIR 必须是安全的绝对路径"
[[ "${STORAGE_ID}" =~ ^[A-Za-z0-9._-]{16,128}$ ]] || fail "MYSQL_STORAGE_ID格式错误"
[[ "${RETENTION_DAYS}" =~ ^[0-9]+$ ]] || fail "DATA_BACKUP_RETENTION_DAYS必须是整数"
(( RETENTION_DAYS >= 7 && RETENTION_DAYS <= 3650 )) || fail "备份保留天数必须在7–3650天之间"
[[ -x "${PROJECT_DIR}/scripts/backup_mysql_encrypted.sh" ]] || fail "备份脚本不存在或不可执行"
[[ -d "${BACKUP_ROOT}" && ! -L "${BACKUP_ROOT}" ]] || fail "备份目录不存在或是符号链接"
[[ -d "${DATA_DIR}" && ! -L "${DATA_DIR}" ]] || fail "MySQL数据目录不存在或是符号链接"
[[ -f "${PASSPHRASE_FILE}" && ! -L "${PASSPHRASE_FILE}" ]] || fail "备份口令文件不存在或是符号链接"
runuser -u "${SERVICE_USER}" -- test -w "${BACKUP_ROOT}" || fail "${SERVICE_USER}不能写入备份目录"
runuser -u "${SERVICE_USER}" -- test -r "${PASSPHRASE_FILE}" || fail "${SERVICE_USER}不能读取备份口令文件"
if [[ -n "${DOCKER_SOCKET}" && ! "${DOCKER_SOCKET}" =~ ^unix:///[A-Za-z0-9._/-]+$ ]]; then
fail "DOCKER_HOST只允许安全的本机Unix socket"
fi
SERVICE_GROUP="$(id -gn "${SERVICE_USER}")"
install -d -m 0750 -o root -g "${SERVICE_GROUP}" "${ENV_DIR}"
install -m 0640 -o root -g "${SERVICE_GROUP}" /dev/null "${ENV_FILE}"
{
printf 'DATA_BACKUP_ROOT=%s\n' "${BACKUP_ROOT}"
printf 'DATA_BACKUP_PASSPHRASE_FILE=%s\n' "${PASSPHRASE_FILE}"
printf 'DATA_BACKUP_RETENTION_DAYS=%s\n' "${RETENTION_DAYS}"
printf 'MYSQL_DATA_DIR=%s\n' "${DATA_DIR}"
printf 'MYSQL_STORAGE_ID=%s\n' "${STORAGE_ID}"
if [[ -n "${DOCKER_SOCKET}" ]]; then
printf 'DOCKER_HOST=%s\n' "${DOCKER_SOCKET}"
fi
} > "${ENV_FILE}"
install -m 0644 /dev/null "${SERVICE_FILE}"
{
printf '%s\n' '[Unit]'
printf '%s\n' 'Description=Encrypted MySQL backup for Nianxx Data Center'
printf '%s\n' 'Wants=network-online.target'
printf '%s\n' 'After=network-online.target docker.service'
printf '\n%s\n' '[Service]'
printf '%s\n' 'Type=oneshot'
printf 'User=%s\n' "${SERVICE_USER}"
printf 'Group=%s\n' "${SERVICE_GROUP}"
printf 'WorkingDirectory=%s\n' "${PROJECT_DIR}"
printf 'EnvironmentFile=%s\n' "${ENV_FILE}"
printf 'ExecStart=%s/scripts/backup_mysql_encrypted.sh\n' "${PROJECT_DIR}"
printf '%s\n' 'UMask=0077'
printf '%s\n' 'NoNewPrivileges=true'
printf '%s\n' 'PrivateTmp=true'
printf '%s\n' 'ProtectSystem=full'
printf '%s\n' 'ProtectHome=false'
printf '%s\n' 'LockPersonality=true'
} > "${SERVICE_FILE}"
install -m 0644 /dev/null "${TIMER_FILE}"
{
printf '%s\n' '[Unit]'
printf '%s\n' 'Description=Daily encrypted MySQL backup for Nianxx Data Center'
printf '\n%s\n' '[Timer]'
printf '%s\n' 'OnCalendar=*-*-* 02:17:00'
printf '%s\n' 'RandomizedDelaySec=15m'
printf '%s\n' 'Persistent=true'
printf '%s\n' 'Unit=nianxx-mysql-backup.service'
printf '\n%s\n' '[Install]'
printf '%s\n' 'WantedBy=timers.target'
} > "${TIMER_FILE}"
systemctl daemon-reload
systemctl start nianxx-mysql-backup.service
systemctl enable --now nianxx-mysql-backup.timer
echo "首次加密备份已验证,systemd每日备份已启用。"
echo "查看定时器:systemctl list-timers nianxx-mysql-backup.timer"
echo "查看日志:journalctl -u nianxx-mysql-backup.service"
echo "确认异地同步后,才可在.env中设置 DATA_BACKUP_ENABLED=true。"