增加备份
This commit is contained in:
@@ -37,6 +37,11 @@ DB_PATH=crypto.db
|
||||
# 交易截图上传目录
|
||||
UPLOAD_DIR=static/images
|
||||
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# BACKUP_ROOT=/root/backups
|
||||
# BACKUP_RETENTION_DAYS=30
|
||||
# BACKUP_INSTANCE=crypto_monitor_binance
|
||||
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# TOTAL_CAPITAL=100
|
||||
# 每天起始基数(U)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
# Daily backup: SQLite DB + static/images → /root/backups/<instance>/<YYYY-MM-DD>/
|
||||
# Prune backup folders older than RETENTION_DAYS (default 30).
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
BACKUP_ROOT="${BACKUP_ROOT:-/root/backups}"
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-30}"
|
||||
INSTANCE_NAME="${BACKUP_INSTANCE:-$(basename "$PROJECT_DIR")}"
|
||||
TZ_NAME="${BACKUP_TZ:-Asia/Shanghai}"
|
||||
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(TZ="$TZ_NAME" date '+%Y-%m-%d %H:%M:%S %Z')" "$*"
|
||||
}
|
||||
|
||||
read_env_var() {
|
||||
local key="$1"
|
||||
local default="$2"
|
||||
local line
|
||||
if [[ ! -f .env ]]; then
|
||||
printf '%s' "$default"
|
||||
return
|
||||
fi
|
||||
line="$(grep -E "^${key}=" .env 2>/dev/null | tail -1 || true)"
|
||||
if [[ -z "$line" ]]; then
|
||||
printf '%s' "$default"
|
||||
return
|
||||
fi
|
||||
printf '%s' "${line#*=}" | tr -d '\r'
|
||||
}
|
||||
|
||||
resolve_project_path() {
|
||||
local p="$1"
|
||||
if [[ "$p" == /* ]]; then
|
||||
printf '%s' "$p"
|
||||
else
|
||||
printf '%s' "$PROJECT_DIR/$p"
|
||||
fi
|
||||
}
|
||||
|
||||
prune_old_backups() {
|
||||
local base="$BACKUP_ROOT/$INSTANCE_NAME"
|
||||
[[ -d "$base" ]] || return 0
|
||||
local cutoff
|
||||
cutoff="$(TZ="$TZ_NAME" date -d "-${RETENTION_DAYS} days" +%Y-%m-%d 2>/dev/null || true)"
|
||||
if [[ -z "$cutoff" ]]; then
|
||||
find "$base" -mindepth 1 -maxdepth 1 -type d -mtime +"$RETENTION_DAYS" -print0 |
|
||||
xargs -r -0 rm -rf
|
||||
return 0
|
||||
fi
|
||||
local dir name
|
||||
for dir in "$base"/*/; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
name="$(basename "$dir")"
|
||||
[[ "$name" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || continue
|
||||
if [[ "$name" < "$cutoff" ]]; then
|
||||
log "prune: remove $dir (older than ${RETENTION_DAYS} days)"
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
DB_REL="$(read_env_var DB_PATH crypto.db)"
|
||||
UPLOAD_REL="$(read_env_var UPLOAD_DIR static/images)"
|
||||
BACKUP_ROOT="$(read_env_var BACKUP_ROOT "$BACKUP_ROOT")"
|
||||
RETENTION_DAYS="$(read_env_var BACKUP_RETENTION_DAYS "$RETENTION_DAYS")"
|
||||
INSTANCE_NAME="$(read_env_var BACKUP_INSTANCE "$INSTANCE_NAME")"
|
||||
|
||||
DB_PATH="$(resolve_project_path "$DB_REL")"
|
||||
UPLOAD_DIR="$(resolve_project_path "$UPLOAD_REL")"
|
||||
DATE_TAG="$(TZ="$TZ_NAME" date +%Y-%m-%d)"
|
||||
DEST="$BACKUP_ROOT/$INSTANCE_NAME/$DATE_TAG"
|
||||
|
||||
if [[ ! -f "$DB_PATH" ]]; then
|
||||
log "error: database not found: $DB_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DEST"
|
||||
log "start backup instance=$INSTANCE_NAME dest=$DEST"
|
||||
|
||||
if command -v sqlite3 >/dev/null 2>&1; then
|
||||
sqlite3 "$DB_PATH" ".backup '$DEST/crypto.db'"
|
||||
log "db: sqlite3 backup -> $DEST/crypto.db"
|
||||
else
|
||||
cp -a "$DB_PATH" "$DEST/crypto.db"
|
||||
log "db: cp -> $DEST/crypto.db (sqlite3 not installed)"
|
||||
fi
|
||||
|
||||
if [[ -d "$UPLOAD_DIR" ]]; then
|
||||
tar -czf "$DEST/static_images.tar.gz" -C "$(dirname "$UPLOAD_DIR")" "$(basename "$UPLOAD_DIR")"
|
||||
log "images: $UPLOAD_DIR -> $DEST/static_images.tar.gz"
|
||||
else
|
||||
log "warn: upload dir missing, skip images: $UPLOAD_DIR"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "instance=$INSTANCE_NAME"
|
||||
echo "project_dir=$PROJECT_DIR"
|
||||
echo "backup_date=$DATE_TAG"
|
||||
echo "db_path=$DB_PATH"
|
||||
echo "upload_dir=$UPLOAD_DIR"
|
||||
} >"$DEST/manifest.txt"
|
||||
|
||||
prune_old_backups
|
||||
log "done"
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install daily backup cron: Beijing 00:00 (CRON_TZ=Asia/Shanghai).
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
BACKUP_SCRIPT="$SCRIPT_DIR/backup_data.sh"
|
||||
INSTANCE_NAME="${BACKUP_INSTANCE:-$(basename "$PROJECT_DIR")}"
|
||||
LOG_FILE="${BACKUP_CRON_LOG:-/var/log/crypto-monitor-backup-${INSTANCE_NAME}.log}"
|
||||
if [[ ! -x "$BACKUP_SCRIPT" ]]; then
|
||||
chmod +x "$BACKUP_SCRIPT"
|
||||
fi
|
||||
|
||||
TMP="$(mktemp)"
|
||||
trap 'rm -f "$TMP"' EXIT
|
||||
|
||||
{
|
||||
crontab -l 2>/dev/null | grep -vF "$BACKUP_SCRIPT" || true
|
||||
echo "CRON_TZ=Asia/Shanghai"
|
||||
echo "0 0 * * * $BACKUP_SCRIPT >> $LOG_FILE 2>&1"
|
||||
} >"$TMP"
|
||||
|
||||
# Keep a single CRON_TZ line at top.
|
||||
awk '
|
||||
BEGIN { tz = 0 }
|
||||
/^CRON_TZ=Asia\/Shanghai$/ {
|
||||
if (tz++) next
|
||||
}
|
||||
{ print }
|
||||
' "$TMP" >"${TMP}.2"
|
||||
mv "${TMP}.2" "$TMP"
|
||||
|
||||
crontab "$TMP"
|
||||
echo "Installed cron for $INSTANCE_NAME"
|
||||
echo " Schedule : daily 00:00 Asia/Shanghai"
|
||||
echo " Script : $BACKUP_SCRIPT"
|
||||
echo " Log : $LOG_FILE"
|
||||
crontab -l | grep -F "$BACKUP_SCRIPT" || true
|
||||
@@ -106,7 +106,7 @@
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 熟悉流程再实盘。
|
||||
2. **API 权限**最小化,密钥勿泄露。
|
||||
3. **同一账户避免多程序重复开仓**。
|
||||
4. **备份数据库**后再升级迁移。
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
|
||||
5. 升级代码后留意 **首轮启动**有无数据库迁移报错。
|
||||
|
||||
---
|
||||
|
||||
@@ -30,8 +30,15 @@
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.3 节
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`。
|
||||
2. 重启服务(如 `pm2 restart`);SQLite 会在启动时自动 `ALTER` 新列。
|
||||
3. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
|
||||
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
|
||||
3. 重启服务(如 `pm2 restart`);SQLite 会在启动时自动 `ALTER` 新列。
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
|
||||
|
||||
@@ -147,7 +147,66 @@ cp .env .env.backup.$(date +%Y%m%d)
|
||||
|
||||
- **换机 / 迁移**:用 `scp` 复制整份 `.env` 到新机器对应目录;或在新机重新 `cp .env.example .env` 后填写。
|
||||
|
||||
### 5.3 必填项检查(Binance + 代理)
|
||||
### 5.3 自动备份(数据库 + 复盘图片)
|
||||
|
||||
默认每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天** 后自动删除更早的目录。
|
||||
|
||||
备份内容(路径来自 `.env` 的 `DB_PATH`、`UPLOAD_DIR`):
|
||||
|
||||
- `crypto.db`(优先 `sqlite3 .backup` 热备)
|
||||
- `static/images` 打包为 `static_images.tar.gz`
|
||||
|
||||
目录结构示例:
|
||||
|
||||
```text
|
||||
/root/backups/crypto_monitor_binance/2026-05-17/
|
||||
crypto.db
|
||||
static_images.tar.gz
|
||||
manifest.txt
|
||||
```
|
||||
|
||||
**一次性安装定时任务**(在对应项目目录执行,Binance / Gate 各执行一次):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
Gate 实例:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
Gate Bot 实例(趋势回调等):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
**立即试跑**(不写 cron):
|
||||
|
||||
```bash
|
||||
bash scripts/backup_data.sh
|
||||
```
|
||||
|
||||
日志默认:`/var/log/crypto-monitor-backup-<项目目录名>.log`。可选在 `.env` 中覆盖:`BACKUP_ROOT`、`BACKUP_RETENTION_DAYS`、`BACKUP_INSTANCE`。
|
||||
|
||||
**恢复示例**(先停 PM2,再覆盖文件):
|
||||
|
||||
```bash
|
||||
pm2 stop crypto-monitor-binance
|
||||
cp /root/backups/crypto_monitor_binance/2026-05-16/crypto.db ./crypto.db
|
||||
tar -xzf /root/backups/crypto_monitor_binance/2026-05-16/static_images.tar.gz -C .
|
||||
pm2 start ecosystem.config.cjs
|
||||
```
|
||||
|
||||
建议安装:`apt install -y sqlite3`(热备更稳)。
|
||||
|
||||
### 5.4 必填项检查(Binance + 代理)
|
||||
|
||||
与交易所相关的变量使用 **`BINANCE_`** 前缀(与代码一致)。至少确认:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user