#!/bin/bash # ARK: survival evolved manager # # Original author: LeXaT # Maintainer: FezVrasta # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Check the user is not currently running this script as root if [ "$(id -u)" == "0" ]; then echo "This script must NOT be run as root" 1>&2 exit 1 fi #--------------------- # Variables #--------------------- # Global variables if [ -f "/etc/arkmanager/arkmanager.cfg" ]; then source /etc/arkmanager/arkmanager.cfg fi if [ -f "${HOME}/.arkmanager.cfg" ]; then source "${HOME}/.arkmanager.cfg" fi # Local variables info="" thejob="" instver="" bnumber="" timestamp=$( date +%T ) GREEN="\\033[1;32m" RED="\\033[1;31m" YELLOW="\\e[0;33m" NORMAL="\\033[0;39m" maxOpenFiles=100000 arkmanagerLog="arkmanager.log" # here are logged the actions performed by arkmanager arkserverLog="arkserver.log" # here is logged the output of ShooterGameServer #--------------------- # functions #--------------------- # # check configuration and report errors # checkConfig() { # SteamCMD configuration # steamcmdroot if [ ! -d "$steamcmdroot" ] ; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tYour SteamCMD root seems not valid." fi # steamcmdexec if [ ! -f "$steamcmdroot/$steamcmdexec" ] ; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tYour SteamCMD exec could not be found." fi # steamcmd_user if ! getent passwd $steamcmd_user > /dev/null 2>&1 ; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tYour SteamCMD user is not valid." fi # Environment configuration # arkserverroot if [ ! -w `echo "$arkserverroot" | sed 's:/[^/]*$::'` ] ; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tYou have not rights to write in the defined ARK server root directory" fi # arkserverexec if [ ! -f "$arkserverroot/$arkserverexec" ] ; then echo -e "[" "$YELLOW" "WARN" "$NORMAL" "]" "\tYour SteamCMD exec could not be found." fi # Service configuration # logdir if [ ! -w "$logdir" ] ; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tYou have not rights to write in the log directory." fi } # # Check if a new version is available but not apply it # function checkForUpdate(){ tput sc echo "Querying Steam database for latest version..." if isUpdateNeeded; then tput rc; tput ed; echo -e "Current version:" "$RED" $instver "$NORMAL" echo -e "Available version:" "$GREEN" $bnumber "$NORMAL" echo -e "Your server needs to be restarted in order to receive the latest update." echo -e "Run \"arkmanager update\" to do so" else tput rc; tput ed; echo -e "Current version:" "$GREEN" $instver "$NORMAL" echo -e "Available version:" "$GREEN" $bnumber "$NORMAL" echo "Your server is up to date!" fi } # # Check if the server need to be updated # Return 0 if update is needed, else return 1 # function isUpdateNeeded(){ getCurrentVersion getAvailableVersion if [ "$bnumber" -eq "$instver" ]; then return 1 # no update needed else return 0 # update needed fi } # # Parse an ACF structure # $1 is the desired path # $2 is the desired property # $3 is the current path # function parseSteamACF(){ local sname while read name val; do name="${name#\"}" name="${name%\"}" val="${val#\"}" val="${val%\"}" if [ "$name" = "}" ]; then break elif [ "$name" == "{" ]; then parseSteamACF "$1" "$2" "${3}.${sname}" else if [ "$3" == "$1" -a "$name" == "$2" ]; then echo "$val" break fi sname="${name}" fi done } # # Return the current version number # function getCurrentVersion(){ if [ -f "${arkserverroot}/steamapps/appmanifest_${appid}.acf" ]; then instver=`while read name val; do if [ "${name}" == "{" ]; then parseSteamACF "" "buildid"; break; fi; done <"${arkserverroot}/steamapps/appmanifest_${appid}.acf"` echo $instver > "$arkserverroot/arkversion" else instver="" fi return $instver } # # Get the current available server version on steamdb # function getAvailableVersion(){ rm -f "$steamcmd_appinfocache" bnumber=`$steamcmdroot/$steamcmdexec +login anonymous +app_info_update 1 +app_info_print "$appid" +quit | while read name val; do if [ "${name}" == "{" ]; then parseSteamACF ".depots.branches.public" "buildid"; break; fi; done` return $bnumber } # # Check id the server process is alive # function isTheServerRunning(){ SERVICE="ShooterGameServer" ps aux | grep -v grep | grep $SERVICE > /dev/null result=$? return $result } # # Check if the server is up and visible in steam server list # # function isTheServerUp(){ lsof -i :"$ark_Port" > /dev/null result=$? # In this case, the result is: # 1 if the command fail. The port is not listenning # 0 if the command succeed. The port is listenning if [ $result -eq 0 ];then return 1 else return 0 fi } # # start function # doStart() { if isTheServerRunning; then echo "The server is already running" else tput sc echo "The server is starting..." arkserveropts=$serverMap # bring in ark_... options for varname in "${!ark_@}"; do name="${varname#ark_}" val="${!varname}" # Port is actually one higher than specified # i.e. specifying port 7777 will have the server # use port 7778 if [ "$name" == "Port" ]; then (( val = val - 1 )) fi if [ -n "$val" ]; then arkserveropts="${arkserveropts}?${name}=${val}" fi done arkserveropts="${arkserveropts}?listen" # run the server in background echo "$timestamp: start" >> "$logdir/$arkserverLog" # set max open files limit before we start the server ulimit -n $maxOpenFiles nohup "$arkserverroot/$arkserverexec" "$arkserveropts" "$logdir/$arkserverLog" 2>&1 & # output of this command is logged echo "$timestamp: start" >> "$logdir/$arkmanagerLog" tput rc; tput ed; echo "The server is now up" fi } # # stop the ARK server # doStop() { if isTheServerRunning; then tput sc echo "Stopping server..." # kill the server with the PID PID=`ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}'` kill -9 $PID tput rc; tput ed; echo "The server has been stopped" echo "$timestamp: stop" >> "$logdir/$arkmanagerLog" else echo "The server is already stopped" fi } # # install of ARK server # doInstall() { mkdir -p "$arkserverroot" cd "$steamcmdroot" # install the server ./$steamcmdexec +login anonymous +force_install_dir "$arkserverroot" +app_update $appid validate +quit # the current version should be the last version. We set our version getCurrentVersion } # # Stop the server, update it and then start it back. # doUpdate() { cd "$arkserverroot" if isUpdateNeeded; then forceUpdate else echo "Your server is already up to date! The most recent version is ${bnumber}." echo "$timestamp: No update needed." >> "$logdir/update.log" fi; } forceUpdate(){ # check if the server was alive before the update so we can launch it back after the update serverWasAlive=0 if isTheServerRunning ;then serverWasAlive=1 fi doStop cd "$steamcmdroot" ./$steamcmdexec +login anonymous +force_install_dir "$arkserverroot" +app_update $appid +quit # the current version should be the last version. We set our version getCurrentVersion echo "$timestamp: update to $instver complete" >> "$logdir/update.log" # we restart the server only if it was started before the update if [ $serverWasAlive -eq 1 ]; then doStart fi } # # Waits for server to perform save before update (until save file is newer than 1 minute) # safeUpdate(){ cd "$arkserverroot" if isUpdateNeeded; then while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name $serverMap.ark` ]; do echo "$timestamp: Save file older than 1 minute. Delaying update." >> "$logdir/update.log" sleep 30s done echo "$timestamp: Save file newer than 1 minute. Performing an update." >> "$logdir/update.log" forceUpdate else echo "Your server is already up to date! The most recent version is ${bnumber}." echo "$timestamp: No update needed." >> "$logdir/update.log" fi } # # Print the status of the server (running? online? version?) # printStatus(){ if isTheServerRunning ;then echo -e "$NORMAL" "Server running: " "$GREEN" "Yes" "$NORMAL" else echo -e "$NORMAL" "Server running: " "$RED" "No" "$NORMAL" fi if isTheServerUp ;then echo -e "$NORMAL" "Server online: " "$RED" "No" "$NORMAL" else echo -e "$NORMAL" "Server online: " "$GREEN" "Yes" "$NORMAL" fi getCurrentVersion echo -e "$NORMAL" "Server version: " "$GREEN" $instver "$NORMAL" } doUpgrade() { echo "arkmanager v${arkstVersion}: Checking for updates..." arkstLatestVersion=`curl -s https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version` if [[ $arkstLatestVersion > $arkstVersion ]]; then read -p "A new version was found! Do you want to upgrade ARK Server Tools to v${$arkstLatestVersion}?" -n 1 -r echo -en "/n" if [[ $REPLY =~ ^[Yy]$ ]]; then curl -s https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/netinstall.sh | sudo bash -s ${steamcmd_user} ${arkstChannel} else exit 0 fi else echo "Your ARK server tools are already up to date" fi } #--------------------- # Main program #--------------------- # check the configuration and throw errors or warnings if needed checkConfig case "$1" in start) doStart ;; stop) doStop ;; restart) doStop echo "$timestamp: stop" >> "$logdir/$arkmanagerLog" sleep 10 doStart echo "$timestamp: start" >> "$logdir/$arkmanagerLog" echo "$timestamp: restart" >> "$logdir/$arkmanagerLog" ;; install) doInstall ;; update) doUpdate #testfunction ;; forceupdate) forceUpdate ;; checkupdate) checkForUpdate ;; broadcast) doInfo $2 ;; status) printStatus ;; upgrade) doUpgrade ;; -h|--help) echo -e "Usage: arkmanager[OPTION]\n" echo "Option Description" echo "start Starts the server" echo "stop Stops the server" echo "restart Stops the server and then starts it" echo "install Install the ARK server files from steamcmd" echo "update Check for a new ARK server version, if needed, stops the server, updates it, and starts it again" echo "forceupdate Apply update without check the current version" echo "checkupdate Check for a new ARK server version" echo "safeupdate Wait for server to perform world save and update." echo "boradcast PLACEHOLDER, not supported yet" echo "status Returns the status of the current ARK server instance" echo "upgrade Check for a new ARK Server Tools version and upgrades it if needed" ;; *) echo "arkmanager v${arkstVersion}: no command specified" echo "Try 'arkmanager -h' or 'arkmanager --help' for more information." ;; esac