HuggingFace0920 commited on
Commit
2728cdc
·
verified ·
1 Parent(s): 9cbb6de

Create sync_data.sh

Browse files
Files changed (1) hide show
  1. sync_data.sh +357 -0
sync_data.sh ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ # 添加更详细的日志
4
+ log_info() {
5
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1"
6
+ }
7
+
8
+ log_error() {
9
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1"
10
+ }
11
+
12
+ # 检查环境变量
13
+ if [ -z "$HF_TOKEN" ] || [ -z "$DATASET_ID" ]; then
14
+ log_error "未启用备份功能 - 缺少HF_TOKEN或DATASET_ID环境变量"
15
+ log_info "HF_TOKEN=${HF_TOKEN:0:3}... DATASET_ID=${DATASET_ID}"
16
+ exit 0
17
+ fi
18
+
19
+ # 创建临时目录
20
+ TEMP_DIR="/tmp/sillytavern_backup"
21
+ DATA_DIR="/home/node/app/data"
22
+
23
+ # 确保目录存在并有正确权限
24
+ mkdir -p $TEMP_DIR
25
+ chmod -R 777 $TEMP_DIR
26
+ mkdir -p $DATA_DIR
27
+ chmod -R 777 $DATA_DIR
28
+
29
+ log_info "临时目录: $TEMP_DIR"
30
+ log_info "数据目录: $DATA_DIR"
31
+ log_info "HF_TOKEN: ${HF_TOKEN:0:5}..."
32
+ log_info "DATASET_ID: $DATASET_ID"
33
+
34
+ # 安装python和huggingface_hub
35
+ if ! command -v python3 > /dev/null 2>&1; then
36
+ log_info "正在安装Python..."
37
+ apk add --no-cache python3 py3-pip
38
+ else
39
+ log_info "Python3已安装: $(python3 --version)"
40
+ fi
41
+
42
+ # 确保pip已安装
43
+ if ! command -v pip3 > /dev/null 2>&1; then
44
+ log_info "正在安装pip..."
45
+ apk add --no-cache py3-pip
46
+ else
47
+ log_info "Pip3已安装: $(pip3 --version)"
48
+ fi
49
+
50
+ # 安装或更新huggingface_hub
51
+ log_info "正在安装/更新huggingface_hub..."
52
+ pip3 install --no-cache-dir --upgrade huggingface_hub
53
+ log_info "huggingface_hub安装完成"
54
+
55
+ # 测试huggingface_hub是否正常工作
56
+ if ! python3 -c "import huggingface_hub; print('huggingface_hub版本:', huggingface_hub.__version__)" > /dev/null 2>&1; then
57
+ log_error "huggingface_hub导入失败,正在重试安装..."
58
+ pip3 install --no-cache-dir huggingface_hub
59
+ fi
60
+
61
+ # 测试权限是否正常
62
+ touch "${TEMP_DIR}/test_file" && rm "${TEMP_DIR}/test_file"
63
+ if [ $? -ne 0 ]; then
64
+ log_error "临时目录权限测试失败,正在修复权限..."
65
+ chmod -R 777 $TEMP_DIR
66
+ fi
67
+
68
+ # 测试与HuggingFace API的连接
69
+ log_info "正在测试与HuggingFace API的连接..."
70
+ python3 -c "
71
+ from huggingface_hub import HfApi
72
+ try:
73
+ api = HfApi(token='$HF_TOKEN')
74
+ user_info = api.whoami()
75
+ print(f'成功连接到HuggingFace API,用户: {user_info}')
76
+ except Exception as e:
77
+ print(f'连接HuggingFace API失败: {str(e)}')
78
+ exit(1)
79
+ "
80
+ if [ $? -ne 0 ]; then
81
+ log_error "HuggingFace API连接测试失败,请检查令牌是否有效"
82
+ else
83
+ log_info "HuggingFace API连接测试成功"
84
+ fi
85
+
86
+ # 生成唯一的测试文件名
87
+ TEST_FILE_NAME="test_file_$(date +%s)"
88
+
89
+ # 测试数据集权限
90
+ log_info "正在测试Dataset权限..."
91
+ python3 -c "
92
+ from huggingface_hub import HfApi
93
+ try:
94
+ api = HfApi(token='$HF_TOKEN')
95
+
96
+ # 创建本地测试文件
97
+ with open('$TEMP_DIR/test_file', 'w') as f:
98
+ f.write('test')
99
+
100
+ # 上传测试文件
101
+ test_file_name = '$TEST_FILE_NAME'
102
+ print(f'正在上传测试文件: {test_file_name}')
103
+
104
+ api.upload_file(
105
+ path_or_fileobj='$TEMP_DIR/test_file',
106
+ path_in_repo=test_file_name,
107
+ repo_id='$DATASET_ID',
108
+ repo_type='dataset'
109
+ )
110
+ print('成功上传测试文件到Dataset')
111
+
112
+ # 删除已上传的测试文件
113
+ print('正在删除测试文件...')
114
+ api.delete_file(
115
+ path_in_repo=test_file_name,
116
+ repo_id='$DATASET_ID',
117
+ repo_type='dataset'
118
+ )
119
+ print('已成功删除测试文件')
120
+
121
+ except Exception as e:
122
+ print(f'Dataset权限测试失败: {str(e)}')
123
+ exit(1)
124
+ "
125
+ if [ $? -ne 0 ]; then
126
+ log_error "Dataset权限测试失败,请检查DATASET_ID是否正确且有写入权限"
127
+ else
128
+ log_info "Dataset权限测试成功,测试文件已清理"
129
+ fi
130
+
131
+ # 确保本地测试文件被删除
132
+ rm -f "$TEMP_DIR/test_file"
133
+
134
+ # 上传备份
135
+ upload_backup() {
136
+ file_path="$1"
137
+ file_name="$2"
138
+
139
+ if [ ! -f "$file_path" ]; then
140
+ log_error "备份文件不存在: $file_path"
141
+ return 1
142
+ fi
143
+
144
+ log_info "开始上传备份: $file_name ($(du -h $file_path | cut -f1))"
145
+
146
+ python3 -c "
147
+ from huggingface_hub import HfApi
148
+ import sys
149
+ import os
150
+ import time
151
+ def manage_backups(api, repo_id, max_files=10):
152
+ try:
153
+ files = api.list_repo_files(repo_id=repo_id, repo_type='dataset')
154
+ backup_files = [f for f in files if f.startswith('sillytavern_backup_') and f.endswith('.tar.gz')]
155
+ backup_files.sort()
156
+
157
+ if len(backup_files) >= max_files:
158
+ files_to_delete = backup_files[:(len(backup_files) - max_files + 1)]
159
+ for file_to_delete in files_to_delete:
160
+ try:
161
+ api.delete_file(path_in_repo=file_to_delete, repo_id=repo_id, repo_type='dataset')
162
+ print(f'已删除旧备份: {file_to_delete}')
163
+ except Exception as e:
164
+ print(f'删除 {file_to_delete} 时出错: {str(e)}')
165
+ except Exception as e:
166
+ print(f'管理备份文件时出错: {str(e)}')
167
+ token='$HF_TOKEN'
168
+ repo_id='$DATASET_ID'
169
+ try:
170
+ api = HfApi(token=token)
171
+
172
+ # ���查文件大小
173
+ file_size = os.path.getsize('$file_path')
174
+ print(f'备份文件大小: {file_size / (1024*1024):.2f} MB')
175
+ # 确认Dataset存在
176
+ try:
177
+ dataset_info = api.dataset_info(repo_id=repo_id)
178
+ print(f'Dataset信息: {dataset_info.id}')
179
+ except Exception as e:
180
+ print(f'获取Dataset信息失败: {str(e)}')
181
+
182
+ start_time = time.time()
183
+ print(f'开始上传: {start_time}')
184
+
185
+ # 上传文件
186
+ api.upload_file(
187
+ path_or_fileobj='$file_path',
188
+ path_in_repo='$file_name',
189
+ repo_id=repo_id,
190
+ repo_type='dataset'
191
+ )
192
+
193
+ end_time = time.time()
194
+ print(f'上传完成,耗时: {end_time - start_time:.2f} 秒')
195
+ print(f'成功上传 $file_name')
196
+
197
+ # 管理备份
198
+ manage_backups(api, repo_id)
199
+ except Exception as e:
200
+ print(f'上传文件时出错: {str(e)}')
201
+ sys.exit(1)
202
+ "
203
+ if [ $? -ne 0 ]; then
204
+ log_error "备份上传失败"
205
+ return 1
206
+ else
207
+ log_info "备份上传成功"
208
+ return 0
209
+ fi
210
+ }
211
+
212
+ # 下载最新备份
213
+ download_latest_backup() {
214
+ log_info "开始下载最新备份..."
215
+
216
+ python3 -c "
217
+ from huggingface_hub import HfApi
218
+ import sys
219
+ import os
220
+ import tarfile
221
+ import tempfile
222
+ import time
223
+ try:
224
+ api = HfApi(token='$HF_TOKEN')
225
+ print('已创建API实例')
226
+
227
+ # 列出仓库文件
228
+ try:
229
+ files = api.list_repo_files(repo_id='$DATASET_ID', repo_type='dataset')
230
+ print(f'仓库文件数量: {len(files)}')
231
+ except Exception as e:
232
+ print(f'列出仓库文件失败: {str(e)}')
233
+ sys.exit(1)
234
+
235
+ backup_files = [f for f in files if f.startswith('sillytavern_backup_') and f.endswith('.tar.gz')]
236
+ print(f'找到备份文件数量: {len(backup_files)}')
237
+
238
+ if not backup_files:
239
+ print('未找到备份文件')
240
+ sys.exit(0)
241
+
242
+ # 按名称排序(实际上是按时间戳排序)
243
+ latest_backup = sorted(backup_files)[-1]
244
+ print(f'最新备份文件: {latest_backup}')
245
+
246
+ with tempfile.TemporaryDirectory() as temp_dir:
247
+ print(f'创建临时目录: {temp_dir}')
248
+
249
+ start_time = time.time()
250
+ print(f'开始下载: {start_time}')
251
+
252
+ # 下载文件
253
+ try:
254
+ filepath = api.hf_hub_download(
255
+ repo_id='$DATASET_ID',
256
+ filename=latest_backup,
257
+ repo_type='dataset',
258
+ local_dir=temp_dir
259
+ )
260
+ print(f'文件下载到: {filepath}')
261
+ except Exception as e:
262
+ print(f'下载文件失败: {str(e)}')
263
+ sys.exit(1)
264
+
265
+ end_time = time.time()
266
+ print(f'下载完成,耗时: {end_time - start_time:.2f} 秒')
267
+
268
+ if filepath and os.path.exists(filepath):
269
+ # 确保目标目录存在
270
+ os.makedirs('$DATA_DIR', exist_ok=True)
271
+
272
+ # 检查文件权限
273
+ print(f'文件权限: {oct(os.stat(filepath).st_mode)[-3:]}')
274
+
275
+ # 解压文件
276
+ try:
277
+ with tarfile.open(filepath, 'r:gz') as tar:
278
+ print('开始解压文件...')
279
+ tar.extractall('$DATA_DIR')
280
+ print('文件解压完成')
281
+ except Exception as e:
282
+ print(f'解压文件失败: {str(e)}')
283
+ sys.exit(1)
284
+
285
+ print(f'成功从 {latest_backup} 恢复备份')
286
+ else:
287
+ print('下载的文件路径无效')
288
+ sys.exit(1)
289
+ except Exception as e:
290
+ print(f'下载备份过程中出错: {str(e)}')
291
+ sys.exit(1)
292
+ "
293
+ if [ $? -ne 0 ]; then
294
+ log_error "备份下载失败"
295
+ return 1
296
+ else
297
+ log_info "备份下载成功"
298
+ return 0
299
+ fi
300
+ }
301
+
302
+ # 首次启动时下载最新备份
303
+ log_info "正在从HuggingFace下载最新备份..."
304
+ download_latest_backup
305
+
306
+ # 同步函数
307
+ sync_data() {
308
+ log_info "数据同步服务已启动"
309
+
310
+ while true; do
311
+ log_info "开始同步进程,时间: $(date)"
312
+
313
+ if [ -d "$DATA_DIR" ]; then
314
+ timestamp=$(date +%Y%m%d_%H%M%S)
315
+ backup_file="sillytavern_backup_${timestamp}.tar.gz"
316
+ backup_path="${TEMP_DIR}/${backup_file}"
317
+
318
+ log_info "创建备份文件: $backup_path"
319
+
320
+ # 检查数据目录内容
321
+ file_count=$(find "$DATA_DIR" -type f | wc -l)
322
+ log_info "数据目录文件数量: $file_count"
323
+
324
+ if [ "$file_count" -eq 0 ]; then
325
+ log_info "数据目录为空,跳过备份"
326
+ else
327
+ # 压缩数据目录
328
+ tar -czf "$backup_path" -C "$DATA_DIR" .
329
+ if [ $? -ne 0 ]; then
330
+ log_error "创建压缩文件失败"
331
+ else
332
+ log_info "压缩文件创建成功: $(du -h $backup_path | cut -f1)"
333
+
334
+ # 上传备份
335
+ log_info "正在上传备份到HuggingFace..."
336
+ upload_backup "$backup_path" "$backup_file"
337
+
338
+ # 删除临时备份文件
339
+ rm -f "$backup_path"
340
+ log_info "已删除临时备份文件"
341
+ fi
342
+ fi
343
+ else
344
+ log_error "数据目录不存在: $DATA_DIR"
345
+ mkdir -p "$DATA_DIR"
346
+ chmod -R 777 "$DATA_DIR"
347
+ fi
348
+
349
+ # 设置同步间隔
350
+ SYNC_INTERVAL=${SYNC_INTERVAL:-3600}
351
+ log_info "下次同步将在 ${SYNC_INTERVAL} 秒后进行..."
352
+ sleep $SYNC_INTERVAL
353
+ done
354
+ }
355
+
356
+ # 启动同步进程
357
+ sync_data