一键脚本
- 免交互式 默认从
/var/lib/fan-webssh/backup取最新备份恢复(自动停服→清理→解压→启动)
bash <(curl -sL https://raw.githubusercontent.com/meimolihan/fan-webssh/main/scripts/fan-webssh_recover.sh) "/var/lib/fan-webssh/backup"
# 指定备份目录 + 指定文件名(精确还原)
bash <(curl -sL https://raw.githubusercontent.com/meimolihan/fan-webssh/main/scripts/fan-webssh_recover.sh) /data/bak "FanWebSSH-2026-09-17_21-00-00.tar.gz"
| 用法 | 命令 | 说明 |
|---|---|---|
| 默认还原 | ./fan-webssh_recover.sh |
从默认备份目录取最新备份 |
| 指定目录 | ./fan-webssh_recover.sh /data/bak |
从指定目录取最新备份 |
| 指定文件 | ./fan-webssh_recover.sh /data/bak FanWebSSH-xxx.tar.gz |
精确还原指定备份文件 |
补充说明
该脚本用于 fan-webssh 服务数据一键恢复。自动执行「停止服务 → 清空旧数据 → 解压备份 → 重载 systemd → 启动服务」全流程。前提:systemd 服务单元已加入 KillMode=process(install.sh 已配置),这样停止服务时只会终止主 node 进程,不会连带中断脚本自身。
功能特点
- 全自动流程:停服 → 清理 → 解压 → 启服 → 状态校验,一键完成
- 免交互设计:无需任何输入,缺省自动取最新备份
- 可选文件:支持指定精确备份文件(文件名需匹配
FanWebSSH-*.tar.gz) - 恢复前清空:先清空旧数据目录再解压,避免新旧数据残留混合
- 状态校验:恢复后自动检查服务状态(active / inactive / failed)
- 失败兜底:解压失败自动尝试重新启动服务,避免停机
- 读取安装记录:数据目录/备份目录从
/etc/fan-webssh.conf自动读取
输出说明
脚本输出包含以下内容:
| 字段 | 说明 |
|---|---|
| 备份目录 | 备份文件所在目录 |
| 数据目录 | 服务数据恢复的目标路径 |
| 恢复文件 | 实际使用的备份文件完整路径 |
| 停止服务 | 显示 systemctl stop 执行结果 |
| 执行恢复 | 显示清空+解压过程 |
| 重载配置 | 显示 systemctl daemon-reload 与启动结果 |
| 服务状态 | 恢复后服务运行状态校验结果 |
注意事项
- 需要 root 权限执行,且宿主机已安装 systemctl(systemd 发行版)
- 恢复会覆盖现有数据,建议恢复前先执行备份脚本进行数据备份
- 备份目录默认从安装记录读取,不存在配置文件时使用
${APP_DIR}/backup默认值 - 重要:需确认 systemd 单元包含
KillMode=process,否则systemctl stop的 SIGTERM 会终止当前脚本,导致恢复中断(anomaly 环境下曾出现默认模式覆盖 cgroup 所有进程的问题) - 恢复数据后需从面板重新登录,登录凭据将回滚到备份时点
- 指定还原文件存在于备份目录且文件名匹配
FanWebSSH-*.tar.gz才会执行 - 无可用备份文件时脚本直接退出,不会破坏现有数据
脚本源码
#!/bin/bash
set -uo pipefail
# ================== terminal colors ==================
list_color_init() {
export gl_hui=$'\033[38;5;59m'
export gl_hong=$'\033[38;5;9m'
export gl_lv=$'\033[38;5;10m'
export gl_huang=$'\033[38;5;11m'
export gl_lan=$'\033[38;5;32m'
export gl_bai=$'\033[38;5;15m'
export gl_zi=$'\033[38;5;13m'
export gl_bufan=$'\033[38;5;14m'
export reset=$'\033[0m'
}
list_color_init
SERVICE="fan-webssh"
CONFIG_FILE="/etc/fan-webssh.conf"
APP_DIR="/var/lib/fan-webssh"
DATA_DIR="/var/lib/fan-webssh/app/db"
# 从安装记录读取安装目录/数据目录/备份目录(不存在时使用默认值)
BACKUP_DIR=""
if [ -f "${CONFIG_FILE}" ]; then
while IFS='=' read -r KEY VALUE; do
KEY=$(printf '%s' "$KEY" | tr -d ' ')
[ "$KEY" = "APP_DIR" ] && [ -n "$VALUE" ] && APP_DIR="${VALUE}"
[ "$KEY" = "DATA_DIR" ] && [ -n "$VALUE" ] && DATA_DIR="${VALUE}"
[ "$KEY" = "BACKUP_DIR" ] && [ -n "$VALUE" ] && BACKUP_DIR="${VALUE}"
done < "${CONFIG_FILE}"
fi
BACKUP_DIR="${BACKUP_DIR:-${APP_DIR}/backup}"
# 参数解析:1) 备份目录 2) 指定还原文件(可选,缺省取最新备份)
# 用法:
# ./fan-webssh_recover.sh # 默认目录,取该目录最新备份
# ./fan-webssh_recover.sh /data/bak [文件名] # 指定目录,可选指定文件
parse_args() {
local p1="${1:-}"
local p2="${2:-}"
if [[ -n "${p1}" ]]; then
BACKUP_DIR="${p1}"
fi
if [[ -n "${p2}" ]]; then
RESTORE_FILE_ARG="${p2}"
fi
}
RESTORE_FILE_ARG=""
parse_args "$@"
echo -e "${gl_zi}>>> fan-webssh 恢复脚本${gl_bai}"
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
echo -e "${gl_huang}备份目录:${gl_lv}${BACKUP_DIR}${gl_bai}"
echo -e "${gl_huang}数据目录:${gl_lv}${DATA_DIR}${gl_bai}"
command -v systemctl >/dev/null 2>&1 || { echo -e "${gl_hong}❌ 未检测到 systemctl,无法恢复服务${gl_bai}"; exit 1; }
mkdir -p "${BACKUP_DIR}"
echo -e ""
if [ -n "${RESTORE_FILE_ARG}" ]; then
echo -e "${gl_lan}>>> 使用指定备份文件${gl_bai}"
if [[ "${RESTORE_FILE_ARG}" =~ ^FanWebSSH-.*\.tar\.gz$ ]] && [ -f "${BACKUP_DIR}/${RESTORE_FILE_ARG}" ]; then
f="${RESTORE_FILE_ARG}"
else
echo -e "${gl_hong}❌ 指定的备份文件不存在: ${RESTORE_FILE_ARG}${gl_bai}"
exit 1
fi
else
echo -e "${gl_lan}>>> 查找最新备份文件${gl_bai}"
f=$(find "$BACKUP_DIR" -maxdepth 1 -type f -name "FanWebSSH-*.tar.gz" -printf "%f\n" \
| sed -E 's/^FanWebSSH-([0-9]{4}-[0-9]{2}-[0-9]{2}(_[0-9]{2}-[0-9]{2}-[0-9]{2})?)\.tar\.gz$/\1 &/' \
| sort -k1,1 \
| tail -n1 \
| awk '{print $2}')
fi
if [ -z "$f" ];then
echo -e "${gl_hong}❌ 无备份文件,退出${gl_bai}"
exit 1
fi
RESTORE_FILE="${BACKUP_DIR}/${f}"
echo -e "${gl_huang}恢复文件: ${gl_lv}${RESTORE_FILE}${gl_bai}"
echo -e ""
echo -e "${gl_huang}>>> 停止 ${SERVICE} 服务${gl_bai}"
systemctl stop ${SERVICE}
echo -e ""
echo -e "${gl_huang}>>> 执行恢复${gl_bai}"
# 备份内容为数据目录下所有内容;恢复前先清空旧数据目录,避免残留文件
find "${DATA_DIR}" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true
mkdir -p "${DATA_DIR}"
if tar -xzf "${RESTORE_FILE}" -C "${DATA_DIR}"; then
echo -e "${gl_lv}>>> 恢复完成${gl_bai}"
else
echo -e "${gl_hong}❌ 恢复失败,正在启动服务${gl_bai}"
systemctl start ${SERVICE}
exit 1
fi
echo -e ""
echo -e "${gl_huang}>>> 重载systemd配置并启动服务${gl_bai}"
systemctl daemon-reload
systemctl start ${SERVICE}
sleep 2
STATUS=$(systemctl is-active ${SERVICE})
case "${STATUS}" in
active)
echo -e "${gl_lv}✅ 服务状态:运行中${gl_bai}"
;;
inactive)
echo -e "${gl_hong}❌ 服务状态:已停止${gl_bai}"
;;
failed)
echo -e "${gl_hong}❌ 服务状态:启动失败${gl_bai}"
;;
*)
echo -e "${gl_huang}⚠️ 服务状态:${STATUS}${gl_bai}"
;;
esac
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
创建本地脚本
new_script="new_test.sh"
cat > "$new_script" << 'EOF'
#!/bin/bash
# 粘贴脚本源码
EOF
chmod +x "$new_script" && ./"$new_script" && rm -f "$new_script"