aappeekk commited on
Commit
42dc41b
·
verified ·
1 Parent(s): f7564fc

Update sync_data.sh

Browse files
Files changed (1) hide show
  1. sync_data.sh +68 -61
sync_data.sh CHANGED
@@ -1,120 +1,127 @@
1
  #!/bin/bash
2
 
3
- # 路径修正
4
- PYTHON_BIN="python3"
5
- LOG_PREFIX="[Backup-System]"
 
 
 
 
6
 
7
- echo "$LOG_PREFIX 脚本启动 - 正在初始化..."
8
 
9
- # 1. 检查环境变量
10
  if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
11
- echo "$LOG_PREFIX [ERROR] 缺少 WebDAV 配置变量,将直接启动 Koishi。"
12
  yarn start
13
  exit 0
14
  fi
15
 
16
- FULL_WEBDAV_URL="${WEBDAV_URL}${WEBDAV_BACKUP_PATH:+/$WEBDAV_BACKUP_PATH}"
17
- echo "$LOG_PREFIX 目标地址: $FULL_WEBDAV_URL"
 
 
 
18
 
19
- # 2. 恢复备份逻辑
20
  restore_backup() {
21
- echo "$LOG_PREFIX [Restore] 正在连接 WebDAV 检索最新备份..."
22
  $PYTHON_BIN -c "
23
- import sys, os, tarfile, requests, subprocess
24
  from webdav3.client import Client
25
 
26
  options = {
27
- 'webdav_hostname': '${FULL_WEBDAV_URL}',
28
  'webdav_login': '${WEBDAV_USERNAME}',
29
  'webdav_password': '${WEBDAV_PASSWORD}'
30
  }
31
  client = Client(options)
 
 
32
  try:
33
- files = client.list()
34
- backups = [f for f in files if f.endswith('.tar.gz') and f.startswith('komari_backup_')]
 
 
 
35
  if not backups:
36
- print('$LOG_PREFIX [Restore] 未发现备份文件,跳过恢复过程。')
37
  sys.exit(0)
38
 
39
- latest_backup = sorted(backups)[-1]
40
- print(f'$LOG_PREFIX [Restore] 发现最新备份: {latest_backup}')
 
 
 
41
 
42
- local_path = f'/tmp/{latest_backup}'
43
- print(f'$LOG_PREFIX [Restore] 开始下载到 {local_path}...')
44
 
45
- r = requests.get(f'${FULL_WEBDAV_URL}/{latest_backup}', auth=('${WEBDAV_USERNAME}', '${WEBDAV_PASSWORD}'), stream=True)
46
  if r.status_code == 200:
 
47
  with open(local_path, 'wb') as f:
48
- for chunk in r.iter_content(chunk_size=1024*1024): # 1MB chunk
49
- if chunk: f.write(chunk)
50
 
51
- print(f'$LOG_PREFIX [Restore] 下载完成。正在解压整个 /app 目录...')
52
  with tarfile.open(local_path, 'r:gz') as tar:
53
  tar.extractall('/app')
54
- print(f'$LOG_PREFIX [Restore] 恢复成功!数据已更新。')
55
  else:
56
- print(f'$LOG_PREFIX [Restore] 下载失败,状态码: {r.status_code}')
57
  except Exception as e:
58
- print(f'$LOG_PREFIX [Restore] 异常发生: {str(e)}')
59
  "
60
  }
61
 
62
- # 3. 同步备份逻辑
63
  sync_data() {
64
  while true; do
65
- # 初始等待,防止启动瞬间就备份
66
- SYNC_INTERVAL=${SYNC_INTERVAL:-600}
67
- echo "$LOG_PREFIX [Sync] 计划在 $SYNC_INTERVAL 秒后执行下一次备份..."
68
- sleep $SYNC_INTERVAL
69
 
70
- echo "$LOG_PREFIX [Sync] ========================================"
71
- echo "$LOG_PREFIX [Sync] 开始执行备份任务: $(date)"
72
-
73
  timestamp=$(date +%Y%m%d_%H%M%S)
74
  backup_file="komari_backup_${timestamp}.tar.gz"
75
- start_time=$(date +%s)
76
-
77
- # 打包整个 /app 目录(包含 node_modules)
78
- echo "$LOG_PREFIX [Sync] 正在打包 /app (包含所有依赖)..."
79
- tar -czf "/tmp/${backup_file}" -C /app .
80
 
81
- file_size=$(du -h "/tmp/${backup_file}" | cut -f1)
82
- echo "$LOG_PREFIX [Sync] 打包完成。文件大小: $file_size"
 
 
 
 
83
 
84
- # 使用 curl 上传并显示进度 (仅在日志中显示简要)
85
- echo "$LOG_PREFIX [Sync] 正在上传到 WebDAV..."
86
- curl -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "/tmp/${backup_file}" "$FULL_WEBDAV_URL/${backup_file}" --fail --silent --show-error
87
 
88
  if [ $? -eq 0 ]; then
89
- end_time=$(date +%s)
90
- duration=$((end_time - start_time))
91
- echo "$LOG_PREFIX [Sync] 上传成功!耗时: ${duration}s"
92
-
93
- # 清理旧备份逻辑
94
- echo "$LOG_PREFIX [Clean] 正在清理 WebDAV 上的冗余备份 (保留最近 5 个)..."
95
  $PYTHON_BIN -c "
96
  from webdav3.client import Client
97
- options = {'webdav_hostname': '${FULL_WEBDAV_URL}', 'webdav_login': '${WEBDAV_USERNAME}', 'webdav_password': '${WEBDAV_PASSWORD}'}
98
  client = Client(options)
99
- backups = sorted([f for f in client.list() if f.startswith('komari_backup_') and f.endswith('.tar.gz')])
 
 
100
  if len(backups) > 5:
101
  for f in backups[:-5]:
102
- client.clean(f)
103
- print(f'$LOG_PREFIX [Clean] 已删除旧备份: {f}')
104
- else:
105
- print(f'$LOG_PREFIX [Clean] 当前备份数量 ({len(backups)}), 无需清理。')
106
  "
107
  else
108
- echo "$LOG_PREFIX [ERROR] 上传失败!请检查网络连接或 WebDAV 空间。"
109
  fi
110
-
111
  rm -f "/tmp/${backup_file}"
112
- echo "$LOG_PREFIX [Sync] ========================================"
113
  done
114
  }
115
 
116
- # 执行流程
117
  restore_backup
118
  sync_data &
119
- echo "$LOG_PREFIX 启动 Koishi 主程序..."
120
  yarn start
 
1
  #!/bin/bash
2
 
3
+ # --- 1. 环境准备 ---
4
+ # 自动识别 Python 路径
5
+ if [ -f "/app/venv/bin/python" ]; then
6
+ PYTHON_BIN="/app/venv/bin/python"
7
+ else
8
+ PYTHON_BIN="python3"
9
+ fi
10
 
11
+ LOG_PREFIX="[Backup-System]"
12
 
 
13
  if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
14
+ echo "$LOG_PREFIX 缺少变量,跳过备份逻辑直接启动。"
15
  yarn start
16
  exit 0
17
  fi
18
 
19
+ # 规范化 WebDAV URL (确保没有结尾斜杠)
20
+ CLEAN_URL=$(echo "${WEBDAV_URL}" | sed 's:/*$::')
21
+ WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-""}
22
+ # 这里的 FULL_URL 仅用于连接
23
+ FULL_WEBDAV_URL="${CLEAN_URL}${WEBDAV_BACKUP_PATH:+/$WEBDAV_BACKUP_PATH}"
24
 
25
+ # --- 2. 恢复逻辑 ---
26
  restore_backup() {
27
+ echo "$LOG_PREFIX 开始检查 WebDAV 备份..."
28
  $PYTHON_BIN -c "
29
+ import sys, os, tarfile, requests
30
  from webdav3.client import Client
31
 
32
  options = {
33
+ 'webdav_hostname': '${CLEAN_URL}',
34
  'webdav_login': '${WEBDAV_USERNAME}',
35
  'webdav_password': '${WEBDAV_PASSWORD}'
36
  }
37
  client = Client(options)
38
+ remote_dir = '${WEBDAV_BACKUP_PATH}'
39
+
40
  try:
41
+ # 使用 list 穿透到子目录
42
+ files = client.list(remote_dir) if remote_dir else client.list()
43
+ # 过滤文件名:webdav3 返回的文件可能包含路径前缀,取 os.path.basename
44
+ backups = [f for f in files if f.endswith('.tar.gz') and 'komari_backup_' in f]
45
+
46
  if not backups:
47
+ print('$LOG_PREFIX 未发现备份。')
48
  sys.exit(0)
49
 
50
+ # 找到最新的文件名
51
+ latest_file_name = sorted(backups)[-1]
52
+ # 构建完整的下载 URL
53
+ full_path = f'{remote_dir}/{latest_file_name}' if remote_dir else latest_file_name
54
+ download_url = f'${CLEAN_URL}/{full_path}'.replace('//', '/').replace(':/', '://')
55
 
56
+ print(f'$LOG_PREFIX 准备下载: {latest_file_name}')
 
57
 
58
+ r = requests.get(download_url, auth=('${WEBDAV_USERNAME}', '${WEBDAV_PASSWORD}'), stream=True)
59
  if r.status_code == 200:
60
+ local_path = f'/tmp/{latest_file_name}'
61
  with open(local_path, 'wb') as f:
62
+ for chunk in r.iter_content(chunk_size=1048576):
63
+ f.write(chunk)
64
 
65
+ print(f'$LOG_PREFIX 下载成功,解压到 /app ...')
66
  with tarfile.open(local_path, 'r:gz') as tar:
67
  tar.extractall('/app')
68
+ print(f'$LOG_PREFIX 恢复完成。')
69
  else:
70
+ print(f'$LOG_PREFIX 下载失败: HTTP {r.status_code} URL: {download_url}')
71
  except Exception as e:
72
+ print(f'$LOG_PREFIX 恢复脚本报错: {str(e)}')
73
  "
74
  }
75
 
76
+ # --- 3. 定期备份逻辑 ---
77
  sync_data() {
78
  while true; do
79
+ # 等待间隔
80
+ INTERVAL=${SYNC_INTERVAL:-600}
81
+ echo "$LOG_PREFIX 等待 $INTERVAL 秒后进行下一次同步..."
82
+ sleep $INTERVAL
83
 
 
 
 
84
  timestamp=$(date +%Y%m%d_%H%M%S)
85
  backup_file="komari_backup_${timestamp}.tar.gz"
 
 
 
 
 
86
 
87
+ echo "$LOG_PREFIX ======================================"
88
+ echo "$LOG_PREFIX 开始备份: $backup_file"
89
+
90
+ # 备份整个 /app
91
+ tar -czf "/tmp/${backup_file}" -C /app .
92
+ echo "$LOG_PREFIX 打包完成,大小: $(du -h /tmp/$backup_file | cut -f1)"
93
 
94
+ # 使用 curl 上传 (处理路径拼接)
95
+ UPLOAD_URL="${FULL_WEBDAV_URL}/${backup_file}"
96
+ curl -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "/tmp/${backup_file}" "$UPLOAD_URL" --fail
97
 
98
  if [ $? -eq 0 ]; then
99
+ echo "$LOG_PREFIX 上传成功!"
100
+ # 清理旧备份 (保留 5 )
 
 
 
 
101
  $PYTHON_BIN -c "
102
  from webdav3.client import Client
103
+ options = {'webdav_hostname': '${CLEAN_URL}', 'webdav_login': '${WEBDAV_USERNAME}', 'webdav_password': '${WEBDAV_PASSWORD}'}
104
  client = Client(options)
105
+ remote_dir = '${WEBDAV_BACKUP_PATH}'
106
+ files = client.list(remote_dir) if remote_dir else client.list()
107
+ backups = sorted([f for f in files if f.endswith('.tar.gz') and 'komari_backup_' in f])
108
  if len(backups) > 5:
109
  for f in backups[:-5]:
110
+ target = f'{remote_dir}/{f}' if remote_dir else f
111
+ client.clean(target)
112
+ print(f'$LOG_PREFIX 已删除旧备份: {f}')
 
113
  "
114
  else
115
+ echo "$LOG_PREFIX 上传失败!"
116
  fi
117
+
118
  rm -f "/tmp/${backup_file}"
119
+ echo "$LOG_PREFIX ======================================"
120
  done
121
  }
122
 
123
+ # --- 4. 启动顺序 ---
124
  restore_backup
125
  sync_data &
126
+ echo "$LOG_PREFIX 启动 Koishi..."
127
  yarn start