ARK: Linux Dedicated Save World State on Stop/Restart

ARK: Survival Evolved Logo

This guide explains how to setup systemd to automatically save ARK: Survival Evolved world state before stopping/restarting the service.

ARK still doesn't handle Linux signals properly to allow world save on exit. Now that ARK has RCON support, we can amend the systemd shutdown scripts to use RCON to save the world state before stopping or restarting the service.

This guide has been created using CentOS 7 x64 and assumes you have setup ARK as per the install instructions. While not tested, this guide should apply to any other systemd distro. For distros still using SysVinit, most of this won't apply, however the 'ark-stop.sh' script and the 'rcon' tool may still be useful.

Contents:

RCON Client

Before you can begin, you need an RCON client. The client I'm using is very small and requires compiling, so install 'gcc':

# yum install gcc

Now get the RCON source and compile it:

# wget http://www.dopefish.de/files/rcon.c
# gcc rcon.c -o rcon
# chmod ugo+rx rcon
# mv rcon /usr/bin

Test RCON is working:

# /usr/bin/rcon -PADMIN_PASS -a127.0.0.1 -p27020 listplayers
Important: do not put spaces between the parameter identifier and the value.

Shutdown Script

We need a new shutdown script that will use RCON to get the server to save the world before a shutdown/restart.

Paste the code below into a new file, I'm using /opt/ark-stop.sh. Set the host, port and admin_pass at the top. The script takes two arguments, the kill signal and PID which will be passed from the systemd ark-dedicated.service, it will then broadcast a message to connected players, trigger a world save, wait 15 seconds, then stop the service as before.

#!/bin/bash

admin_pass='secret'
host='127.0.0.1'
port=27020

usage () {
    echo 'Ark: Survival Evolved safe-stop script.'
    echo
    echo 'This script is intended to be called by systemd when stopping or restarting'
    echo 'the Ark service. This script will use "rcon" to save the world state before'
    echo 'stopping the service.'
    echo
    echo 'You should not call this script directly, instead use:'
    echo '  systemctl (stop|restart) ark-dedicated'
    echo
    echo 'In /etc/systemd/system/ark-dedicated.conf, make sure that ExecReload and'
    echo 'ExecStop call this script:'
    echo '  ExecReload=/path/to/ark-stop.sh HUP $MAINPID'
    echo '  ExecStop=/path/to/ark-stop.sh QUIT $MAINPID'
    echo
    echo
    echo 'Usage:'
    echo '  ark-stop.sh SIGNAL PID'
    echo
    echo 'SIGNAL and PID should be supplied by systemd, see above. These parameters are'
    echo 'passed onto the kill command: "/bin/kill -s SIGNAL PID" after saving the world'
    echo 'state.'
    echo
}

if [ -z "$1" ]
then
    echo 'Parameter 1 (signal) is missing.'
    echo
    usage
    exit 1;
fi

if [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
    usage
    exit 0;
fi

if [ -z "$2" ]
then
    echo 'Parameter 2 (PID) is missing.'
    echo
    usage
    exit 1;
fi

# rcon broadcast message
/usr/bin/rcon -P${admin_pass} -a${host} -p${port} 'broadcast This server is going offline in 15 seconds, the world is saving now, any changes made beyond this point will be lost.'

# rcon saveworld
/usr/bin/rcon -P${admin_pass} -a${host} -p${port} 'saveworld'

# wait 15s
sleep 15;

# kill the service
/bin/kill -s $1 $2

Make the script executable by root only:

# chmod 700 /opt/ark-stop.sh

You should probably test the script at this point, to do so, get the PID for Ark (it should be running), and pass it to the script:

# pgrep ShooterGame
# /opt/ark-stop.sh QUIT <pid_from_pgrep>

Note: This script works for me, but my server is fairly unloaded and has a small number of players. For larger servers, you may need to increase the sleep duration. Alternatively, a sleep loop could probably be added to monitor the data files before stopping the executable.

Update systemd

Finally we need to amend the systemd configuration to use the new shutdown/restart script. Assuming you've setup via the ARK guide, you should have /etc/systemd/system/ark-dedicated.service with contents similar to:

[Unit]
Description=ARK: Survival Evolved dedicated server
Wants=network-online.target
After=syslog.target network.target nss-lookup.target network-online.target

[Service]
ExecStart=/path/to/ark/ShooterGame/Binaries/Linux/ShooterGameServer "TheIsland?MaxPlayers=10?listen?RCONEnabled=True?RCONPort=27020" -server -log
LimitNOFILE=100000
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
User=steam
Group=steam

[Install]
WantedBy=multi-user.target

Replace the ExecReload and ExecStop commands to point to the new script:

ExecReload=/opt/ark-stop.sh HUP $MAINPID
ExecStop=/opt/ark-stop.sh QUIT $MAINPID

Tell systemd to reload the .service files:

systemctl daemon-reload

Testing

Run your server through a start, restart, stop, start cycle to make sure everything is happy. It may help to have someone in-game who can destroy a tree immediately before you stop the service to verify the world is saving and confirm the broadcast message is displayed.

If the broadcast message isn't displayed/state isn't saving, check your admin password, host and port are correct and make sure ARK startup command (in ark-dedicated.service) contains: "?RCONEnabled=True?RCONPort=27020".

If the broadcast message is displayed, but state is not saved, try increasing the delay between the save trigger and call to kill, it may be that your server is not completing the save within the 15 seconds.

Undoing

Presumably at some point in the future the devs will add support for signal handling and this bodge won't be needed anymore. To remove this bodge:

  • Edit /etc/systemd/system/ark-dedicated.service and restore the original ExecReload and ExecStop commands:
    ExecReload=/bin/kill -s HUP $MAINPID
    ExecStop=/bin/kill -s QUIT $MAINPID
  • Restart systemd to reload the ark-dedicated.service:
    # systemctl daemon-reload
  • Remove the RCON save script:
    # rm /opt/ark-stop.sh

Don't forget to do another start, restart, stop, start cycle to test you've got everything restored correctly.