Skip to content

Instantly share code, notes, and snippets.

@LittleSaya
Created February 1, 2024 14:38
Show Gist options
  • Save LittleSaya/ff220665c1349f8d4443a4f014937698 to your computer and use it in GitHub Desktop.
Save LittleSaya/ff220665c1349f8d4443a4f014937698 to your computer and use it in GitHub Desktop.
Palworld dedicated server save backup and daemon script
@REM PalServer 存档自动备份脚本
@REM Auther: LittleSaya
@echo off
setlocal EnableDelayedExpansion
title Palserver Backup Script
@REM 服务器路径(常量)
set __PALSERVER_DIR__=D:\Program Files (x86)\Steam\steamapps\common\PalServer
@REM 备份文件存放目录(常量)
set __STORE_DIR__=F:\palserver\backup_1
@REM 备份时间间隔(秒)(常量)
set __INTERVAL__=10
:LBL_BEGIN
@REM 当前时间
set _CURRENT_YEAR_=%date:~0,4%
set _CURRENT_MONTH_=%date:~5,2%
set _CURRENT_DAY_=%date:~8,2%
set _CURRENT_HOUR_=%time:~0,2%
set _CURRENT_MINUTE_=%time:~3,2%
set _CURRENT_SECOND_=%time:~6,2%
@REM 把空格替换成 0
set _CURRENT_YEAR_=%_CURRENT_YEAR_: =0%
set _CURRENT_MONTH_=%_CURRENT_MONTH_: =0%
set _CURRENT_DAY_=%_CURRENT_DAY_: =0%
set _CURRENT_HOUR_=%_CURRENT_HOUR_: =0%
set _CURRENT_MINUTE_=%_CURRENT_MINUTE_: =0%
set _CURRENT_SECOND_=%_CURRENT_SECOND_: =0%
@REM 用于在命令提示符中显示的时间字符串
set _CURRENT_TIME_ECHO_=%_CURRENT_YEAR_%/%_CURRENT_MONTH_%/%_CURRENT_DAY_% %_CURRENT_HOUR_%:%_CURRENT_MINUTE_%:%_CURRENT_SECOND_%
@REM 用于文件系统的日期字符串
set _CURRENT_DATE_FS_=%_CURRENT_YEAR_%_%_CURRENT_MONTH_%_%_CURRENT_DAY_%
@REM 用于文件系统的时间字符串
set _CURRENT_TIME_FS_=%_CURRENT_HOUR_%_%_CURRENT_MINUTE_%_%_CURRENT_SECOND_%
echo backup start at %_CURRENT_TIME_ECHO_%
set _NEW_BACKUP_DATE_=%_CURRENT_DATE_FS_%
set _NEW_BACKUP_DIR_=Saved-%_CURRENT_TIME_FS_%
@REM 进入存储目录,检查当天的文件夹是否存在,如果不存在,则创建
cd /d %__STORE_DIR__%
for /f "tokens=1,2,3,4" %%a in ('dir /a:d . ^| findstr %_CURRENT_DATE_FS_%') do (
goto LBL_SKIP_CREATE_DATE_DIR
)
mkdir %_NEW_BACKUP_DATE_%
:LBL_SKIP_CREATE_DATE_DIR
@REM 创建新的备份文件夹
cd %_NEW_BACKUP_DATE_%
mkdir %_NEW_BACKUP_DIR_%
@REM 回到服务器目录,复制 Saved 文件夹到存储目录
cd /d %__PALSERVER_DIR__%\Pal
robocopy Saved %__STORE_DIR__%\%_NEW_BACKUP_DATE_%\%_NEW_BACKUP_DIR_% /e
timeout /T %__INTERVAL__% /NOBREAK
goto LBL_BEGIN
@REM PalServer 存档自动备份脚本(7z版)
@REM Auther: LittleSaya
@echo off
setlocal EnableDelayedExpansion
title Palserver Backup Script
@REM 服务器路径(常量)
set __PALSERVER_DIR__=D:\Program Files (x86)\Steam\steamapps\common\PalServer
@REM 备份文件存放目录(常量)
set __STORE_DIR__=F:\palserver\backup_1
@REM 备份时间间隔(秒)(常量)
set __INTERVAL__=10
:LBL_BEGIN
@REM 当前时间
set _CURRENT_YEAR_=%date:~0,4%
set _CURRENT_MONTH_=%date:~5,2%
set _CURRENT_DAY_=%date:~8,2%
set _CURRENT_HOUR_=%time:~0,2%
set _CURRENT_MINUTE_=%time:~3,2%
set _CURRENT_SECOND_=%time:~6,2%
@REM 把空格替换成 0
set _CURRENT_YEAR_=%_CURRENT_YEAR_: =0%
set _CURRENT_MONTH_=%_CURRENT_MONTH_: =0%
set _CURRENT_DAY_=%_CURRENT_DAY_: =0%
set _CURRENT_HOUR_=%_CURRENT_HOUR_: =0%
set _CURRENT_MINUTE_=%_CURRENT_MINUTE_: =0%
set _CURRENT_SECOND_=%_CURRENT_SECOND_: =0%
@REM 用于在命令提示符中显示的时间字符串
set _CURRENT_TIME_ECHO_=%_CURRENT_YEAR_%/%_CURRENT_MONTH_%/%_CURRENT_DAY_% %_CURRENT_HOUR_%:%_CURRENT_MINUTE_%:%_CURRENT_SECOND_%
@REM 用于文件夹名称的时间字符串
set _CURRENT_TIME_DIR_=%_CURRENT_YEAR_%_%_CURRENT_MONTH_%_%_CURRENT_DAY_%
@REM 用于文件名称的时间字符串
set _CURRENT_TIME_FILE_=%_CURRENT_HOUR_%_%_CURRENT_MINUTE_%_%_CURRENT_SECOND_%
echo backup start at %_CURRENT_TIME_ECHO_%
set _HAS_BACKUP_=
set _MAX_TIMESTAMP_=
set _DATE_=
set _TIME_=
set _SIZE_=
set _NAME_=
set _YEAR_=
set _MONTH_=
set _DAY_=
set _HOUR_=
set _MINUTE_=
set _SECOND_=
set _TIMESTAMP_=
set _LAST_BACKUP_DIR_=
set _LAST_BACKUP_FILE_=
set _LAST_HASH_=
set _NEW_BACKUP_DIR_=%_CURRENT_TIME_DIR_%
set _NEW_BACKUP_FILE_=Saved-%_CURRENT_TIME_FILE_%.zip
set _NEW_HASH_=
@REM 寻找上一次的备份(文件路径形如 2024_01_27/Saved-18_02_56.zip )
cd /d %__STORE_DIR__%
set _HAS_BACKUP_=0
@REM 日期最新的子文件夹(有文件夹 <=> 有备份)
set _MAX_TIMESTAMP_=0
for /f "tokens=1,2,3,4" %%a in ('dir /a:d . ^| findstr /r "[0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9]"') do (
set _DATE_=%%a
set _TIME_=%%b
set _SIZE_=%%c
set _NAME_=%%d
set _HAS_BACKUP_=1
set _YEAR_=!_NAME_:~0,4!
set _MONTH_=!_NAME_:~5,2!
set _DAY_=!_NAME_:~8,2!
set _TIMESTAMP_=!_YEAR_!!_MONTH_!!_DAY_!
if !_TIMESTAMP_! gtr !_MAX_TIMESTAMP_! (
set _MAX_TIMESTAMP_=!_TIMESTAMP_!
set _LAST_BACKUP_DIR_=!_NAME_!
)
)
if %_HAS_BACKUP_% equ 0 (
echo no backup found
)
@REM 如果有备份文件夹,则进入,并获取上一次备份的文件名称和 hash
if %_HAS_BACKUP_% equ 1 (
cd !_LAST_BACKUP_DIR_!
set _MAX_TIMESTAMP_=0
for /f "tokens=1,2,3,4" %%a in ('dir . ^| findstr /r "Saved-[0-9][0-9]_[0-9][0-9]_[0-9][0-9]\.zip"') do (
set _DATE_=%%a
set _TIME_=%%b
set _SIZE_=%%c
set _NAME_=%%d
set _HOUR_=!_NAME_:~6,2!
set _MINUTE_=!_NAME_:~9,2!
set _SECOND_=!_NAME_:~12,2!
set _TIMESTAMP_=!_HOUR_!!_MINUTE_!!_SECOND_!
if !_TIMESTAMP_! gtr !_MAX_TIMESTAMP_! (
set _MAX_TIMESTAMP_=!_TIMESTAMP_!
set _LAST_BACKUP_FILE_=!_NAME_!
)
)
for /f "skip=1 tokens=1" %%a in ('certutil -hashfile !_LAST_BACKUP_FILE_! SHA256') do (
set _LAST_HASH_=%%a
echo last hash: !_LAST_HASH_!
goto LBL_EXIT_LOOP_HASH
)
)
:LBL_EXIT_LOOP_HASH
if %_HAS_BACKUP_% equ 1 (
@REM 回到存储目录
cd ..
)
@REM 如果新旧文件名相同,则跳过备份
echo new backup path: %_NEW_BACKUP_DIR_%\%_NEW_BACKUP_FILE_%
if %_HAS_BACKUP_% equ 1 (
if "%_NEW_BACKUP_DIR_%\%_NEW_BACKUP_FILE_%" equ "%_LAST_BACKUP_DIR_%\%_LAST_BACKUP_FILE_%" (
echo skip backup due to duplicated file name
goto LBL_SKIP_BACKUP
)
)
@REM 如果没有备份,或者日期发生变化,则创建新目录
if %_HAS_BACKUP_% equ 0 (
mkdir %_NEW_BACKUP_DIR_%
) else (
if "%_NEW_BACKUP_DIR_%" neq "%_LAST_BACKUP_DIR_%" (
mkdir %_NEW_BACKUP_DIR_%
)
)
@REM 回到服务器目录,生成新备份文件
cd /d %__PALSERVER_DIR__%
cd Pal
7z a %_NEW_BACKUP_FILE_% Saved >nul 2>&1
@REM 计算新文件的 hash
for /f "skip=1 tokens=1" %%a in ('certutil -hashfile %_NEW_BACKUP_FILE_% SHA256') do (
set _NEW_HASH_=%%a
echo new hash: !_NEW_HASH_!
goto LBL_EXIT_LOOP_HASH_2
)
:LBL_EXIT_LOOP_HASH_2
@REM 如果新旧文件 hash 相同,则删除刚刚生成的备份,并跳过备份
if "%_NEW_HASH_%" equ "%_LAST_HASH_%" (
echo new backup deleted due to duplicated file hash
del %_NEW_BACKUP_FILE_%
goto LBL_SKIP_BACKUP
)
@REM 否则,将备份文件移动到存储目录下
move %_NEW_BACKUP_FILE_% %__STORE_DIR__%\%_NEW_BACKUP_DIR_%
:LBL_SKIP_BACKUP
echo backup end
echo:
timeout /T %__INTERVAL__% /NOBREAK
goto LBL_BEGIN
@REM PalServer 进程守护脚本
@REM Auther: LittleSaya
@echo off
setlocal EnableDelayedExpansion
title Palserver Daemon Script
@REM PalServer 的映像名称,用于检测进程是否存在
set __IMAGE_NAME__=PalServer.exe
@REM 检测间隔(秒)
set __INTERVAL__=10
@REM 启动服务器的命令
set __START_SERVER__=start steam://rungameid/2394010
:LBL_BEGIN
@REM 当前时间
set _CURRENT_YEAR_=%date:~0,4%
set _CURRENT_MONTH_=%date:~5,2%
set _CURRENT_DAY_=%date:~8,2%
set _CURRENT_HOUR_=%time:~0,2%
set _CURRENT_MINUTE_=%time:~3,2%
set _CURRENT_SECOND_=%time:~6,2%
@REM 把空格替换成 0
set _CURRENT_YEAR_=%_CURRENT_YEAR_: =0%
set _CURRENT_MONTH_=%_CURRENT_MONTH_: =0%
set _CURRENT_DAY_=%_CURRENT_DAY_: =0%
set _CURRENT_HOUR_=%_CURRENT_HOUR_: =0%
set _CURRENT_MINUTE_=%_CURRENT_MINUTE_: =0%
set _CURRENT_SECOND_=%_CURRENT_SECOND_: =0%
@REM 用于在命令提示符中显示的时间字符串
set _CURRENT_TIME_ECHO_=%_CURRENT_YEAR_%/%_CURRENT_MONTH_%/%_CURRENT_DAY_% %_CURRENT_HOUR_%:%_CURRENT_MINUTE_%:%_CURRENT_SECOND_%
set _IMAGE_NAME=
set _PID=
set _SESSION_NAME=
set _SESSION_NO=
set _MEMORY_COST=
set _MEMORY_COST_UNIT=
set _IS_RUNNING=
@REM 检测服务器进程是否存在
set _IS_RUNNING=1
for /f "tokens=1,2,3,4,5,6" %%a in ('tasklist /fi "imagename eq %__IMAGE_NAME__%" /nh') do (
set _IMAGE_NAME=%%a
set _PID=%%b
set _SESSION_NAME=%%c
set _SESSION_NO=%%d
set _MEMORY_COST=%%e
set _MEMORY_COST_UNIT=%%f
if "!_IMAGE_NAME!" neq "%__IMAGE_NAME__%" (
set _IS_RUNNING=0
)
goto LBL_EXIT_LOOP_IS_RUNNING
)
:LBL_EXIT_LOOP_IS_RUNNING
@REM 如果进程存在就跳过重启步骤
if %_IS_RUNNING% equ 1 (
echo %_CURRENT_TIME_ECHO_%: server is running
goto LBL_SKIP_RESTART
) else (
echo %_CURRENT_TIME_ECHO_%: server is not running
)
@REM 重启服务器
echo %_CURRENT_TIME_ECHO_%: start server with command: %__START_SERVER__%
%__START_SERVER__%
:LBL_SKIP_RESTART
timeout /T %__INTERVAL__% /NOBREAK
goto LBL_BEGIN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment