Spaces:
Paused
Paused
Update sync_data.sh
Browse files- sync_data.sh +84 -146
sync_data.sh
CHANGED
|
@@ -1,165 +1,103 @@
|
|
| 1 |
#!/bin/bash
|
| 2 |
-
|
| 3 |
|
| 4 |
-
#
|
| 5 |
-
|
| 6 |
-
BACKUP_DIR=${BACKUP_DIR:-"/app/backup"}
|
| 7 |
-
LOG_FILE="$BACKUP_DIR/sync.log"
|
| 8 |
-
WEBDAV_URL=${WEBDAV_URL}
|
| 9 |
-
WEBDAV_USERNAME=${WEBDAV_USERNAME}
|
| 10 |
-
WEBDAV_PASSWORD=${WEBDAV_PASSWORD}
|
| 11 |
-
WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-alist_backups}
|
| 12 |
-
SYNC_INTERVAL=${SYNC_INTERVAL:-3600}
|
| 13 |
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
}
|
| 21 |
|
| 22 |
-
#
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
restore_backup() {
|
| 27 |
-
log "开始恢复最新备份..."
|
| 28 |
-
|
| 29 |
-
# 检查 WebDAV 配置
|
| 30 |
-
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
|
| 31 |
-
log "WebDAV 配置缺失,跳过恢复"
|
| 32 |
-
return
|
| 33 |
-
fi
|
| 34 |
|
| 35 |
-
|
| 36 |
-
LATEST_BACKUP=$(python3 -c "
|
| 37 |
import os
|
|
|
|
| 38 |
from webdav3.client import Client
|
| 39 |
-
options = {
|
| 40 |
-
'webdav_hostname': '$WEBDAV_URL',
|
| 41 |
-
'webdav_login': '$WEBDAV_USERNAME',
|
| 42 |
-
'webdav_password': '$WEBDAV_PASSWORD',
|
| 43 |
-
'webdav_root': '$WEBDAV_BACKUP_PATH'
|
| 44 |
-
}
|
| 45 |
-
client = Client(options)
|
| 46 |
-
backups = [f for f in client.list() if f.startswith('alist_backup_') and f.endswith('.tar.gz')]
|
| 47 |
-
if backups:
|
| 48 |
-
print(sorted(backups)[-1])
|
| 49 |
-
else:
|
| 50 |
-
print('')
|
| 51 |
-
")
|
| 52 |
-
|
| 53 |
-
if [ -z "$LATEST_BACKUP" ]; then
|
| 54 |
-
log "未找到备份文件"
|
| 55 |
-
return
|
| 56 |
-
fi
|
| 57 |
-
|
| 58 |
-
# 下载备份文件
|
| 59 |
-
log "下载最新备份: $LATEST_BACKUP"
|
| 60 |
-
python3 -c "
|
| 61 |
-
import requests
|
| 62 |
-
from webdav3.client import Client
|
| 63 |
-
options = {
|
| 64 |
-
'webdav_hostname': '$WEBDAV_URL',
|
| 65 |
-
'webdav_login': '$WEBDAV_USERNAME',
|
| 66 |
-
'webdav_password': '$WEBDAV_PASSWORD',
|
| 67 |
-
'webdav_root': '$WEBDAV_BACKUP_PATH'
|
| 68 |
-
}
|
| 69 |
-
client = Client(options)
|
| 70 |
-
with client.download_to_stream('$LATEST_BACKUP', '/tmp/latest_backup.tar.gz') as response:
|
| 71 |
-
with open('/tmp/latest_backup.tar.gz', 'wb') as f:
|
| 72 |
-
for chunk in response.iter_content(chunk_size=8192):
|
| 73 |
-
f.write(chunk)
|
| 74 |
-
print('备份下载完成')
|
| 75 |
-
"
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
}
|
| 88 |
|
| 89 |
-
#
|
| 90 |
-
|
| 91 |
while true; do
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
log "上传备份到 WebDAV: $BACKUP_FILE"
|
| 101 |
-
python3 -c "
|
| 102 |
from webdav3.client import Client
|
| 103 |
-
|
| 104 |
-
'webdav_hostname': '$WEBDAV_URL',
|
| 105 |
-
'webdav_login': '$WEBDAV_USERNAME',
|
| 106 |
-
'webdav_password': '$WEBDAV_PASSWORD'
|
| 107 |
-
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
"
|
| 114 |
-
|
| 115 |
-
rm -f "/tmp/$BACKUP_FILE"
|
| 116 |
-
else
|
| 117 |
-
log "数据目录不存在,跳过备份"
|
| 118 |
-
fi
|
| 119 |
-
|
| 120 |
-
# 清理旧备份
|
| 121 |
-
log "清理旧备份(保留最近 5 个)"
|
| 122 |
-
python3 -c "
|
| 123 |
-
from webdav3.client import Client
|
| 124 |
-
options = {
|
| 125 |
-
'webdav_hostname': '$WEBDAV_URL',
|
| 126 |
-
'webdav_login': '$WEBDAV_USERNAME',
|
| 127 |
-
'webdav_password': '$WEBDAV_PASSWORD',
|
| 128 |
-
'webdav_root': '$WEBDAV_BACKUP_PATH'
|
| 129 |
-
}
|
| 130 |
-
client = Client(options)
|
| 131 |
-
backups = sorted([f for f in client.list() if f.startswith('alist_backup_')], reverse=True)
|
| 132 |
-
if len(backups) > 5:
|
| 133 |
-
for f in backups[5:]:
|
| 134 |
-
client.clean(f)
|
| 135 |
-
print(f'已删除旧备份: {f}')
|
| 136 |
-
"
|
| 137 |
-
log "同步完成,等待下一次同步..."
|
| 138 |
-
sleep $SYNC_INTERVAL
|
| 139 |
done
|
| 140 |
}
|
| 141 |
|
| 142 |
-
#
|
| 143 |
-
case "$1" in
|
| 144 |
restore)
|
| 145 |
-
|
| 146 |
;;
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
log "启动 Aria2..."
|
| 150 |
-
aria2c --enable-rpc --rpc-listen-all --rpc-allow-origin-all --rpc-listen-port=6800 --daemon &
|
| 151 |
-
|
| 152 |
-
# 恢复备份
|
| 153 |
-
restore_backup &
|
| 154 |
-
|
| 155 |
-
# 启动 Alist
|
| 156 |
-
log "启动 Alist..."
|
| 157 |
-
./alist server --data /app/data &
|
| 158 |
-
|
| 159 |
-
# 启动同步任务
|
| 160 |
-
sync_backup &
|
| 161 |
-
|
| 162 |
-
# 等待所有后台任务完成(实际上不会完成)
|
| 163 |
-
wait
|
| 164 |
;;
|
| 165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
#!/bin/bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
|
| 4 |
+
# 日志记录
|
| 5 |
+
exec > >(tee -a "${LOG_DIR}/sync.log") 2>&1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
+
# WebDAV配置检查
|
| 8 |
+
check_webdav() {
|
| 9 |
+
[ -z "${WEBDAV_URL}" ] && { echo "WEBDAV_URL未设置"; return 1; }
|
| 10 |
+
[ -z "${WEBDAV_USERNAME}" ] && { echo "WEBDAV_USERNAME未设置"; return 1; }
|
| 11 |
+
[ -z "${WEBDAV_PASSWORD}" ] && { echo "WEBDAV_PASSWORD未设置"; return 1; }
|
| 12 |
+
return 0
|
| 13 |
}
|
| 14 |
|
| 15 |
+
# 恢复备份
|
| 16 |
+
restore() {
|
| 17 |
+
echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始恢复备份..."
|
| 18 |
+
check_webdav || return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
+
python3 <<EOF
|
|
|
|
| 21 |
import os
|
| 22 |
+
import sys
|
| 23 |
from webdav3.client import Client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
+
try:
|
| 26 |
+
# 初始化客户端
|
| 27 |
+
client = Client({
|
| 28 |
+
'webdav_hostname': os.getenv('WEBDAV_URL'),
|
| 29 |
+
'webdav_login': os.getenv('WEBDAV_USERNAME'),
|
| 30 |
+
'webdav_password': os.getenv('WEBDAV_PASSWORD'),
|
| 31 |
+
'verbose': True
|
| 32 |
+
})
|
| 33 |
+
|
| 34 |
+
# 查找最新备份
|
| 35 |
+
backups = [f for f in client.list()
|
| 36 |
+
if f.startswith('alist_backup_') and f.endswith('.tar.gz')]
|
| 37 |
+
if not backups:
|
| 38 |
+
print("未找到备份文件")
|
| 39 |
+
sys.exit(0)
|
| 40 |
+
|
| 41 |
+
latest = sorted(backups)[-1]
|
| 42 |
+
print(f"找到备份文件: {latest}")
|
| 43 |
+
|
| 44 |
+
# 下载备份(使用正确API)
|
| 45 |
+
local_path = f"/tmp/{latest}"
|
| 46 |
+
if client.check(latest):
|
| 47 |
+
client.download_file(latest, local_path)
|
| 48 |
+
print(f"下载完成: {local_path}")
|
| 49 |
+
else:
|
| 50 |
+
print("备份文件不存在")
|
| 51 |
+
sys.exit(1)
|
| 52 |
+
|
| 53 |
+
# 解压备份
|
| 54 |
+
os.system(f"mkdir -p {os.getenv('DATA_DIR')} {os.getenv('CONFIG_DIR')}")
|
| 55 |
+
os.system(f"tar -xzf {local_path} -C /")
|
| 56 |
+
os.remove(local_path)
|
| 57 |
+
print("恢复完成!")
|
| 58 |
+
|
| 59 |
+
except Exception as e:
|
| 60 |
+
print(f"恢复失败: {str(e)}")
|
| 61 |
+
sys.exit(1)
|
| 62 |
+
EOF
|
| 63 |
}
|
| 64 |
|
| 65 |
+
# 定时同步
|
| 66 |
+
sync() {
|
| 67 |
while true; do
|
| 68 |
+
echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始同步数据..."
|
| 69 |
+
backup_file="alist_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
|
| 70 |
+
|
| 71 |
+
# 打包数据
|
| 72 |
+
tar -czf "/tmp/${backup_file}" -C / app/data app/config
|
| 73 |
+
|
| 74 |
+
# 上传备份
|
| 75 |
+
python3 <<EOF
|
|
|
|
|
|
|
| 76 |
from webdav3.client import Client
|
| 77 |
+
client = Client({
|
| 78 |
+
'webdav_hostname': '${WEBDAV_URL}',
|
| 79 |
+
'webdav_login': '${WEBDAV_USERNAME}',
|
| 80 |
+
'webdav_password': '${WEBDAV_PASSWORD}'
|
| 81 |
+
})
|
| 82 |
+
client.upload_file('${backup_file}', '/tmp/${backup_file}')
|
| 83 |
+
print('上传成功')
|
| 84 |
+
EOF
|
| 85 |
+
|
| 86 |
+
# 清理
|
| 87 |
+
rm -f "/tmp/${backup_file}"
|
| 88 |
+
sleep ${SYNC_INTERVAL}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
done
|
| 90 |
}
|
| 91 |
|
| 92 |
+
# 执行子命令
|
| 93 |
+
case "${1:-}" in
|
| 94 |
restore)
|
| 95 |
+
restore
|
| 96 |
;;
|
| 97 |
+
sync)
|
| 98 |
+
sync
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
;;
|
| 100 |
+
*)
|
| 101 |
+
echo "Usage: $0 {restore|sync}"
|
| 102 |
+
exit 1
|
| 103 |
+
esac
|