Auto Update Steamcmd Servers
Idee
Mit Steamcmd können verschiedene Spieleserver heruntergeladen werden.
Die lokal installierte Version hat eine buildid, die mit der öffentlich verfügbaren Version verglichen wird.
Unterscheiden sich die beiden IDs, werden die Dateien mittels Docker und des Steamcmd Images aktualisiert.
Läuft der Container des Servers noch, wird dieser gestoppt und im anschluss neugestartet.
Genauere Infos zum Verhalten wird noch weiter unten beleuchtet.
Skript
Grundsätzlich ist dieses Skript für Docker basierte Server gedacht. Es kann auch andere Systeme updaten, allerdings sind Prüfungen und Funktionen für Docker eingebaut. Einfach unter /usr/local/sbin/update_steam_game.sh
ablegen.
#!/bin/bash
set -e
: "${APP_ID:=}"
: "${APP_DIR:=}"
: "${APP_UID:=1000}"
: "${APP_GID:=1000}"
: "${APP_DIR_INIT:=0}"
: "${CONTAINER_NAME:=}"
: "${UPDATE_SCRIPT:=}"
[[ ! -d "${APP_DIR}" && "${APP_DIR_INIT}" != "1" ]] && echo "APP_DIR [${APP_DIR}] does not exist" && exit 1
# get state of game
TEMP_FILE=$(mktemp)
URL="https://api.steamcmd.net/v1/info/${APP_ID}"
curl -X GET "${URL}" -o ${TEMP_FILE} > /dev/null 2>&1
local_buildid=$(grep -oP 'buildid.+"\K[0-9]+' ${APP_DIR}/appmanifest_${APP_ID}.acf 2>/dev/null|| echo 0)
remote_buildid=$(jq -r '.data.[].depots.branches.public.buildid' "${TEMP_FILE}")
rm "${TEMP_FILE}"
if [[ "${local_buildid}" == "${remote_buildid}" ]]; then
echo "no update needed - buildid local[${local_buildid}] remote[${remote_buildid}]"
exit 0
fi
# stop container if existing and not stopped
state=$(docker ps -a -f name="^${CONTAINER_NAME}$" --format json | jq -r '.State')
if [[ ${state} == "" ]];then
echo "Container [${CONTAINER_NAME}] does not exist (check ENV CONTAINER_NAME variable)"
elif [[ ! ${state} =~ exited ]];then
echo "stopping container [${CONTAINER_NAME}]"
docker stop "${CONTAINER_NAME}"
stopped=1
fi
# update by script / default cmd
if [[ -x "${UPDATE_SCRIPT}" ]];then
echo "UPDATE BY SCRIPT [${UPDATE_SCRIPT}]"
${UPDATE_SCRIPT}
else
# create directory and fix permissions
if [[ ! -d "${APP_DIR}" ]];then
mkdir -p "${APP_DIR}"
fi
ts=$(date +'%s')
chown -R 1000:1000 "${APP_DIR}"
cmd="docker run --network host --rm -it --name=${CONTAINER_NAME:-steam_$ts}_updater -v ${APP_DIR}:/home/steam/Steam/steamapps:rw cm2network/steamcmd /home/steam/steamcmd/steamcmd.sh +login anonymous +app_update ${APP_ID} validate +quit"
echo "UPDATE BY COMMAND [${cmd}]"
$cmd
chown -R ${APP_UID}:${APP_GID} "${APP_DIR}"
fi
[[ ${stopped} -eq 1 ]] && echo "starting docker container [${CONTAINER_NAME}]" && docker start "${CONTAINER_NAME}"
Berechtigung fixen:
chmod 700 /usr/local/sbin/update_steam_game.sh
Benutzung
Zu Beginn des Skripts werden folgende Variablen gesetzt:
Variable | Verwendung |
---|---|
APP_ID | ID des Spiels, Palworld z.B. hat die ID 2394010 |
APP_DIR | Pfad zu steamapps (Installation), im Dockercontainer wäre dies der Pfad zu /home/steam/Steam/steamapps |
APP_DIR_INIT | Existiert der Ordner noch nicht, wird dieser angelegt und das Spiel erstmalig heruntergeladen |
CONTAINER_NAME | Name des Server-Containers der geprüft und ggf. neugestartet werden soll |
UPDATE_SCRIPT | Pfad zu einem eigenen Update Skript, welches Anstelle des docker run Befehls mit Standard Steamcmd Parametern ausgeführt wird (z.B. wenn Login nötig ist, oder anderer Branch) |
OPTIONALE VARIABLEN | |
APP_UID | Nach dem Update wird der Owner von APP_DIR auf diese ID gesetzt |
APP_GID | Nach dem Update wird die Owner Group von APP_DIR auf diese GID gesetzt |
Beispiel:
Auto Update für Palworld, kann so auch als Cronjob / Systemd Timer laufen…
APP_ID="2394010" APP_DIR_INIT="1" APP_DIR="/srv/docker/containers/steam/palworld.testing2/" CONTAINER_NAME="steam_palworld_test" /usr/local/sbin/update_steam_game.sh