MySQL OneKey Backup
一个面向 Linux 和 Cron 的单文件 MySQL/MariaDB 备份脚本,支持备份校验、过期清理、Hook 和多渠道通知。
生成配置
打开在线配置生成器,通过表单生成命令、环境变量、Crontab、客户端配置文件、每库完成 Hook 示例和 Apprise 配置,也可以直接下载 mysql_backup.sh。配置中心支持浏览器本地保存、JSON 导入导出和命令反解析。保存和导出默认排除密码、Token、Webhook 等敏感字段;需要完整备份时可手动选择包含。所有内容都在浏览器本地处理,不会上传数据。
功能
- 备份全部数据库、单个数据库或多个数据库。
- 多个数据库可分别导出,也可写入同一个 SQL 文件。
- 支持
zip、sql、both三种产物模式。 - 发布前校验 SQL、Zip 和 SHA256,失败时不发布不完整产物。
- 使用文件锁阻止同一目标目录内的任务并发执行,并清理脚本创建的过期运行目录。
- 支持前置、每库完成和后置 Hook。
- 支持 Apprise、Bark、ntfy、飞书、企业微信、钉钉和 Gotify 通知。
- 所有备份配置均支持环境变量和命令行选项,命令行值优先。
下载
下载到默认位置 /opt/mysql-backup/mysql_backup.sh:
sudo install -d -m 755 /opt/mysql-backup
sudo curl -fL https://raw.githubusercontent.com/funnyzak/mysql-onekey-backup/main/mysql_backup.sh \
-o /opt/mysql-backup/mysql_backup.sh
sudo chmod 755 /opt/mysql-backup/mysql_backup.sh
如果 GitHub Raw 访问较慢,可把下载地址替换为 jsDelivr CDN 地址。
快速开始
备份根目录必须提前创建,归运行脚本的用户所有,且不能允许组用户或其他用户写入:
install -d -m 700 -o backup -g backup /var/backups/mysql
根目录的上级路径必须归当前用户或 root 所有,也不能允许组用户或其他用户写入。
检查参数和本机依赖。该命令不会连接数据库或发送通知:
bash mysql_backup.sh \
--target-dir /var/backups/mysql \
--host 127.0.0.1 \
--port 3306 \
--user backup \
--defaults-extra-file /etc/mysql-backup/client.cnf \
--database app \
--check
首次部署时,可以单独检查依赖:
bash mysql_backup.sh --dependency-report
该命令不要求备份目录,也不会连接数据库或发送通知。缺少必要依赖时返回状态码 2,依赖齐全时返回 0。
执行备份:
bash mysql_backup.sh \
--target-dir /var/backups/mysql \
--host 127.0.0.1 \
--port 3306 \
--user backup \
--defaults-extra-file /etc/mysql-backup/client.cnf \
--database app \
--database analytics
不传 --database 时备份全部数据库。默认每个数据库生成一个 SQL 文件,产物模式为 zip。使用 --single-file 时,全部数据库合并到 all_databases.sql,显式指定的数据库合并到 selected_databases.sql。
分文件备份会分别启动 mysqldump,各数据库的快照时间可能略有不同。需要跨数据库保持同一备份时间点时,使用 --single-file。
运行要求
- Bash 4.2+
mysqldumpmysql,仅备份全部数据库并分别导出时需要flocksha256sum或shasumzip,仅zip和both模式需要curl,仅启用 HTTP 通知渠道时需要apprise和timeout(或gtimeout),仅启用 Apprise CLI 通知时需要
脚本不会自动安装软件。--dependency-report 会列出缺失项和安装建议,执行安装命令前请先确认。Apprise CLI 的安装方法见官方文档。
数据库认证
脚本支持直接密码、MySQL 客户端配置文件和 MySQL Login Path。三种方式只能选一种。生产环境推荐使用权限为 600 的客户端配置文件或 Login Path。
不要通过 MYSQL_BACKUP_DUMP_OPTIONS 或 --dump-option 传递密码。
客户端配置文件
推荐只在配置文件中保存密码:
[client]
password=replace-with-your-password
文件必须存在、可读、不是符号链接,归运行备份的用户所有,且组用户和其他用户没有任何权限。各级父目录必须归当前用户或 root 所有,且不能允许组用户或其他用户写入。
install -d -m 700 -o backup -g backup /etc/mysql-backup
touch /etc/mysql-backup/client.cnf
chown backup:backup /etc/mysql-backup/client.cnf
chmod 600 /etc/mysql-backup/client.cnf
通过 --defaults-extra-file 或 MYSQL_BACKUP_DEFAULTS_FILE 使用该文件。脚本参数中的 host、port 和 user 会覆盖配置文件中的同名值。
Login Path
使用 mysql_config_editor 创建 Login Path:
mysql_config_editor set \
--login-path=backup \
--host=127.0.0.1 \
--port=3306 \
--user=backup \
--password
bash mysql_backup.sh \
--target-dir /var/backups/mysql \
--login-path backup \
--database app
Login Path 属于创建它的系统用户,Cron 也必须使用同一个用户运行。显式传入的 host、port 和 user 会覆盖 Login Path 中的值。
直接设置密码
可以通过环境变量设置密码:
export MYSQL_BACKUP_HOST=127.0.0.1
export MYSQL_BACKUP_PORT=3306
export MYSQL_BACKUP_USER=backup
export MYSQL_BACKUP_PASSWORD='replace-with-your-password'
bash mysql_backup.sh \
--target-dir /var/backups/mysql \
--database app
也可以使用 --password,但密码会出现在进程参数和 Shell 历史中。环境变量仍可能被同一用户或 root 读取。
密码可包含空格、引号、反斜杠、#、; 和 %,在 Shell 中应使用单引号。脚本拒绝包含控制字符的密码。
通知
默认发送成功和失败通知,加入 --notify-start 后也会发送开始通知。通知默认开启脱敏:隐藏数据库地址、端口、用户、Login Path、数据库名和备份路径,失败详情只提示查看本地日志。服务器标签、Run ID、阶段、耗时和备份大小仍会显示。
如需在受信任渠道中查看完整详情,可使用 --no-notify-redact 或设置 MYSQL_BACKUP_NOTIFY_REDACT=false。成功通知会统计本次生成的 SQL 和 ZIP 文件总大小,并以 KB、MB、GB 等易读单位显示。多个渠道可以同时启用,单个渠道失败不影响备份结果。
HTTP 通知只接受 HTTPS;localhost、127.0.0.1 和 [::1] 可以使用 HTTP。命令行中的 Webhook、Token 和 Key 可能出现在进程参数和 Shell 历史中,敏感配置优先使用环境变量或权限为 600 的 Apprise 配置文件。
Bark
export MYSQL_BACKUP_BARK_SERVER=https://api.day.app
export MYSQL_BACKUP_BARK_DEVICE_KEY=replace-with-device-key
export MYSQL_BACKUP_BARK_SOUND=alarm # 可选
export MYSQL_BACKUP_BARK_GROUP=mysql-backup # 可选
MYSQL_BACKUP_BARK_SERVER 也可以指向自建 Bark 服务。
ntfy
export MYSQL_BACKUP_NTFY_SERVER=https://ntfy.sh
export MYSQL_BACKUP_NTFY_TOPIC=mysql-backup
export MYSQL_BACKUP_NTFY_TOKEN=replace-with-access-token # 私有主题才需要
飞书、企业微信和钉钉
export MYSQL_BACKUP_FEISHU_WEBHOOK_URL='https://open.feishu.cn/open-apis/bot/v2/hook/replace-me'
export MYSQL_BACKUP_WECOM_WEBHOOK_URL='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=replace-me'
export MYSQL_BACKUP_DINGTALK_WEBHOOK_URL='https://oapi.dingtalk.com/robot/send?access_token=replace-me'
钉钉机器人如果启用关键词校验,请加入 MySQL backup,也可以使用 IP 白名单。当前实现不支持钉钉动态签名。
Gotify
export MYSQL_BACKUP_GOTIFY_SERVER=https://gotify.example.com
export MYSQL_BACKUP_GOTIFY_TOKEN=replace-with-app-token
export MYSQL_BACKUP_GOTIFY_PRIORITY=5 # 可选,默认 5
Gotify 优先级范围为 -9999 到 9999。
Apprise CLI
把 Apprise URL 写入配置文件,例如:
json://example.invalid/replace-with-token
配置文件必须归运行备份的用户所有,权限为 600,不能是符号链接。上级路径需满足客户端配置文件的属主和权限要求。
chown backup:backup /etc/mysql-backup/apprise.conf
chmod 600 /etc/mysql-backup/apprise.conf
export MYSQL_BACKUP_APPRISE_CONFIG=/etc/mysql-backup/apprise.conf
export MYSQL_BACKUP_APPRISE_TAGS='ops,admin' # 可选
Apprise API
调用已保存配置的 Apprise API:
export MYSQL_BACKUP_APPRISE_API_URL=http://127.0.0.1:8000/notify/mysql-backup
export MYSQL_BACKUP_APPRISE_TAGS='ops,admin' # 可选
使用 stateless /notify 时,再提供 Apprise 服务 URL:
export MYSQL_BACKUP_APPRISE_API_URL=http://127.0.0.1:8000/notify
export MYSQL_BACKUP_APPRISE_URLS='bark://device-key ntfy://ntfy.sh/mysql-backup'
--check 只检查通知配置、URL、文件权限和依赖,不发送测试消息。
产物目录
每次成功备份对应一个独立目录:
/var/backups/mysql/
├── .staging/
└── runs/
└── dbback_20260729T120000Z_12345/
├── .mysql-onekey-backup-run
├── backup.zip
├── manifest.txt
└── SHA256SUMS
manifest.txt 记录脚本版本、运行 ID、数据库连接来源、数据库列表、产物模式和耗时,不包含密码。
常用选项
查看完整帮助:
bash mysql_backup.sh --help
所有备份配置都支持环境变量和命令行选项。标量使用命令行值覆盖环境变量;列表出现对应命令行选项后,会整体替换环境变量列表。--dependency-report 是独立检查命令,没有对应的环境变量。选项和值之间使用空格,不支持 --option=value 写法。
| 环境变量 | 命令行选项 | 说明 |
|---|---|---|
MYSQL_BACKUP_TARGET_DIR |
--target-dir DIR |
已存在的备份根目录,必填 |
MYSQL_BACKUP_HOST |
--host HOST |
数据库地址,默认 127.0.0.1 |
MYSQL_BACKUP_PORT |
--port PORT |
数据库端口,默认 3306 |
MYSQL_BACKUP_USER |
--user USER |
数据库用户,默认 root |
MYSQL_BACKUP_PASSWORD |
--password PASSWORD |
数据库密码;与客户端配置文件、Login Path 三选一 |
MYSQL_BACKUP_DATABASES |
--database NAME,可重复;--all-databases 清空环境列表 |
环境变量每行一个数据库;空值表示全部数据库 |
MYSQL_BACKUP_DEFAULTS_FILE |
--defaults-extra-file FILE |
MySQL 客户端配置文件,权限设为 600 |
MYSQL_BACKUP_LOGIN_PATH |
--login-path NAME |
MySQL Login Path;与直接密码、客户端配置文件三选一 |
MYSQL_BACKUP_DUMP_OPTIONS |
--dump-option OPTION,可重复;--default-dump-options 清空环境追加项 |
环境变量每行一个白名单参数 |
MYSQL_BACKUP_SEPARATE_FILES |
--separate-files / --single-file |
文件粒度,默认分别导出;适用于指定数据库和全部数据库 |
MYSQL_BACKUP_OUTPUT_MODE |
--output-mode MODE |
zip、sql 或 both,默认 zip |
MYSQL_BACKUP_EXPIRE_HOURS |
--expire-hours HOURS |
保留小时数,默认 4320;0 不清理 |
MYSQL_BACKUP_BEFORE_HOOK |
--before-hook FILE |
前置 Hook |
MYSQL_BACKUP_BEFORE_HOOK_COMMAND |
--before-hook-command CMD |
前置自定义命令;与脚本二选一 |
MYSQL_BACKUP_AFTER_DATABASE_HOOK |
--after-database-hook FILE |
每个数据库分别导出成功后执行的 Hook |
MYSQL_BACKUP_AFTER_DATABASE_HOOK_COMMAND |
--after-database-hook-command CMD |
每个数据库分别导出成功后执行的自定义命令;与脚本二选一 |
MYSQL_BACKUP_AFTER_HOOK |
--after-hook FILE |
后置 Hook |
MYSQL_BACKUP_AFTER_HOOK_COMMAND |
--after-hook-command CMD |
发布和清理完成后执行的自定义命令;与脚本二选一 |
MYSQL_BACKUP_SERVER_NAME |
--server-name NAME |
通知中的服务器名 |
MYSQL_BACKUP_CHECK |
--check / --no-check |
只检查配置,默认 false |
MYSQL_BACKUP_NOTIFY_START |
--notify-start / --no-notify-start |
是否发送开始通知,默认 false |
MYSQL_BACKUP_NOTIFY_REDACT |
--notify-redact / --no-notify-redact |
是否隐藏通知中的连接、数据库和路径详情,默认 true |
MYSQL_BACKUP_NOTIFY_TIMEOUT |
--notify-timeout SECONDS |
通知超时,范围 1 到 300,默认 10 |
MYSQL_BACKUP_APPRISE_CONFIG |
--apprise-config FILE |
Apprise CLI 配置文件 |
MYSQL_BACKUP_APPRISE_API_URL |
--apprise-api-url URL |
Apprise API 的 /notify 或 /notify/{key} 地址 |
MYSQL_BACKUP_APPRISE_URLS |
--apprise-urls URLS |
Stateless Apprise 服务 URL |
MYSQL_BACKUP_APPRISE_TAGS |
--apprise-tags TAGS |
Apprise 标签表达式 |
MYSQL_BACKUP_BARK_SERVER |
--bark-server URL |
Bark 服务地址 |
MYSQL_BACKUP_BARK_DEVICE_KEY |
--bark-device-key KEY |
Bark 设备 Key |
MYSQL_BACKUP_BARK_SOUND |
--bark-sound SOUND |
Bark 提示音,可选 |
MYSQL_BACKUP_BARK_GROUP |
--bark-group GROUP |
Bark 通知分组,可选 |
MYSQL_BACKUP_NTFY_SERVER |
--ntfy-server URL |
ntfy 服务地址 |
MYSQL_BACKUP_NTFY_TOPIC |
--ntfy-topic TOPIC |
ntfy 主题 |
MYSQL_BACKUP_NTFY_TOKEN |
--ntfy-token TOKEN |
ntfy Access Token,可选 |
MYSQL_BACKUP_FEISHU_WEBHOOK_URL |
--feishu-webhook-url URL |
飞书机器人 Webhook |
MYSQL_BACKUP_WECOM_WEBHOOK_URL |
--wecom-webhook-url URL |
企业微信机器人 Webhook |
MYSQL_BACKUP_DINGTALK_WEBHOOK_URL |
--dingtalk-webhook-url URL |
钉钉机器人 Webhook |
MYSQL_BACKUP_GOTIFY_SERVER |
--gotify-server URL |
Gotify 服务地址 |
MYSQL_BACKUP_GOTIFY_TOKEN |
--gotify-token TOKEN |
Gotify 应用 Token |
MYSQL_BACKUP_GOTIFY_PRIORITY |
--gotify-priority NUMBER |
Gotify 优先级,范围 -9999 到 9999,默认 5 |
--dump-option 只接受白名单内的参数,例如 --routines、--events、--hex-blob、--no-data、--ignore-table=库.表 和 --where=条件。
Hook
Hook 脚本必须是普通可执行文件,不能是符号链接。文件需归运行备份的用户所有,且不能允许组用户或其他用户写入。上级路径必须归当前用户或 root 所有,且不能允许组用户或其他用户写入。每个阶段也可以改用 --before-hook-command、--after-database-hook-command 或 --after-hook-command 直接填写 Bash 命令;同一阶段的脚本和命令只能配置一个。
自定义命令通过 bash -c 执行,命令可以读取下列 BACKUP_* 上下文变量。命令内容中的密码、Token 等敏感值不会默认保存到配置中心的本地配置。
所有 Hook 都可以读取:
BACKUP_RUN_IDBACKUP_TARGET_DIRBACKUP_STAGE_DIRBACKUP_PUBLISHED_DIR
BACKUP_PUBLISHED_DIR 在发布完成前为空。
每库完成 Hook 还可以读取:
BACKUP_DATABASE_NAMEBACKUP_DATABASE_FILEBACKUP_DATABASE_INDEXBACKUP_DATABASE_TOTALBACKUP_OUTPUT_MODE
每库完成 Hook 支持指定数据库和全部数据库的分文件模式,不支持 --single-file。它接收压缩前的暂存 SQL,应把文件当作只读输入,并把处理结果写到暂存目录之外。
前置 Hook 失败时不会执行备份;每库完成 Hook 失败时会终止任务且不发布本次产物;后置 Hook 失败时产物已经发布,但任务仍会返回失败并发送失败通知。
完整的每库完成 Hook 示例可通过在线配置生成器生成和下载。
Cron
每天 03:00 使用客户端配置文件备份,并通过 Apprise 发送通知:
0 3 * * * /usr/bin/bash /opt/mysql-backup/mysql_backup.sh --target-dir /var/backups/mysql --defaults-extra-file /etc/mysql-backup/client.cnf --database app --apprise-config /etc/mysql-backup/apprise.conf --apprise-tags ops >> /var/log/mysql-backup.log 2>&1
每条 Cron 任务应在自己的命令中携带完整参数,避免多个备份任务共享环境变量后相互覆盖。Cron 会在 Shell 之前处理命令中的 %,参数里的每个 % 都要写成 \%。敏感值建议放在权限为 600 的 MySQL 或 Apprise 配置文件中,并使用独立的低权限账号运行任务。
开发与测试
bash -n mysql_backup.sh scripts/test_mysql_backup.sh
bash scripts/test_mysql_backup.sh
node scripts/test_config_html.js
shellcheck mysql_backup.sh scripts/test_mysql_backup.sh
测试使用命令替身模拟 MySQL、任务锁、curl 和 Apprise,不需要真实数据库或通知地址。
License
MIT License © 2023 funnyzak