Trilium 备份加密版完整脚本
目标
过程
问题
解决方案
#!/bin/bash
set -u
####################################
# Trilium 整目录灾备(加密版)
####################################
### === 基础配置 ===
DATA_DIR="/opt/1panel/apps/trilium/trilium/data"
LOCAL_BACKUP_DIR="/opt/backup/trilium"
REMOTE_TARGET="alist:中国移动云盘/DATA/backup/trilium"
LOCAL_KEEP=1
REMOTE_KEEP=7
# 加密密码(建议改为读取文件)
GPG_PASSPHRASE_FILE="/root/.backup_trilium_passphrase"
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
BACKUP_NAME="trilium_full_${DATE}.tar.gz"
ENCRYPTED_NAME="${BACKUP_NAME}.gpg"
LOCK_FILE="/var/run/backup_trilium.lock"
LOG_PREFIX="[Trilium-Backup]"
### === 并发锁 ===
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
echo "$LOG_PREFIX 已有备份任务在运行,退出"
exit 0
fi
### === 前置检查 ===
command -v gpg >/dev/null 2>&1 || {
echo "$LOG_PREFIX ❌ gpg 未安装"
exit 1
}
command -v jq >/dev/null 2>&1 || {
echo "$LOG_PREFIX ⚠ jq 未安装,远端清理将跳过"
SKIP_REMOTE_CLEAN=1
}
[ -f "$GPG_PASSPHRASE_FILE" ] || {
echo "$LOG_PREFIX ❌ 未找到加密密码文件"
exit 1
}
mkdir -p "$LOCAL_BACKUP_DIR"
cd "$DATA_DIR" || exit 1
echo "$LOG_PREFIX 开始整目录灾备:$BACKUP_NAME"
### === 打包(WAL 容忍)===
tar -czf "${LOCAL_BACKUP_DIR}/${BACKUP_NAME}" \
--warning=no-file-changed \
--exclude="backup" \
--exclude="tmp" \
--exclude="log" \
.
TAR_EXIT=$?
if [ $TAR_EXIT -ge 2 ]; then
echo "$LOG_PREFIX ❌ tar 严重失败(exit=$TAR_EXIT)"
exit 1
fi
echo "$LOG_PREFIX tar 完成(exit=$TAR_EXIT)"
### === 加密 ===
echo "$LOG_PREFIX 开始加密备份"
gpg --batch --yes \
--symmetric --cipher-algo AES256 \
--passphrase-file "$GPG_PASSPHRASE_FILE" \
"${LOCAL_BACKUP_DIR}/${BACKUP_NAME}"
rm -f "${LOCAL_BACKUP_DIR}/${BACKUP_NAME}"
echo "$LOG_PREFIX 加密完成:$ENCRYPTED_NAME"
### === 校验 ===
BACKUP_SIZE=$(stat -c%s "${LOCAL_BACKUP_DIR}/${ENCRYPTED_NAME}")
if [ "$BACKUP_SIZE" -lt 10485760 ]; then
echo "$LOG_PREFIX ❌ 加密备份异常过小"
exit 1
fi
### === 本地清理 ===
cd "$LOCAL_BACKUP_DIR" || exit 1
ls -1tr trilium_full_*.gpg | head -n -"$LOCAL_KEEP" | xargs -r rm -f
### === 上传 ===
echo "$LOG_PREFIX 上传至远端:$REMOTE_TARGET"
rclone copy "$LOCAL_BACKUP_DIR" "$REMOTE_TARGET" --progress
### === 远端清理 ===
if [ "${SKIP_REMOTE_CLEAN:-0}" -eq 0 ]; then
rclone lsjson "$REMOTE_TARGET" | \
jq -r 'sort_by(.ModTime) | .[:-'"$REMOTE_KEEP"'] | .[].Name' | \
while read -r f; do
echo "$LOG_PREFIX 删除远端旧文件:$f"
rclone delete "$REMOTE_TARGET/$f"
done
fi
echo "$LOG_PREFIX 🎉 加密整目录灾备完成"
最终结论
后续整理到