PalworldのSavedバックアップスクリプト

# バックアップスクリプトの仕様
- 1日に1回、cronでスクリプトを起動しバックアップする想定
- バックアップ前にsystemctlでサーバーを停止し、バックアップ後に(再)起動する
- `backup_from` のディレクトをZIPファイルでバックアップする
- バックアップファイルの置き場所は `backup_dest` で指定する
- スクリプト実行時に、バックアップから `2週間分の秒数＋マージン30秒` を経過している場合は自動削除する
- ただし、バックアップファイル名に保管接尾辞 `_preserved` がついている場合は自動削除しない
- スクリプト起動日が月末日であれば、バックアップファイル名に保管接尾辞をつける

# バックアップファイル名の仕様
下記のいずれかになる。
- `p6d_YYYYMMDD-HHMM-S.zip`
- `p6d_YYYYMMDD-HHMM-S_preserved.zip`

※ `S` はエポック秒

# 使用上の注意
お使いの環境で `zip` コマンドが利用可能である必要があります。
`dnf install zip` (RedHat系)、`apt install zip` (Debian系)等でパッケージをインストールするなどしてください。

`backup_dest` で指定したディレクトリに適切なパーミッションを設定してください。

sudoの設定で`systemctl stop <サービス名>`と`systemctl start <サービス名>`をパスワード無し実行可にしてください。
sudoersの追記例は下記の通りです。(実行ユーザー名は`palworld`としています)

```text:追記例
palworld       ALL=(ALL:ALL) NOPASSWD: /usr/bin/systemctl stop palworld-dedicated.service
palworld       ALL=(ALL:ALL) NOPASSWD: /usr/bin/systemctl start palworld-dedicated.service
```

# バックアップシェルスクリプト

※ご使用の際はスクリプトファイルのパーミッション設定を実行可にしてください。

```shell:backup-p6d.sh
#!/bin/bash

# ============================================================ #
#  backup p6d
#
#  Copyright (c) 2024 CIB-MC
#  Released under the MIT license
#  https://opensource.org/licenses/mit-license.php
# ============================================================ #

# please edit variables below for youer enviroment

service_name="palworld-dedicated.service"
backup_from="/home/palworld/steam/steamapps/common/PalServer/Pal/"
backup_dest="/var/backups/p6d/"

preserved_suffix="_preserved"
sec_to_live=$((60 * 60 * 24 * 7 * 2 + 30)) # 60sec x 60min x 24hour x 7day x 2week + 30sec


# ============================================================ #
#  initialize variables for the patch 
# ============================================================ #

exit_status=0
next_day=`date -d '+1 day' +%d`
str_ts=`date +%Y%m%d-%H%M_%s`
epoch_now=`date +%s`
file_name_suffix=""


# ============================================================ #
#  stop palworld dedicated server
# ============================================================ #

stop_command="sudo systemctl stop ${service_name}"
eval $stop_command
if [ $? -ne 0 ]; then
        echo "Failed to stop palworld server!"
        exit 1
fi


# ============================================================ #
#  set backup file to preserved if today is last day of month
# ============================================================ #

if [ $next_day -eq 1 ]; then
        file_name_suffix=$preserved_suffix
fi


# ============================================================ #
#  backup dirs in backup_from
# ============================================================ #

file_name="p6d_${str_ts}${file_name_suffix}.zip"
file_path=$backup_dest$file_name
backup_command="cd ${backup_from}; zip -q -r ${file_path} ./Saved;"
eval $backup_command
if [ $? -ne 0 ]; then
        echo "Failed to backup Saved dir!"
        exit_status=1
fi


# ============================================================ #
#  delete backup files over sec to live and are not preserved
# ============================================================ #

find_backup_file_cond="${backup_dest}*"
files_backup=`find $find_backup_file_cond -type f -name "*.zip"`
for file_backup in $files_backup;
do
        if [[ !($file_backup =~ ${preserved_suffix}\.zip$ ) && ($file_backup =~ _([0-9]+)\.zip$) ]]; then
                epoch_backup=${BASH_REMATCH[1]}
                if [ $(($epoch_now - $epoch_backup)) -gt $sec_to_live ]; then
                        delete_command="rm -f ${file_backup};"
                        eval $delete_command
                        if [ $? -ne 0 ]; then
                                exit_status=1
                        fi
                fi
        fi
done

# ============================================================ #
#  (re)start palworld dedicated server
# ============================================================ #

start_command="sudo systemctl start ${service_name}"
eval $start_command
if [ $? -ne 0 ]; then
        echo "Failed to start palworld server!"
        exit_status=1
fi


# ============================================================ #

if [ $exit_status -ne 0 ]; then
        echo "=== BACKUP PROCESS WAS NOT ALL SUCCEEDED! ==="
        echo "Please read logs above and take action you need to do."
fi
exit $exit_status
```

# その他
改造はライセンスを守ってご自由にどうぞ。