- Published on
饥荒联机版服务器自动备份监控脚本配置笔记
- Authors

- 作者
- 子君

饥荒联机版服务器自动备份监控脚本配置笔记
背景
在 Linux 云服务器上使用一个名为 z.sh 的二进制程序(实际为 ELF 可执行文件)来启动《饥荒联机版》(Don't Starve Together)专用服务器。z.sh 提供了一个交互式菜单,可以手动启动/停止服务器。需求是:当服务器进程结束时,自动备份存档,并按存档名称分类保存,保留最近 10 个备份,同时记录清晰的日志。
解决方案
编写一个独立的 Bash 监控脚本 monitor_and_backup.sh,配合启动脚本 start_monitor.sh,实现以下功能:
- 等待服务端进程出现,记录其 PID 和
-conf_dir参数(如DST_1) - 监控该 PID 是否退出
- 进程退出后,从
cluster.ini中读取存档名(cluster_name),清理非法字符后与时间戳组成备份文件名 - 将整个存档目录打包压缩到
/root/.klei/backup/DST_X/下 - 自动删除旧备份(保留最近 10 个)
- 日志输出到
/root/.klei/backup.log,每次运行用分隔线包裹,便于查阅 - 使用文件锁防止同一时间多个监控实例运行
- 启动脚本具备“清理旧实例”功能,避免残留进程导致新监控无法启动
文件结构
/root/
├── monitor_and_backup.sh # 监控脚本
├── start_monitor.sh # 启动监控的辅助脚本(带清理)
└── .klei/
├── DST_1/ # 存档目录(示例)
│ └── Cluster_1/
│ └── cluster.ini # 包含 cluster_name
├── backup/ # 自动备份存放目录
│ └── DST_1/
│ └── 存档名_时间戳.tar.gz
└── backup.log # 日志文件
脚本内容
1、监控脚本:/root/monitor_and_backup.sh
#!/bin/bash
# 饥荒服务端监控脚本 - 最终版
# 功能:等待服务端启动 → 等待服务端退出 → 自动备份(按 cluster_name 命名)→ 日志区块化
LOCK_FILE="/tmp/monitor_dst.lock"
exec 200>"$LOCK_FILE"
flock -n 200 || {
echo "$(date '+%Y-%m-%d %H:%M:%S') - 已有监控脚本在运行,退出" >> /root/.klei/backup.log
exit 1
}
# 配置
DST_PROCESS_NAME="dontstarve_dedicated_server_nullrenderer"
KLEI_BASE="/root/.klei"
BACKUP_BASE="$KLEI_BASE/backup"
LOG_FILE="$KLEI_BASE/backup.log"
SLEEP_INTERVAL=5
KEEP_BACKUPS=10
# 初始化
mkdir -p "$BACKUP_BASE"
touch "$LOG_FILE"
# 日志函数(自动加时间)
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# 清理旧备份(保留最近 KEEP_BACKUPS 个)
clean_old_backups() {
local backup_dir="$1"
local prefix="$2"
[ -d "$backup_dir" ] || return
cd "$backup_dir" || return
ls -t ${prefix}_*.tar.gz 2>/dev/null | tail -n +$((KEEP_BACKUPS+1)) | while read -r old; do
rm -f "$old"
log "删除旧备份: $backup_dir/$old"
done
}
# ================== 脚本开始 ==================
log ""
log "================== $(date '+%Y-%m-%d %H:%M:%S') =================="
log ""
log "监控脚本启动,等待进程 $DST_PROCESS_NAME 出现..."
# 等待进程启动,并记录 PID 和 conf_dir
while true; do
PID=$(pgrep -f "$DST_PROCESS_NAME" | head -1)
if [ -n "$PID" ]; then
log "检测到进程 PID=$PID"
CMDLINE=$(cat /proc/$PID/cmdline | tr '\0' ' ')
CONF_DIR=$(echo "$CMDLINE" | grep -oP '(?<=-conf_dir )\S+')
if [ -z "$CONF_DIR" ]; then
log "警告:未能从命令行提取 -conf_dir,使用默认 DST_1"
CONF_DIR="DST_1"
fi
log "当前存档目录: $CONF_DIR"
break
else
log "未检测到进程,继续等待..."
sleep $SLEEP_INTERVAL
fi
done
# 等待该特定 PID 退出
while kill -0 $PID 2>/dev/null; do
log "进程 $PID 仍在运行,继续监控..."
sleep $SLEEP_INTERVAL
done
# 进程已退出,执行备份
log "进程 $PID 已结束,开始备份存档..."
SRC_DIR="$KLEI_BASE/$CONF_DIR"
if [ ! -d "$SRC_DIR" ]; then
log "错误:源目录 $SRC_DIR 不存在,无法备份"
log ""
log "================== $(date '+%Y-%m-%d %H:%M:%S') =================="
log ""
exit 1
fi
# 读取 cluster_name(固定路径:Cluster_1/cluster.ini)
CLUSTER_INI="$SRC_DIR/Cluster_1/cluster.ini"
if [ -f "$CLUSTER_INI" ]; then
CLUSTER_NAME=$(grep -E '^cluster_name\s*=' "$CLUSTER_INI" | head -1 | sed -E 's/^cluster_name\s*=\s*//' | sed 's/^"//;s/"$//' | sed "s/^'//;s/'$//")
fi
if [ -z "$CLUSTER_NAME" ]; then
log "警告:未找到 cluster_name,使用 $CONF_DIR 作为备份名称"
CLUSTER_NAME="$CONF_DIR"
fi
# 清理非法字符(删除 ? * : " < > | \ / 等,空格转为下划线)
SAFE_NAME=$(echo "$CLUSTER_NAME" | tr ' ' '_' | sed 's/[][\\/*?:"<>|/]//g')
log "备份名称: $SAFE_NAME"
# 时间戳格式:年-月-日_时-分-秒
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
BACKUP_DIR="$BACKUP_BASE/$CONF_DIR"
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="$BACKUP_DIR/${SAFE_NAME}_${TIMESTAMP}.tar.gz"
log "正在备份 $SRC_DIR 到 $BACKUP_FILE"
tar -czf "$BACKUP_FILE" -C "$KLEI_BASE" "$CONF_DIR"
if [ $? -eq 0 ]; then
log "备份成功: $BACKUP_FILE"
clean_old_backups "$BACKUP_DIR" "$SAFE_NAME"
else
log "备份失败: $SRC_DIR"
log ""
log "================== $(date '+%Y-%m-%d %H:%M:%S') =================="
log ""
exit 1
fi
log "备份任务完成,监控脚本退出。"
log ""
log "================== $(date '+%Y-%m-%d %H:%M:%S') =================="
log ""
exit 0
2、启动脚本:/root/start_monitor.sh(带自动清理旧实例)
#!/bin/bash
# 启动监控脚本(带清理旧实例功能)
MONITOR_SCRIPT="/root/monitor_and_backup.sh"
LOG_FILE="/root/.klei/backup.log"
LOCK_FILE="/tmp/monitor_dst.lock"
# 1. 检查监控脚本是否存在并可执行
if [ ! -x "$MONITOR_SCRIPT" ]; then
echo "错误:监控脚本 $MONITOR_SCRIPT 不存在或不可执行"
exit 1
fi
# 2. 查找正在运行的监控脚本进程(排除 grep 自己)
OLD_PIDS=$(pgrep -f "$MONITOR_SCRIPT" | grep -v $$ || true)
if [ -n "$OLD_PIDS" ]; then
echo "发现已有监控脚本进程: $OLD_PIDS,正在终止..."
echo "$OLD_PIDS" | xargs kill -9 2>/dev/null
sleep 1
fi
# 3. 清理锁文件(如果存在)
if [ -f "$LOCK_FILE" ]; then
echo "清理残留锁文件: $LOCK_FILE"
rm -f "$LOCK_FILE"
fi
# 4. 启动新的监控脚本(后台运行)
nohup "$MONITOR_SCRIPT" >> "$LOG_FILE" 2>&1 &
NEW_PID=$!
echo "监控脚本已启动,PID=$NEW_PID"
echo "日志文件: $LOG_FILE"
使用方法
准备工作
1、确保服务器上已安装 util-linux(提供 flock 命令):
yum install -y util-linux # CentOS
# 或 apt install -y util-linux # Debian/Ubuntu
2、创建上述两个脚本文件,并赋予执行权限:
chmod +x /root/monitor_and_backup.sh
chmod +x /root/start_monitor.sh
3、确保服务端存档目录结构符合预期:/root/.klei/DST_X/Cluster_1/cluster.ini(其中 cluster.ini 包含 cluster_name = 你的世界名)
日常操作流程
1、启动游戏服务器:运行 ./z.sh(或你的启动命令),在菜单中选择“启动服务器”,然后按 Ctrl+C 退出 z.sh 界面(服务端进程会继续在后台运行)。
2、启动监控脚本(每次开服后执行一次):
/root/start_monitor.sh
3、关闭游戏服务器:可以通过 z.sh 菜单关闭,或使用命令:
pkill -f dontstarve_dedicated_server_nullrenderer
4、查看日志
tail -f /root/.klei/backup.log
5、查看备份文件
ls -lh /root/.klei/backup/DST_1/
备份文件明明规则
- 格式:
{cluster_name}_{年-月-日_时-分-秒}.tar.gz - 示例:
今年花谢,明年花谢,白了人头_2026-05-20_03-34-24.tar.gz - 非法字符(
? * : " < > | \ /)会被自动删除,空格转为下划线。
日志示例
================== 2026-05-20 03:33:59 ==================
2026-05-20 03:33:59 - 监控脚本启动,等待进程 dontstarve_dedicated_server_nullrenderer 出现...
2026-05-20 03:33:59 - 检测到进程 PID=8201
2026-05-20 03:33:59 - 当前存档目录: DST_1
2026-05-20 03:33:59 - 进程 8201 仍在运行,继续监控...
...
2026-05-20 03:34:24 - 进程 8201 已结束,开始备份存档...
2026-05-20 03:34:24 - 备份名称: 今年花谢,明年花谢,白了人头
2026-05-20 03:34:24 - 正在备份 /root/.klei/DST_1 到 /root/.klei/backup/DST_1/今年花谢,明年花谢,白了人头_2026-05-20_03-34-24.tar.gz
2026-05-20 03:34:26 - 备份成功: /root/.klei/backup/DST_1/今年花谢,明年花谢,白了人头_2026-05-20_03-34-24.tar.gz
2026-05-20 03:34:26 - 备份任务完成,监控脚本退出。
================== 2026-05-20 03:34:26 ==================
常见问题及解决
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 启动监控提示“已有监控脚本在运行” | 上次监控异常退出,锁文件残留 | 启动脚本已自动清理,或手动 rm -f /tmp/monitor_dst.lock |
| 服务端关闭后没有备份 | 监控脚本未正确运行(没有 nohup 或前台断开) | 使用 start_monitor.sh 启动,它使用 nohup 保证后台运行 |
| 备份文件名中问号等特殊字符 | cluster_name 包含非法字符 | 脚本已自动删除 ? * : " < > \ / 等,如需保留可修改清理规则 |
| 备份目录不存在 | 未初始化 | 脚本会自动创建 mkdir -p |
高级定制
- 修改保留备份数量:更改脚本中的
KEEP_BACKUPS=10。 - 修改备份压缩格式:将
tar -czf改为tar -cjf(bzip2)或tar -cJf(xz)。 - 修改检查间隔:调整
SLEEP_INTERVAL=5(秒)。 - 添加备份前的自定义操作:在
while kill -0循环之后、备份之前插入代码。
注意事项
- 该监控脚本不会在服务器启动时自动运行,需要每次开服后手动执行
/root/start_monitor.sh。如有需要,可以将该命令与开服命令合并为一个包装脚本。 - 确保服务器磁盘空间充足,定期检查
/root/.klei/backup目录大小。脚本会自动保留最近 10 个备份,但您也可以手动删除旧备份。 - 如果使用
z.sh菜单关闭服务器,请确认它是否真正杀死了服务端进程(某些菜单选项可能只是停止游戏逻辑而不退出进程)。建议使用pkill -f dontstarve_dedicated_server_nullrenderer或提供的stop_dst命令。 - 日志文件会持续增长,建议定期轮转或清理(例如使用
logrotate)。