Download sync_data.sh from flzta/flzt: direct link, hf CLI and curl.
- Browser
- Download file 6.51 kB
-
https://huggingface.co/spaces/flzta/flzt/resolve/main/sync_data.sh
- Command line
-
hf download hf://spaces/flzta/flzt/sync_data.sh
-
curl -L -o sync_data.sh https://huggingface.co/spaces/flzta/flzt/resolve/main/sync_data.sh
6.51 kB
| # 检查环境变量 | |
| if [[ -z "$HF_TOKEN" ]] || [[ -z "$DATASET_ID" ]]; then | |
| echo "Starting without backup functionality - missing HF_TOKEN or DATASET_ID" | |
| exec /opt/cloudreve/cloudreve -c /opt/cloudreve/config.ini | |
| exit 0 | |
| fi | |
| # 设置解密密钥 (请务必设置一个长且随机的字符串) | |
| ENCRYPTION_KEY=${ENCRYPTION_KEY:-"请在此处设置您的加密密钥,这是一个长且随机的字符串"} | |
| BACKUP_DELAY=${BACKUP_DELAY:-7200} # 默认备份间隔为 2 小时 | |
| # 激活虚拟环境 | |
| source /opt/venv/bin/activate | |
| # 上传备份 | |
| upload_backup() { | |
| file_path="$1" | |
| file_name="$2" | |
| token="$HF_TOKEN" | |
| repo_id="$DATASET_ID" | |
| encryption_key="$ENCRYPTION_KEY" | |
| python3 -c " | |
| from huggingface_hub import HfApi | |
| import sys | |
| import os | |
| import base64 | |
| from cryptography.fernet import Fernet | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | |
| import io | |
| def generate_key(password, salt=b'cloudreve_salt'): | |
| kdf = PBKDF2HMAC( | |
| algorithm=hashes.SHA256(), | |
| length=32, | |
| salt=salt, | |
| iterations=100000, | |
| ) | |
| key = base64.urlsafe_b64encode(kdf.derive(password.encode())) | |
| return key | |
| def encrypt_file(file_path, key): | |
| f = Fernet(key) | |
| with open(file_path, 'rb') as file: | |
| file_data = file.read() | |
| encrypted_data = f.encrypt(file_data) | |
| encrypted_file_path = file_path + '.enc' | |
| with open(encrypted_file_path, 'wb') as file: | |
| file.write(encrypted_data) | |
| return encrypted_file_path | |
| def manage_backups(api, repo_id, max_files=2): | |
| files = api.list_repo_files(repo_id=repo_id, repo_type='dataset') | |
| backup_files = [f for f in files if f.startswith('cloudreve_backup_') and f.endswith('.tar.gz.enc')] | |
| backup_files.sort() | |
| if len(backup_files) > max_files: | |
| files_to_delete = backup_files[:(len(backup_files) - max_files)] | |
| for file_to_delete in files_to_delete: | |
| try: | |
| api.delete_file(path_in_repo=file_to_delete, repo_id=repo_id, repo_type='dataset') | |
| print(f'Deleted old backup: {file_to_delete}') | |
| except Exception as e: | |
| print(f'Error deleting {file_to_delete}: {str(e)}') | |
| api = HfApi(token='$token') | |
| try: | |
| # 生成加密密钥 | |
| key = generate_key('$encryption_key') | |
| # 加密文件 | |
| encrypted_file_path = encrypt_file('$file_path', key) | |
| # 上传加密文件 | |
| api.upload_file( | |
| path_or_fileobj=encrypted_file_path, | |
| path_in_repo='$file_name.enc', | |
| repo_id='$repo_id', | |
| repo_type='dataset' | |
| ) | |
| print(f'Successfully uploaded encrypted $file_name') | |
| # 删除临时加密文件 | |
| os.remove(encrypted_file_path) | |
| # 管理备份文件数量 | |
| manage_backups(api, '$repo_id') | |
| except Exception as e: | |
| print(f'Error uploading file: {str(e)}') | |
| " | |
| } | |
| # 下载最新备份 | |
| download_latest_backup() { | |
| token="$HF_TOKEN" | |
| repo_id="$DATASET_ID" | |
| encryption_key="$ENCRYPTION_KEY" | |
| python3 -c " | |
| from huggingface_hub import HfApi | |
| import sys | |
| import os | |
| import tarfile | |
| import tempfile | |
| import base64 | |
| from cryptography.fernet import Fernet | |
| from cryptography.hazmat.primitives import hashes | |
| from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | |
| def generate_key(password, salt=b'cloudreve_salt'): | |
| kdf = PBKDF2HMAC( | |
| algorithm=hashes.SHA256(), | |
| length=32, | |
| salt=salt, | |
| iterations=100000, | |
| ) | |
| key = base64.urlsafe_b64encode(kdf.derive(password.encode())) | |
| return key | |
| def decrypt_file(encrypted_file_path, key): | |
| f = Fernet(key) | |
| with open(encrypted_file_path, 'rb') as file: | |
| encrypted_data = file.read() | |
| decrypted_data = f.decrypt(encrypted_data) | |
| decrypted_file_path = encrypted_file_path[:-4] # 移除 .enc 后缀 | |
| with open(decrypted_file_path, 'wb') as file: | |
| file.write(decrypted_data) | |
| return decrypted_file_path | |
| api = HfApi(token='$token') | |
| try: | |
| files = api.list_repo_files(repo_id='$repo_id', repo_type='dataset') | |
| backup_files = [f for f in files if f.startswith('cloudreve_backup_') and f.endswith('.tar.gz.enc')] | |
| if not backup_files: | |
| print('No backup files found') | |
| sys.exit() | |
| latest_backup = sorted(backup_files)[-1] | |
| with tempfile.TemporaryDirectory() as temp_dir: | |
| # 下载加密的备份文件 | |
| encrypted_filepath = api.hf_hub_download( | |
| repo_id='$repo_id', | |
| filename=latest_backup, | |
| repo_type='dataset', | |
| local_dir=temp_dir | |
| ) | |
| if encrypted_filepath and os.path.exists(encrypted_filepath): | |
| # 生成解密密钥 | |
| key = generate_key('$encryption_key') | |
| # 解密文件 | |
| decrypted_filepath = decrypt_file(encrypted_filepath, key) | |
| # 解压缩到目标目录 | |
| with tarfile.open(decrypted_filepath, 'r:gz') as tar: | |
| tar.extractall('/opt/cloudreve') | |
| print(f'Successfully restored backup from {latest_backup}') | |
| # 清理临时文件 | |
| os.remove(decrypted_filepath) | |
| except Exception as e: | |
| print(f'Error downloading backup: {str(e)}') | |
| " | |
| } | |
| # 首次启动时下载最新备份 | |
| echo "Checking for latest backup from HuggingFace..." | |
| download_latest_backup | |
| # 同步函数 | |
| sync_data() { | |
| local initial_backup_done=false | |
| while true; do | |
| echo "Starting sync process at $(date)" | |
| if [ "$initial_backup_done" = "true" ]; then | |
| # 在这里不进行 sleep,第一次备份后立即进入下方备份流程 | |
| fi | |
| if [ -d /opt/cloudreve ]; then | |
| timestamp=$(date +%Y%m%d_%H%M%S) | |
| backup_file="cloudreve_backup_${timestamp}.tar.gz" | |
| # 压缩整个 Cloudreve 目录 | |
| tar -czf "/tmp/${backup_file}" -C /opt/cloudreve . | |
| echo "Uploading backup to HuggingFace..." | |
| upload_backup "/tmp/${backup_file}" "${backup_file}" | |
| rm -f "/tmp/${backup_file}" | |
| initial_backup_done=true | |
| echo "Backup completed. Waiting for ${BACKUP_DELAY} seconds before the next backup." | |
| sleep "$BACKUP_DELAY" # 将 sleep 移动到这里 | |
| else | |
| echo "Cloudreve directory does not exist yet, waiting..." | |
| sleep 60 # 如果 Cloudreve 目录不存在,等待 60 秒后重试 | |
| fi | |
| done | |
| } | |
| # 后台启动同步进程 | |
| sync_data & | |
| # 启动 Cloudreve | |
| exec /opt/cloudreve/cloudreve -c /opt/cloudreve/config.ini |