From 7014502ee1e542278b95a94af1225e199c3f1274 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 20 Feb 2016 21:36:19 +1000 Subject: [PATCH 01/24] Change .mod file output --- tools/arkmanager | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 7bccf83..bb8c3ac 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1348,23 +1348,31 @@ doExtractMod(){ fi done + modname="$(curl -s "http://steamcommunity.com/sharedfiles/filedetails/?id=${modid}" | sed -n 's|^.*
\([^<]*\)
.*|\1|p')" + + rm "${moddestdir}/.mod" + perl -e ' my $data; { local $/; $data = ; } my $mapnamelen = unpack("@0 L<", $data); my $mapname = substr($data, 4, $mapnamelen - 1); - $mapnamelen += 4; - my $mapfilelen = unpack("@" . ($mapnamelen + 4) . " L<", $data); - my $mapfile = substr($data, $mapnamelen + 8, $mapfilelen); - print pack("L< L< L< Z8 L< C L< L<", $ARGV[0], 0, 8, "ModName", 1, 0, 1, $mapfilelen); - print $mapfile; + my $mapfilelen = unpack("@" . ($mapnamelen + 8) . " L<", $data); + my $mapfile = substr($data, $mapnamelen + 12, $mapfilelen); + my $modname = $ARGV[1] . "\x00"; + my $modnamelen = length($modname); + my $modpath = "../../../ShooterGame/Content/Mods/" . $ARGV[0] . "\x00"; + my $modpathlen = length($modpath); + print pack("L< L< L< Z$modnamelen L< Z$modpathlen L< L< Z$mapfilelen", + $ARGV[0], 0, $modnamelen, $modname, $modpathlen, $modpath, + 1, $mapfilelen, $mapfile); print "\x33\xFF\x22\xFF\x02\x00\x00\x00\x01"; - ' $modid <"$moddestdir/mod.info" >"$moddestdir/.mod" + ' $modid "$modname" <"$moddestdir/mod.info" >"${moddestdir}.mod" if [ -f "$moddestdir/modmeta.info" ]; then - cat "$moddestdir/modmeta.info" >>"$moddestdir/.mod" + cat "$moddestdir/modmeta.info" >>"${moddestdir}.mod" else - echo -ne '\x01\x00\x00\x00\x08\x00\x00\x00ModType\x00\x02\x00\x00\x001\x00' >>"$moddestdir/.mod" + echo -ne '\x01\x00\x00\x00\x08\x00\x00\x00ModType\x00\x02\x00\x00\x001\x00' >>"${moddestdir}.mod" fi echo "$modbranch" >"$moddestdir/.modbranch" From fe11e77f0f025c2f10754fdedfbbe227790949c1 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 21 Feb 2016 10:40:06 +1000 Subject: [PATCH 02/24] Only try to remove .mod if it exists --- tools/arkmanager | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index bb8c3ac..317d3e0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1350,7 +1350,9 @@ doExtractMod(){ modname="$(curl -s "http://steamcommunity.com/sharedfiles/filedetails/?id=${modid}" | sed -n 's|^.*
\([^<]*\)
.*|\1|p')" - rm "${moddestdir}/.mod" + if [ -f "${moddestdir}/.mod" ]; then + rm "${moddestdir}/.mod" + fi perl -e ' my $data; From e81f1905cdc5edd68966608decc95d3ffd1f7745 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 23 Feb 2016 05:38:25 +1000 Subject: [PATCH 03/24] Use name from mod.info if mod name can't be retrieved --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 317d3e0..5e8281c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1361,7 +1361,7 @@ doExtractMod(){ my $mapname = substr($data, 4, $mapnamelen - 1); my $mapfilelen = unpack("@" . ($mapnamelen + 8) . " L<", $data); my $mapfile = substr($data, $mapnamelen + 12, $mapfilelen); - my $modname = $ARGV[1] . "\x00"; + my $modname = ($ARGV[1] || $mapname) . "\x00"; my $modnamelen = length($modname); my $modpath = "../../../ShooterGame/Content/Mods/" . $ARGV[0] . "\x00"; my $modpathlen = length($modpath); From 7c0abf2dfbec627601faaa070581018f90f936e3 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 23 Feb 2016 07:36:20 +1000 Subject: [PATCH 04/24] Add Blob SHA to --version output This should make it possible to determine the arkmanager version when it hasn't been installed using the netinstall script. --- tools/arkmanager | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arkmanager b/tools/arkmanager index 5e8281c..67415e0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1806,6 +1806,7 @@ while true; do if [ -n "${arkstCommit}" ]; then echo "Commit: ${arkstCommit:0:7}" fi + echo "Blob SHA: $( (echo -ne "blob $(stat -c "%s" "$0")\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From 4eeeebeb8ec989d22665e58ecce80a34ab19a2e5 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 27 Feb 2016 22:19:10 +1000 Subject: [PATCH 05/24] Add handling for global options --- tools/arkmanager | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 67415e0..b6f8201 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1732,6 +1732,22 @@ while true; do shift nrarg=0 + # Handle global options + case "$command" in + --verbose) + verbose=1 + continue + ;; + --dots) + progressDisplayType=dots + continue + ;; + --spinner) + progressDisplayType=spinner + continue + ;; + esac + # get the number of arguments for commands that take arguments case "$command" in installmod) nrarg=1; ;; From eb72148b35a319c434e491386c3c3c435750656d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 27 Feb 2016 22:39:22 +1000 Subject: [PATCH 06/24] Add support for adding and removing cron jobs --- README.asciidoc | 31 +++++++++++++++++++++ tools/arkmanager | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index 31abc77..2f6a39d 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -238,6 +238,37 @@ instances. `status`:: Prints the status of the ARK server +`install-cronjob `:: + Installs a cron job that executes the specified command. + This accepts any of the options the specified command accepts, + as well as the following options. In order to specify an + argument to the command (e.g. to the `broadcast` command), + use the `--arg=` option. + + `--daily`;; + The command should be executed daily + + `--hourly`;; + The command should be executed hourly + + `--hour=`;; + Specifies one or more hours when the command should execute. + This is the hour field of the cron job. + + `--minute=`;; + Specifies one or more minutes of the hour when the command + should execute. This is the minute field of the cron job. + + `--enable-output`;; + Enables the output from the command - the cron daemon usually + emails this to the user specified in the cron configuration + + `--arg=`;; + Specifies an argument to pass to the command + +`remove-cronjob `:: + Removes a cron job previously installed by `install-cronjob` + Configuration files ------------------- diff --git a/tools/arkmanager b/tools/arkmanager index b6f8201..37ecdae 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1561,6 +1561,64 @@ doBackup(){ fi } +# +# Install a cron job to execute a particular command +# +doInstallCronJob(){ + hour='*' + minute='0' + cmdopts="${arkCronExtraOpts}" + cmdargs="" + output=">/dev/null 2>&1" + command="$1" + shift + + for opt in "$@"; do + case "$opt" in + --daily) + ;; + --hourly) + hour='*' + ;; + --hour=*) + hour="${opt#--hour=}" + ;; + --minute=*) + minute="${opt#--minute=}" + ;; + --enable-output) + output= + ;; + --arg=*) + cmdargs="${cmdargs} $(printf "%q" "${opt#--opt=}")" + ;; + --*) + cmdopts="${cmdopts} $(printf "%q" "${opt}")" + ;; + *) + cmdargs="${args} $(printf "%q" "${opt}")" + ;; + esac + done + + cronjob="${minute} ${hour} * * * arkmanager --cronjob ${command} @${instance} ${cmdopts} --args ${cmdargs} -- ${output}" + + (crontab -l | \ + sed -e "/ [*] [*] [*] arkmanager --cronjob ${command} @${instance} /d"; + echo "${cronjob}" ) | \ + crontab - +} + +# +# Removes an installed cron job +# +doRemoveCronJob(){ + command="$1" + + crontab -l | \ + sed -e "/ [*] [*] [*] arkmanager --cronjob ${command} @${instance} /d" | \ + crontab - +} # # Print the status of the server (running? online? version?) @@ -1697,6 +1755,8 @@ showUsage() { echo "installmod Installs a mod from the Steam workshop" echo "uninstallmod Removes the mod from the Mods directory" echo "reinstallmod Removes and re-installs a mod in the Mods directory" + echo "install-cronjob Adds a cron job using the specified command" + echo "remove-cronjob Removes a cron job that used the specified command" echo "restart Stops the server and then starts it" echo "run Runs the server without daemonizing" echo "start Starts the server" @@ -1746,6 +1806,10 @@ while true; do progressDisplayType=spinner continue ;; + --cronjob) + inCronJob=true + continue + ;; esac # get the number of arguments for commands that take arguments @@ -1756,6 +1820,8 @@ while true; do broadcast) nrarg=1; ;; rconcmd) nrarg=1; ;; useconfig) nrarg=1; ;; + install-cronjob) nrarg=1; ;; + remove-cronjob) nrarg=1; ;; esac # Enumerate the options and arguments @@ -1912,6 +1978,12 @@ while true; do status) printStatus ;; + install-cronjob) + doInstallCronJob "${args[@]}" "${options[@]}" + ;; + remove-cronjob) + doRemoveCronJob "${args[@]}" + ;; *) echo -n "arkmanager v${arkstVersion}: unknown command '$command' specified" showUsage From 326bb5560b20c1c88713aa081cc5f763f9ff141a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 27 Feb 2016 23:35:03 +1000 Subject: [PATCH 07/24] Process ark options in config file order --- tools/arkmanager | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 37ecdae..feb9ecb 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -602,6 +602,42 @@ doRun() { arkextraopts=( ) + while read varname; do + val="${!varname}" + case "$varname" in + ark_*) + name="${varname#ark_}" + + # 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}" + else + arkserveropts="${arkserveropts}?${name}" + fi + ;; + arkopt_*) + name="${varname#arkopt_}" + val="${!varname}" + + if [ -n "$val" ]; then + arkextraopts=( "${arkextraopts[@]}" "-${name}=${val}" ) + fi + ;; + arkflag_*) + name="${varname#arkflag_}" + + arkextraopts=( "${arkextraopts[@]}" "-${name}" ) + ;; + esac + unset $varname + done < <(sed -n 's/^\(ark\(\|opt\|flag\)_[^= ]*\)=.*/\1/p' <"$configfile") + # bring in ark_... options for varname in "${!ark_@}"; do name="${varname#ark_}" From 1729c16df0f7593af9f3b600d8506b33b97bdca2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 2 Mar 2016 00:47:14 +1000 Subject: [PATCH 08/24] Use serverMapModId to set map name and MapModID option --- tools/arkmanager | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index feb9ecb..7308839 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -593,7 +593,17 @@ doRun() { arkserveropts="$serverMap" if [ -n "$serverMapModId" ]; then - arkserveropts="-MapModID=$serverMapModId" + serverMap="$(perl -e ' + my $data; + { local $/; $data = <>; } + my $mapnamelen = unpack("@0 L<", $data); + my $mapname = substr($data, 4, $mapnamelen - 1); + $mapnamelen += 4; + my $mapfilelen = unpack("@" . ($mapnamelen + 4) . " L<", $data); + my $mapfile = substr($data, $mapnamelen + 8, $mapfilelen - 1); + print $mapfile; + ' <"${arkserverroot}/ShooterGame/Content/Mods/${serverMapModId}/mod.info")" + arkserveropts="${serverMap}?MapModID=${serverMapModId}" fi if [ -z "$arkserveropts" ]; then From fd2637577036d22f213b9c882de59cd31f93d3ec Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 7 Mar 2016 15:56:33 +1000 Subject: [PATCH 09/24] Return -1 from numplayers if server unreachable --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 7308839..e1c6042 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -577,7 +577,7 @@ function numPlayersConnected(){ my $sockaddr = pack_sockaddr_in($port, inet_aton($ARGV[1])); send($socket, "\xff\xff\xff\xffTSource Engine Query\x00", 0, $sockaddr); my $data = ""; - recv($socket, $data, 1400, 0) or (print "0" and exit(1)); + recv($socket, $data, 1400, 0) or (print "-1" and exit(1)); my ($servername, $mapname, $game, $fullname, $rest) = split(/\x00/, substr($data, 6), 5); my $players = ord(substr($rest, 2, 1)); print "$players\n"; From 63ded49b304077cb7bce67cb0b740c1a151c6acc Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 9 Mar 2016 19:32:01 +1000 Subject: [PATCH 10/24] Fix a couple of potential issues with player count checking --- tools/arkmanager | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index e1c6042..a066ae5 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -949,7 +949,7 @@ doWarn(){ doBroadcastWithEcho "$warnmsg" for (( min = warnminutes - 1; min >= warninterval; min-- )); do numplayers=$(numPlayersConnected) - if (( numplayers + 0 == 0 )); then + if (( (numplayers + 0) == 0 )); then echo "Nobody is connected. Shutting down immediately" return 0 fi @@ -976,7 +976,7 @@ doWarn(){ doBroadcastWithEcho "$warnmsg" if (( warnseconds >= 20 )); then numplayers=$(numPlayersConnected) - if (( numplayers + 0 == 0 )); then + if (( (numplayers + 0) == 0 )); then echo "Nobody is connected. Shutting down immediately" return 0 fi @@ -1114,7 +1114,7 @@ doUpdate() { fi elif [ "$updatetype" == "ifempty" ]; then numplayers=$(( $(numPlayersConnected) + 0 )) - if (( numplayers == 0 )); then + if (( numplayers != 0 )); then echo "${numplayers} players are still connected" return 1 fi From 3eca9d3446d607e13669a5c2229ece09c662dd5b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 9 Mar 2016 20:03:31 +1000 Subject: [PATCH 11/24] Fix numPlayersConnected to use getQueryPort --- tools/arkmanager | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index a066ae5..6b1f2bb 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -581,7 +581,7 @@ function numPlayersConnected(){ my ($servername, $mapname, $game, $fullname, $rest) = split(/\x00/, substr($data, 6), 5); my $players = ord(substr($rest, 2, 1)); print "$players\n"; - ' "${ark_QueryPort}" "${ark_MultiHome:-127.0.0.1}" + ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" } # @@ -949,6 +949,7 @@ doWarn(){ doBroadcastWithEcho "$warnmsg" for (( min = warnminutes - 1; min >= warninterval; min-- )); do numplayers=$(numPlayersConnected) + echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then echo "Nobody is connected. Shutting down immediately" return 0 @@ -976,6 +977,7 @@ doWarn(){ doBroadcastWithEcho "$warnmsg" if (( warnseconds >= 20 )); then numplayers=$(numPlayersConnected) + echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then echo "Nobody is connected. Shutting down immediately" return 0 From 912c4dc824d8841aa753aea76d71d980252738b0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 8 May 2016 23:27:51 +1000 Subject: [PATCH 12/24] Handle multiple map files in mods --- tools/arkmanager | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 6b1f2bb..59e645b 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1407,15 +1407,21 @@ doExtractMod(){ { local $/; $data = ; } my $mapnamelen = unpack("@0 L<", $data); my $mapname = substr($data, 4, $mapnamelen - 1); - my $mapfilelen = unpack("@" . ($mapnamelen + 8) . " L<", $data); - my $mapfile = substr($data, $mapnamelen + 12, $mapfilelen); + my $nummaps = unpack("@" . ($mapnamelen + 4) . " L<", $data); + my $pos = $mapnamelen + 8; my $modname = ($ARGV[1] || $mapname) . "\x00"; my $modnamelen = length($modname); my $modpath = "../../../ShooterGame/Content/Mods/" . $ARGV[0] . "\x00"; my $modpathlen = length($modpath); - print pack("L< L< L< Z$modnamelen L< Z$modpathlen L< L< Z$mapfilelen", + print pack("L< L< L< Z$modnamelen L< Z$modpathlen L<", $ARGV[0], 0, $modnamelen, $modname, $modpathlen, $modpath, - 1, $mapfilelen, $mapfile); + $nummaps); + for (my $mapnum = 0; $mapnum < $nummaps; $mapnum++){ + my $mapfilelen = unpack("@" . ($pos) . " L<", $data); + my $mapfile = substr($data, $mapnamelen + 12, $mapfilelen); + print pack("L< Z$mapfilelen", $mapfilelen, $mapfile); + $pos = $pos + 4 + $mapfilelen; + } print "\x33\xFF\x22\xFF\x02\x00\x00\x00\x01"; ' $modid "$modname" <"$moddestdir/mod.info" >"${moddestdir}.mod" From 103c3abcf9b2d783f4b8bbe9f8918a7c734b8b46 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 16 May 2016 17:32:32 +1000 Subject: [PATCH 13/24] Account for all lower-case names in some environments --- tools/arkmanager | 57 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 59e645b..3cd8657 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1493,18 +1493,57 @@ doBackup(){ savedir="${ark_AltSaveDirectoryName}" fi + saverootdir="${arkserverroot}/ShooterGame/Saved" + savedcfgdir="${saverootdir}/Config/LinuxServer" + savedir="${savedrootdir}/${savedir}" + + # Check for the (unlikely) case that the case of the + # saved ark directory is screwed up + if [ ! -d "${savedir}" ]; then + cisavedir="$(find "${arkserverroot}" -ipath "${savedir}" | head -n1)" + + if [ -n "$cisavedir" ]; then + echo -e " ${NORMAL}[ ${YELLOW}WARN${NORMAL} ] Saved arks directory capitalization is inconsistent" + savedir="${cisavedir}" + else + echo -e " ${NORMAL}[ ${RED}ERROR${NORMAL} ] Saved arks directory does not exist" + return 1 + fi + fi + # ARK server uses Write-Unlink-Rename echo -ne "${NORMAL} Copying ARK world file " - cp -p "${arkserverroot}/ShooterGame/Saved/${savedir}/${serverMap##*/}.ark" "${backupdir}/${serverMap##*/}.ark" - if [ ! -f "${backupdir}/${serverMap##*/}.ark" ]; then + + # Take into account screwed up casing of saved ark files + # in some environments + mapfile="$(find "${savedir}" -iname "${serverMap##*/}.ark" | head -n1)" + + if [ -z "$mapfile" ]; then sleep 2 - cp -p "${arkserverroot}/ShooterGame/Saved/${savedir}/${serverMap##*/}.ark" "${backupdir}/${serverMap##*/}.ark" + mapfile="$(find "${savedir}" -iname "${serverMap##*/}.ark" | head -n1)" fi + # If both attempts fail, server may have # crashed between unlink and rename - if [ ! -f "${backupdir}/${serverMap##*/}.ark" ]; then - cp -p "${arkserverroot}/ShooterGame/Saved/${savedir}/${serverMap##*/}.tmp" "${backupdir##*/}/${serverMap##*/}.ark" + if [ -z "$mapfile" ]; then + mapfile="$(find "${savedir}" -iname "${serverMap##*/}.tmp" | head -n1)" fi + + # If neither the ark nor the tmp file exists, then the + # map name may be incorrect. Try to get any ark or tmp + # file in the saved arks directory + if [ -z "$mapfile" ]; then + mapfile="$(find "${savedir}" -iname "*.ark" | head -n1)" + + if [ -z "$mapfile" ]; then + mapfile="$(find "${savedir}" -iname "*.tmp" | head -n1)" + fi + fi + + if [ -f "${mapfile}" ]; then + cp -p "${mapfile}" "${backupdir}/${serverMap##*/}.ark" + fi + if [ -f "${backupdir}/${serverMap##*/}.ark" ]; then echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" else @@ -1516,7 +1555,7 @@ doBackup(){ # ARK server uses a non-blocking lock and will # fail to update the file if the lock fails. echo -e "${NORMAL} Copying ARK profile files" - for f in "${arkserverroot}/ShooterGame/Saved/${savedir}/"*.arkprofile; do + for f in "${savedir}/"*.arkprofile; do echo -ne "${NORMAL} ${f##*/} " cp -p "${f}" "${backupdir}/${f##*/}" if [ ! -s "${backupdir}/${f##*/}" ]; then @@ -1537,7 +1576,7 @@ doBackup(){ # ARK server uses Lock-Truncate-Write-Unlock echo -e "${NORMAL} Copying ARK tribe files " - for f in "${arkserverroot}/ShooterGame/Saved/${savedir}/"*.arktribe; do + for f in "${savedir}/"*.arktribe; do echo -ne "${NORMAL} ${f##*/} " cp -p "${f}" "${backupdir}/${f##*/}" if [ ! -s "${backupdir}/${f##*/}" ]; then @@ -1558,7 +1597,7 @@ doBackup(){ # ARK server uses Lock-Truncate-Write-Unlock echo -ne "${NORMAL} Copying GameUserSettings.ini " - cp -p "${arkserverroot}/ShooterGame/Saved/Config/LinuxServer/GameUserSettings.ini" "${backupdir}/GameUserSettings.ini" + cp -p "${savedcfgdir}/GameUserSettings.ini" "${backupdir}/GameUserSettings.ini" if [ ! -s "${backupdir}/GameUserSettings.ini" ]; then sleep 2 cp -p "${f}" "${backupdir}/${f##*/}" @@ -1572,7 +1611,7 @@ doBackup(){ echo -ne "${NORMAL} Copying Game.ini " - cp -p "${arkserverroot}/ShooterGame/Saved/Config/LinuxServer/Game.ini" "${backupdir}/Game.ini" + cp -p "${savedcfgdir}/Game.ini" "${backupdir}/Game.ini" if [ ! -s "${backupdir}/Game.ini" ]; then sleep 2 cp -p "${f}" "${backupdir}/${f##*/}" From e9b2c9b21f15a869d180620ccd8bd956ad4f8469 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 16 May 2016 17:38:08 +1000 Subject: [PATCH 14/24] Parse output of download_workshop_item command --- tools/arkmanager | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 3cd8657..3acc36b 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -158,6 +158,7 @@ else install_datadir="${install_datadir:-${install_bindir%/*}/share/arkmanager}" fi +declare -A modsrcdirs #--------------------- # functions @@ -366,8 +367,11 @@ function runSteamCMD(){ function runSteamCMDspinner(){ if [ -n "$verbose" ]; then - echo - runSteamCMD "$@" + if command >&3; then + runSteamCMD "$@" | tee /dev/fd/3 + else + runSteamCMD "$@" + fi return $? else if [ -z "$progressDisplayType" ]; then @@ -377,7 +381,11 @@ function runSteamCMDspinner(){ progressDisplayType=dots fi fi - runSteamCMD "$@" >/dev/null 2>&1 & + if command >&3; then + runSteamCMD "$@" >&3 & + else + runSteamCMD "$@" >/dev/null & + fi local scpid=$! local pos=0 local spinner=( '\b-' '\b/' '\b|' '\b\\' ) @@ -396,6 +404,12 @@ function runSteamCMDspinner(){ fi } +function runSteamCMDspinnerSubst(){ + local fd="$1" + shift + runSteamCMDspinner "$@" 3>&1 >/dev/fd/${fd} +} + # # Check if a new version is available but not apply it # @@ -1223,9 +1237,10 @@ doDownloadMod(){ while true; do echo -n "Downloading mod $modid" - runSteamCMDspinner +workshop_download_item $mod_appid $modid + local output=$(runSteamCMDspinnerSubst 5 +workshop_download_item $mod_appid $modid) 5>&1 result=$? if [ $result -eq 0 ]; then + modsrcdir="$(echo "$output" | sed -n 's@^Success. Downloaded item [0-9][0-9]* to "\([^"]*\)" .*@\1@p')" break else echo @@ -1243,6 +1258,7 @@ doDownloadMod(){ if [ -f "$modsrcdir/mod.info" ]; then echo "Mod $modid downloaded" + modsrcdirs[$modid]="$modsrcdir" return 0 else echo "Mod $modid was not successfully downloaded" @@ -1268,6 +1284,10 @@ isModUpdateNeeded(){ local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid" local modbranch="${mod_branch:-Windows}" + if [ -n "${modsrcdirs[$modid]}" ]; then + modsrcdir="${modsrcdirs[$modid]}" + fi + for varname in "${!mod_branch_@}"; do if [ "mod_branch_$modid" == "$varname" ]; then modbranch="${!varname}" @@ -1315,6 +1335,10 @@ doExtractMod(){ local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid" local modbranch="${mod_branch:-Windows}" + if [ -n "${modsrcdirs[$modid]}" ]; then + modsrcdir="${modsrcdirs[$modid]}" + fi + for varname in "${!mod_branch_@}"; do if [ "mod_branch_$modid" == "$varname" ]; then modbranch="${!varname}" From 053a938f56fc0dead21d93d58ec8024a7fb2af99 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 16 May 2016 17:38:37 +1000 Subject: [PATCH 15/24] Improve broadcast warning messages --- tools/arkmanager | 317 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 219 insertions(+), 98 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 3acc36b..0cd3f00 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -896,118 +896,207 @@ doInstall() { getCurrentVersion } +# +# Formats a warning message based on replacement strings +# +printWarnMessage(){ + local msg + if [ -n "$msgWarnReason" ]; then + local reason + local msgtime + if [ "$3" == "minutes" ]; then + if [ -n "$msgTimeMinutes" ]; then + msgtime="${msgTimeMinutes//\{minutes\}/$4}" + else + msgtime="$4 minutes" + fi + else + if [ -n "$msgTimeSeconds" ]; then + msgtime="${msgTimeSeconds//\{seconds\}/$4}" + else + msgtime="$4 seconds" + fi + fi + msg="${msgWarnReason//\{time\}/$msgtime}" + if [ "$1" == "update" ]; then + if [ -n "$appupdate" ]; then + if [ -n "$modupdate" ]; then + if [ -n "$msgReasonUpdateAppMod" ]; then + reason="$msgReasonUpdateMod" + else + reason="an update to the game and an update to mod(s) {modnamesupdated}" + fi + else + if [ -n "$msgReasonUpdateApp" ]; then + reason="$msgReasonUpdateApp" + else + reason="an update to the game" + fi + fi + elif [ -n "$modupdate" ]; then + if [ -n "$msgReasonUpdateMod" ]; then + reason="$msgReasonUpdateMod" + else + reason="an update to mod(s) {modnamesupdated}" + fi + fi + elif [ -n "$shutdownreason" ]; then + reason="$shutdownreason" + elif [ "$1" == "restart" ]; then + if [ -n "$msgReasonRestart" ]; then + reason="$msgReasonRestart" + else + reason="a restart" + fi + else + if [ -n "$msgReasonShutdown" ]; then + reason="$msgReasonShutdown" + else + reason="maintenance" + fi + fi + reason="${reason//\{modnamesupdated\}/${modnamesupdated}}" + msg="${msg//\{reason\}/${reason}}" + printf "%s\n" "$msg" + else + if [ "$1" == "update" ]; then + if [ "$3" == "minutes" ]; then + if [ -n "$msgWarnUpdateMinutes" ]; then + msg="${msgWarnUpdateMinutes//%d/$4}" + else + msg="This ARK server will shutdown for an update in $4 minutes" + fi + else + if [ -n "$msgWarnUpdateSeconds" ]; then + msg="${msgWarnUpdateSeconds//%d/$4}" + else + msg="This ARK server will shutdown for an update in $4 seconds" + fi + fi + elif [ "$1" == "restart" ]; then + if [ "$3" == "minutes" ]; then + if [ -n "$msgWarnRestartMinutes" ]; then + msg="${msgWarnRestartMinutes//%d/$4}" + else + msg="This ARK server will shutdown for a restart in $4 minutes" + fi + else + if [ -n "$msgWarnRestartSeconds" ]; then + msg="${msgWarnRestartSeconds//%d/$4}" + else + msg="This ARK server will shutdown for a restart in $4 seconds" + fi + fi + else + if [ "$3" == "minutes" ]; then + if [ -n "$msgWarnShutdownMinutes" ]; then + msg="${msgWarnShutdownMinutes//%d/$4}" + else + msg="This ARK server will shutdown in $4 minutes" + fi + else + if [ -n "$msgWarnShutdownSeconds" ]; then + msg="${msgWarnShutdownSeconds//%d/$4}" + else + msg="This ARK server will shutdown in $4 seconds" + fi + fi + fi + fi + + doBroadcastWithEcho "$msg" +} + # # Waits for a configurable number of minutes before updating the server # doWarn(){ cd "$arkserverroot" - local warnmsgmin - local warnmsgsec - - if [ "$1" == "update" ]; then - if [ -n "$msgWarnUpdateMinutes" ]; then - warnmsgmin="$msgWarnUpdateMinutes" - else - warnmsgmin="This ARK server will shutdown for an update in %d minutes" - fi - if [ -n "$msgWarnUpdateSeconds" ]; then - warnmsgsec="$msgWarnUpdateSeconds" - else - warnmsgsec="This ARK server will shutdown for an update in %d seconds" - fi - elif [ "$1" == "restart" ]; then - if [ -n "$msgWarnRestartMinutes" ]; then - warnmsgmin="$msgWarnRestartMinutes" - else - warnmsgmin="This ARK server will shutdown for a restart in %d minutes" - fi - if [ -n "$msgWarnRestartSeconds" ]; then - warnmsgsec="$msgWarnRestartSeconds" - else - warnmsgsec="This ARK server will shutdown for a restart in %d seconds" - fi - else - if [ -n "$msgWarnShutdownMinutes" ]; then - warnmsgmin="$msgWarnShutdownMinutes" - else - warnmsgmin="This ARK server will shutdown in %d minutes" - fi - if [ -n "$msgWarnShutdownSeconds" ]; then - warnmsgsec="$msgWarnShutdownSeconds" - else - warnmsgsec="This ARK server will shutdown in %d seconds" - fi - fi - - local pid=`getServerPID` - local sleeppid - if [ -n "$pid" ]; then - local warnmsg - local warnminutes=$(( arkwarnminutes )) - if (( warnminutes == 0 )); then - warnminutes=60 - fi - - local warnintervals=( 90 60 45 30 20 15 10 5 4 3 2 ) - - for warninterval in "${warnintervals[@]}"; do - if [ "`getServerPID`" != "$pid" ]; then - echo "Server has stopped. Aborting $1" - return 1 + ( + update_cancelled(){ + if [ -n "$msgUpdateCancelled" ]; then + msg="${msgUpdateCancelled//%s/$1}" + else + msg="Update cancelled by operator ($1)" fi - if (( warnminutes > warninterval )); then - sleep 1m & + doBroadcastWithEcho "${msg}" + } + + trap "update_cancelled 'Ctrl+C'" SIGINT + trap "update_cancelled 'Terminated'" SIGTERM + trap "update_cancelled 'Connection Closed'" SIGHUP + trap "update_cancelled 'Quit'" SIGQUIT + + local pid=`getServerPID` + local sleeppid + if [ -n "$pid" ]; then + local warnmsg + local warnminutes=$(( arkwarnminutes )) + if (( warnminutes == 0 )); then + warnminutes=60 + fi + + local warnintervals=( 90 60 45 30 20 15 10 5 4 3 2 ) + + for warninterval in "${warnintervals[@]}"; do + if [ "`getServerPID`" != "$pid" ]; then + echo "Server has stopped. Aborting $1" + return 1 + fi + if (( warnminutes >= warninterval )); then + sleep 1m & + sleeppid=$! + printWarnMessage "$1" "$2" "minutes" "$warnminutes" + for (( min = warnminutes - 1; min >= warninterval; min-- )); do + numplayers=$(numPlayersConnected) + echo "There are ${numplayers} players connected" + if (( (numplayers + 0) == 0 )); then + doBroadcastWithEcho "Nobody is connected. Shutting down immediately" + return 0 + fi + wait $sleeppid + if (( $min > $warninterval )); then + sleep 1m & + sleeppid=$! + fi + done + warnminutes=$warninterval + fi + done + + local warnseconds=120 + warnintervals=( 90 60 45 30 20 15 10 5 0 ) + for warninterval in "${warnintervals[@]}"; do + sleep $(( warnseconds - warninterval ))s & sleeppid=$! - warnmsg="$(printf "$warnmsgmin" "$warnminutes")" - doBroadcastWithEcho "$warnmsg" - for (( min = warnminutes - 1; min >= warninterval; min-- )); do + if [ "`getServerPID`" != "$pid" ]; then + echo "Server has stopped. Aborting update" + return 1 + fi + printWarnMessage "$1" "$2" "seconds" "$warnseconds" + if (( warnseconds >= 20 )); then numplayers=$(numPlayersConnected) echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then - echo "Nobody is connected. Shutting down immediately" + doBroadcastWithEcho "Nobody is connected. Shutting down immediately" return 0 fi - wait $sleeppid - if (( $min > $warninterval )); then - sleep 1m & - sleeppid=$! - fi - done - warnminutes=$warninterval - fi - done - - local warnseconds=120 - warnintervals=( 90 60 45 30 20 15 10 5 0 ) - for warninterval in "${warnintervals[@]}"; do - sleep $(( warnseconds - warninterval ))s & - sleeppid=$! - if [ "`getServerPID`" != "$pid" ]; then - echo "Server has stopped. Aborting update" - return 1 - fi - warnmsg="$(printf "$warnmsgsec" "$warnseconds")" - doBroadcastWithEcho "$warnmsg" - if (( warnseconds >= 20 )); then - numplayers=$(numPlayersConnected) - echo "There are ${numplayers} players connected" - if (( (numplayers + 0) == 0 )); then - echo "Nobody is connected. Shutting down immediately" - return 0 fi - fi - wait $sleeppid - warnseconds=$warninterval - done - fi + wait $sleeppid + warnseconds=$warninterval + done + fi - if [ "`getServerPID`" != "$pid" ]; then - echo "Server has stopped. Aborting $1" - return 1 - fi + if [ "`getServerPID`" != "$pid" ]; then + echo "Server has stopped. Aborting $1" + return 1 + fi - return 0 + return 0 + ) + + return $? } # @@ -1313,17 +1402,49 @@ isModUpdateNeeded(){ return 1 } +# +# Get the name of the specified mod +# +getModName(){ + local modid=$1 + local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid" + + if [ -n "${modsrcdirs[$modid]}" ]; then + modsrcdir="${modsrcdirs[$modid]}" + fi + + modname="$(curl -s "http://steamcommunity.com/sharedfiles/filedetails/?id=${modid}" | sed -n 's|^.*
\([^<]*\)
.*|\1|p')" + + if [ -n "$modname" ]; then + echo "$modname" + else + perl -e ' + my $data; + { local $/; $data = ; } + my $mapnamelen = unpack("@0 L<", $data); + my $mapname = substr($data, 4, $mapnamelen - 1); + print $mapname + ' <"${modsrcdir}/mod.info" + fi +} + # # Checks if any installed or requested mods need to be updated # isAnyModUpdateNeeded(){ + modnamesupdated="" + local ismodupdateneeded=1 for modid in $(getModIds); do if isModUpdateNeeded $modid; then - return 0 + ismodupdateneeded=0 + if [ -n "$modnamesupdated" ]; then + modnamesupdated="${modnamesupdated}, " + fi + modnamesupdated="${modnamesupdated}$(getModName "$modid")" fi done - return 1 + return $ismodupdateneeded } # From 2b83abf65cebdc784049bbc2691c20d240c8fff2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 16 May 2016 17:39:49 +1000 Subject: [PATCH 16/24] Allow stop and restart commands to take a reason --- tools/arkmanager | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0cd3f00..0e10b28 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -816,10 +816,24 @@ doStartAll(){ # doStop() { if isTheServerRunning; then - if [[ " $* " =~ " --warn " ]]; then - doWarn "$1" + local stopreason="$1" + local dowarn= + local warnreason= + local dosave= + shift + + for arg in "$@"; do + case "$arg" in + --warn) dowarn=1; ;; + --warnreason=*) warnreason="${arg#*=}"; ;; + --saveworld) dosave=1; ;; + esac + done + + if [[ -n "$dowarn" ]]; then + doWarn "$1" "$warnreason" fi - if [[ " $* " =~ " --saveworld " ]]; then + if [[ -n "$dosave" ]]; then doSaveWorld fi tput sc @@ -1237,7 +1251,7 @@ doUpdate() { doSaveWorld fi - doStop + doStop update # If user wants to back-up, we do it here. From eaefdfaaa61f7f6e8065357950f5ae5e2dd1fdcd Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 16 May 2016 17:55:50 +1000 Subject: [PATCH 17/24] Move .modbranch to __arkmanager_modbranch__.info --- tools/arkmanager | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0e10b28..c55f8d0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1397,7 +1397,11 @@ isModUpdateNeeded(){ fi done - if [ \( ! -f "$moddestdir/.modbranch" \) ] || [ "$(<"$moddestdir/.modbranch")" != "$modbranch" ]; then + if [ -f "$moddestdir/.modbranch" ]; then + mv "$moddestdir/.modbranch" "$moddestdir/__arkmanager_modbranch__.info" + fi + + if [ \( ! -f "$moddestdir/__arkmanager_modbranch__.info" \) ] || [ "$(<"$moddestdir/__arkmanager_modbranch__.info")" != "$modbranch" ]; then return 0 fi @@ -1480,7 +1484,11 @@ doExtractMod(){ fi done - if [ \( ! -f "$moddestdir/.modbranch" \) ] || [ "$(<"$moddestdir/.modbranch")" != "$modbranch" ]; then + if [ -f "$moddestdir/.modbranch" ]; then + mv "$moddestdir/.modbranch" "$moddestdir/__arkmanager_modbranch__.info" + fi + + if [ \( ! -f "$moddestdir/__arkmanager_modbranch__.info" \) ] || [ "$(<"$moddestdir/__arkmanager_modbranch__.info")" != "$modbranch" ]; then rm -rf "$moddestdir" fi @@ -1590,7 +1598,7 @@ doExtractMod(){ echo -ne '\x01\x00\x00\x00\x08\x00\x00\x00ModType\x00\x02\x00\x00\x001\x00' >>"${moddestdir}.mod" fi - echo "$modbranch" >"$moddestdir/.modbranch" + echo "$modbranch" >"$moddestdir/__arkmanager_modbranch__.info" fi } From 8c57170e4d680f55d1713f20548abc2001911d5a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 07:12:33 +1000 Subject: [PATCH 18/24] Remove now unnecessary ulimit setup --- tools/arkmanager | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index c55f8d0..5f0009c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -701,8 +701,6 @@ doRun() { arkserveropts="${arkserveropts}?listen" # run the server in background echo "`timestamp`: start" - # set max open files limit before we start the server - ulimit -n $maxOpenFiles serverpid=0 restartserver=1 From bc40544bf81bbd31d34c5abfef12d44607b08cee Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 08:11:40 +1000 Subject: [PATCH 19/24] Fix an inconsistency between install.sh and arkmanager.init --- tools/systemd/arkmanager.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/systemd/arkmanager.init b/tools/systemd/arkmanager.init index fa760d2..c63be0c 100755 --- a/tools/systemd/arkmanager.init +++ b/tools/systemd/arkmanager.init @@ -1,6 +1,6 @@ #!/bin/bash -DAEMON=/usr/bin/arkmanager +DAEMON="/usr/bin/arkmanager" for service in $(${DAEMON} list-instances --brief); do case "$1" in From c8f6cee90b45aed0baa9089498adba607db20756 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 09:52:48 +1000 Subject: [PATCH 20/24] Fix typo in doBackup --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 5f0009c..db1e70e 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1660,7 +1660,7 @@ doBackup(){ saverootdir="${arkserverroot}/ShooterGame/Saved" savedcfgdir="${saverootdir}/Config/LinuxServer" - savedir="${savedrootdir}/${savedir}" + savedir="${saverootdir}/${savedir}" # Check for the (unlikely) case that the case of the # saved ark directory is screwed up From e05ec78ac897005646a34d573adc5562b05d82d0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 09:56:33 +1000 Subject: [PATCH 21/24] Change to the home directory This should prevent errors when running from an inaccessible directory --- tools/arkmanager | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index db1e70e..898dcf8 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -126,6 +126,8 @@ if [ -f "${HOME}/.arkmanager.cfg" ]; then source "${HOME}/.arkmanager.cfg" fi +cd "$HOME" + lsof=lsof if [ -x /usr/sbin/lsof ]; then lsof=/usr/sbin/lsof From 9a4211d47480a59a90145d6b98e0b68e0dec94b2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 10:14:13 +1000 Subject: [PATCH 22/24] Update documentation with new options --- README.asciidoc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index 2f6a39d..ad81caa 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -152,6 +152,9 @@ instances. `--warn`;; Warns any connected players that the server is going down + `--warnreason`;; + Gives a reason for the shutdown. Defaults to `maintenance` + `--saveworld`;; Saves the world using `saveworld` - usually not necessary, as server usually saves the world on a graceful @@ -161,6 +164,9 @@ instances. Runs the `stop` command followed by the `restart` command. Accepts and passes the options for those commands + `--warnreason`;; + Gives a reason for the restart. Defaults to `a restart` + `install`:: Downloads and installs (or validates an existing install) of the ARK server @@ -352,6 +358,32 @@ The following options can be overridden on a per-instance basis: Templated messages for warnings, where `%d` is replaced with the number of minutes / seconds before the update / restart / shutdown +`msgWarnReason`:: +`msgTimeMinutes`:: +`msgTimeSeconds`:: +`msgReasonUpdateApp`:: +`msgReasonUpdateMod`:: +`msgReasonUpdateAppMod`:: +`msgReasonRestart`:: +`msgReasonShutdown`:: + Alternative templated messages for warnings with the following + replacement parameters: + + `{reason}`;; + Valid in `msgWarnReason`, replaced at runtime with the appropriate `msgReason*` template + + `{time}`;; + Valid in `msgWarnReason`, replaced at runtime with the appropriate `msgTime*` template + + `{modnamesupdate}`;; + Valid in `msgReason*Mod`, replaced at runtime with a comma-delimited list of updated mod names + + `{minutes}`;; + Valid in `msgTimeMinutes`, replaced at runtime with minutes remaining until shutdown + + `{seconds}`;; + Valid in `msgTimeSeconds`, replaced at runtime with seconds remaining until shutdown + `logdir`:: Specifies where to store log files From 41097175fa86f6e6866a4f83984c2ced01cf54df Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 19 May 2016 19:09:18 +1000 Subject: [PATCH 23/24] Add cancelshutdown command --- README.asciidoc | 4 ++++ tools/arkmanager | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index ad81caa..a6a68e3 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -211,6 +211,10 @@ instances. Downloads the update but does not apply it. Only has effect if a staging directory is set. +`cancelshutdown`:: + Cancels a pending update / shutdown / restart that was run with + the `--warn` option + `checkupdate`:: Checks if an ARK server update is available diff --git a/tools/arkmanager b/tools/arkmanager index 898dcf8..2629212 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -831,7 +831,9 @@ doStop() { done if [[ -n "$dowarn" ]]; then - doWarn "$1" "$warnreason" + if ! doWarn "$1" "$warnreason"; then + return 1 + fi fi if [[ -n "$dosave" ]]; then doSaveWorld @@ -910,6 +912,20 @@ doInstall() { getCurrentVersion } + +# +# Cancels a pending shutdown +# +doCancelShutdown(){ + if [ -f "${arkserverroot}/.ark-warn.lock" ]; then + local lockpid="$(<"${arkserverroot}/.ark-warn.lock")" + if [ -n "$lockpid" ]; then + kill "$lockpid" + rm -f "${arkserverroot}/.ark-warn.lock" + fi + fi +} + # # Formats a warning message based on replacement strings # @@ -1028,11 +1044,27 @@ doWarn(){ cd "$arkserverroot" ( + echo "$$" >"${arkserverroot}/.ark-warn.lock.$$" 2>/dev/null + while true; do + if ! ln "${arkserverroot}/.ark-warn.lock.$$" "${arkserverroot}/.ark-warn.lock" 2>/dev/null; then + local lockpid="$(<"${arkserverroot}/.ark-warn.lock")" + if [ -n "$lockpid" ] && [ "$lockpid" != "$$" ] && kill -0 "$lockpid" 2>/dev/null; then + echo "Shutdown warning already in progress (PID: $lockpid)" + rm -f "${arkserverroot}/.ark-warn.lock.$$" 2>/dev/null + exit 1 + fi + rm -f "${arkserverroot}/.ark-warn.lock" + else + break + fi + done + rm -f "${arkserverroot}/.ark-warn.lock.$$" + update_cancelled(){ if [ -n "$msgUpdateCancelled" ]; then msg="${msgUpdateCancelled//%s/$1}" else - msg="Update cancelled by operator ($1)" + msg="Shutdown cancelled by operator ($1)" fi doBroadcastWithEcho "${msg}" } @@ -1056,6 +1088,7 @@ doWarn(){ for warninterval in "${warnintervals[@]}"; do if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting $1" + rm -f "${arkserverroot}/.ark-warn.lock" return 1 fi if (( warnminutes >= warninterval )); then @@ -1067,6 +1100,7 @@ doWarn(){ echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" + rm -f "${arkserverroot}/.ark-warn.lock" return 0 fi wait $sleeppid @@ -1086,6 +1120,7 @@ doWarn(){ sleeppid=$! if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting update" + rm -f "${arkserverroot}/.ark-warn.lock" return 1 fi printWarnMessage "$1" "$2" "seconds" "$warnseconds" @@ -1094,6 +1129,7 @@ doWarn(){ echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" + rm -f "${arkserverroot}/.ark-warn.lock" return 0 fi fi @@ -1102,6 +1138,8 @@ doWarn(){ done fi + rm -f "${arkserverroot}/.ark-warn.lock" + if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting $1" return 1 @@ -2204,6 +2242,9 @@ while true; do doStop restart "${options[@]}" echo "`timestamp`: stop" >> "$logdir/$arkmanagerLog" ;; + cancelshutdown) + doCancelShutdown "${options[@]}" + ;; install) doInstall ;; From 6b22944fe611eb96cdd6e3f9e11685b97daff4f3 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 21 May 2016 19:26:04 +1000 Subject: [PATCH 24/24] Print SteamCMD command being executed --- tools/arkmanager | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 2629212..d5488e1 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -369,6 +369,9 @@ function runSteamCMD(){ function runSteamCMDspinner(){ if [ -n "$verbose" ]; then + printf "Executing" + printf " %q" "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 +login ${steamlogin:-anonymous} "$@" +quit + printf "\n" if command >&3; then runSteamCMD "$@" | tee /dev/fd/3 else