From 7f797acd951d4c1c928237aaa425a307e4220f0e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 27 Feb 2016 22:06:04 +1000 Subject: [PATCH 001/169] Begin development on v1.6 --- .version | 2 +- tools/arkmanager | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.version b/.version index c239c60..810ee4e 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -1.5 +1.6 diff --git a/tools/arkmanager b/tools/arkmanager index 52c7633..7bccf83 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,7 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion="1.5" +arkstVersion="1.6" arkstCommit='' doUpgradeTools() { From 7014502ee1e542278b95a94af1225e199c3f1274 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 20 Feb 2016 21:36:19 +1000 Subject: [PATCH 002/169] 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 003/169] 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 004/169] 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 005/169] 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 006/169] 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 007/169] 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 008/169] 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 009/169] 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 010/169] 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 011/169] 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 012/169] 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 013/169] 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 014/169] 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 015/169] 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 016/169] 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 017/169] 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 018/169] 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 019/169] 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 020/169] 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 021/169] 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 022/169] 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 023/169] 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 024/169] 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 025/169] 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 From 5f317c8d5754e2b03019ce8f9a2089d743c76b81 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 28 May 2016 13:25:01 +1000 Subject: [PATCH 026/169] Allow {time} in warning reason --- README.asciidoc | 2 +- tools/arkmanager | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index a6a68e3..07b896e 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -377,7 +377,7 @@ The following options can be overridden on a per-instance basis: Valid in `msgWarnReason`, replaced at runtime with the appropriate `msgReason*` template `{time}`;; - Valid in `msgWarnReason`, replaced at runtime with the appropriate `msgTime*` template + Valid in `msgWarnReason` and `msgReason*`, 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 diff --git a/tools/arkmanager b/tools/arkmanager index d5488e1..2d4775c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -988,6 +988,7 @@ printWarnMessage(){ reason="maintenance" fi fi + reason="${reason//\{time\}/${msgtime}}" reason="${reason//\{modnamesupdated\}/${modnamesupdated}}" msg="${msg//\{reason\}/${reason}}" printf "%s\n" "$msg" From f9668ceae05bc46d9b2726f1dd29e5e42aa871bc Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 28 May 2016 13:35:03 +1000 Subject: [PATCH 027/169] Fix a typo in the documentation --- README.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index 07b896e..ac3784f 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -379,7 +379,7 @@ The following options can be overridden on a per-instance basis: `{time}`;; Valid in `msgWarnReason` and `msgReason*`, replaced at runtime with the appropriate `msgTime*` template - `{modnamesupdate}`;; + `{modnamesupdated}`;; Valid in `msgReason*Mod`, replaced at runtime with a comma-delimited list of updated mod names `{minutes}`;; From ea6de39917175edd3af434736c6467a2c71adc88 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 28 May 2016 20:19:06 +1000 Subject: [PATCH 028/169] " \n " added to empty response message Server response when a command returns no response is "Server received, But no response!! \n " --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2d4775c..3fa123a 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -323,10 +323,10 @@ rconcmd() { auth($socket, $password); sendpkt($socket, 2, 2, $command); my ($resid, $restype, $rcvbody) = recvpkt($socket); - if ($rcvbody eq "Server received, But no response!!") { + if ($rcvbody eq "Server received, But no response!! \n ") { print "Command processed\n"; } else { - print $rcvbody, "\n"; + print "\"", $rcvbody, "\"\n"; } ' "$(getRconPort)" "${ark_MultiHome:-127.0.0.1}" "$adminpass" "$1" } From 957a5689dc7b0cc4b3793f43ac7b982fbe53ce41 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 28 May 2016 20:41:25 +1000 Subject: [PATCH 029/169] Fix an error in doWarn that was causing duplicate warnings --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 3fa123a..a854b88 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1099,7 +1099,7 @@ doWarn(){ sleep 1m & sleeppid=$! printWarnMessage "$1" "$2" "minutes" "$warnminutes" - for (( min = warnminutes - 1; min >= warninterval; min-- )); do + for (( min = warnminutes; min >= warninterval; min-- )); do numplayers=$(numPlayersConnected) echo "There are ${numplayers} players connected" if (( (numplayers + 0) == 0 )); then @@ -1113,7 +1113,7 @@ doWarn(){ sleeppid=$! fi done - warnminutes=$warninterval + warnminutes=$(( warninterval - 1 )) fi done From 0be8a67ba0ff4222ffd7328cb02b849b8e0aa0e2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 02:25:11 +1000 Subject: [PATCH 030/169] Actually cancel warning when Ctrl-C etc are pressed --- tools/arkmanager | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arkmanager b/tools/arkmanager index a854b88..2b82806 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1071,6 +1071,7 @@ doWarn(){ msg="Shutdown cancelled by operator ($1)" fi doBroadcastWithEcho "${msg}" + exit 1 } trap "update_cancelled 'Ctrl+C'" SIGINT From e2c3fa3c683dc12bb3c2590699cd797070fd814a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 02:27:37 +1000 Subject: [PATCH 031/169] Fix warning in runSteamCMDspinner --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2b82806..504d1b6 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -386,7 +386,7 @@ function runSteamCMDspinner(){ progressDisplayType=dots fi fi - if command >&3; then + if (command >&3) 2>/dev/null; then runSteamCMD "$@" >&3 & else runSteamCMD "$@" >/dev/null & From ca3ff1e5f6b550acdd71ab2c8a0a6b9ed027591a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 02:38:19 +1000 Subject: [PATCH 032/169] Fix restart --warn broadcasting shutdown message --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 504d1b6..7b9cb82 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -834,7 +834,7 @@ doStop() { done if [[ -n "$dowarn" ]]; then - if ! doWarn "$1" "$warnreason"; then + if ! doWarn "$stopreason" "$warnreason"; then return 1 fi fi From 6ae8a442990af2306b9318b0a4a2701b44ac2a4e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 12:54:59 +1000 Subject: [PATCH 033/169] Fix error in runSteamCMDspinnerSubst --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 7b9cb82..533deff 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1383,7 +1383,7 @@ doDownloadMod(){ while true; do echo -n "Downloading mod $modid" - local output=$(runSteamCMDspinnerSubst 5 +workshop_download_item $mod_appid $modid) 5>&1 + local output=$(runSteamCMDspinnerSubst 5 +workshop_download_item $mod_appid $modid) result=$? if [ $result -eq 0 ]; then modsrcdir="$(echo "$output" | sed -n 's@^Success. Downloaded item [0-9][0-9]* to "\([^"]*\)" .*@\1@p')" @@ -1400,7 +1400,7 @@ doDownloadMod(){ fi echo "Mod $modid not fully downloaded - retrying" fi - done + done 5>&1 if [ -f "$modsrcdir/mod.info" ]; then echo "Mod $modid downloaded" From 2b160082aa50f935aedba003fd899858d114416e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 18:10:01 +1000 Subject: [PATCH 034/169] Fix permission denied error when updating mods --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 533deff..86eeee5 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1400,7 +1400,7 @@ doDownloadMod(){ fi echo "Mod $modid not fully downloaded - retrying" fi - done 5>&1 + done 5> >(cat) if [ -f "$modsrcdir/mod.info" ]; then echo "Mod $modid downloaded" From 6b9245cb638a51ec83f30d52d9588dc2be45c32b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 18:18:05 +1000 Subject: [PATCH 035/169] Fix spinner --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 86eeee5..27faac2 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -380,7 +380,7 @@ function runSteamCMDspinner(){ return $? else if [ -z "$progressDisplayType" ]; then - if stty <&1 >/dev/null 2>&1; then + if stty <&2 >/dev/null 2>&1; then progressDisplayType=spinner else progressDisplayType=dots From cbe5e2ea5034213efbbc91d9873e2cc8f3d915cf Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 18:39:03 +1000 Subject: [PATCH 036/169] Fix Blob SHA breakage --- netinstall.sh | 2 -- tools/arkmanager | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/netinstall.sh b/netinstall.sh index e1e679a..564b3d9 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -43,8 +43,6 @@ curl -L -k -s https://github.com/FezVrasta/ark-server-tools/archive/${COMMIT}.ta # Install ARK Server Tools cd ark-server-tools-${COMMIT}/tools sed -i "s|^arkstCommit='.*'$|arkstCommit='${COMMIT}'|" arkmanager -version=`<../.version` -sed -i "s|^arkstVersion=\".*\"|arkstVersion='${version}'|" arkmanager chmod +x install.sh bash install.sh "$steamcmd_user" "$@" >"$output" 2>&1 diff --git a/tools/arkmanager b/tools/arkmanager index 27faac2..57d6ef3 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,7 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion="1.6" +arkstVersion='1.6' arkstCommit='' doUpgradeTools() { @@ -2191,7 +2191,8 @@ 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)" + blobsize="$(sed "s@^arkstCommit=.*@arkstCommit=''@" "$0" | wc -c)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From 06e1c190443e20cd7166e800a351733918e1eb79 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 20:03:16 +1000 Subject: [PATCH 037/169] remove-mods removes mods from workshop directory --- tools/arkmanager | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 57d6ef3..2d1f342 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1672,6 +1672,26 @@ doUninstallMod(){ fi } +# +# Removes mod from steamcmd workshop directory +# +doRemoveMods(){ + local modid + for modid in ${1//,/ }; do + if [ -f "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" ]; then + sed -i "/^\\t\\t\"${modid}\"/,/^\\t\\t}/d" "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" + fi + + if [ -d "$steamcmdroot/steamapps/workshop/content/${mod_appid}/${modid}" ]; then + rm -rf "$steamcmdroot/steamapps/workshop/content/${mod_appid}/${modid}" + fi + + if [ -d "$steamcmdroot/steamapps/workshop/downloads/${mod_appid}/${modid}" ]; then + rm -rf "$steamcmdroot/steamapps/workshop/downloads/${mod_appid}/${modid}" + fi + done +} + # # Copies server state to a backup directory # @@ -2125,6 +2145,7 @@ while true; do useconfig) nrarg=1; ;; install-cronjob) nrarg=1; ;; remove-cronjob) nrarg=1; ;; + remove-mods) nrarg=1; ;; esac # Enumerate the options and arguments @@ -2181,6 +2202,10 @@ while true; do defaultinstance="${args[0]}" continue ;; + remove-mods) + doRemoveMods "${args[0]}" + continue + ;; list-instances) doListAllInstances "${options[@]}" exit From f0ef9fdaf7e7329e482499f0c3067fa1f947aa4c Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 20:18:45 +1000 Subject: [PATCH 038/169] Add remove-mods to readme --- README.asciidoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index ac3784f..21c43a7 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -129,6 +129,9 @@ Instanceless commands `useconfig`:: Legacy command for specifying an instance for the following command(s) +`remove-mods`:: + Remove the specified mods from the `steamcmd` workshop directory + Commands acting on instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From e8de3826c985b4619abe2192aea1abac8cf03b6f Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 30 May 2016 20:29:15 +1000 Subject: [PATCH 039/169] Avoid "no command" message if remove-mods is only command --- tools/arkmanager | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2d1f342..4263495 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2204,7 +2204,11 @@ while true; do ;; remove-mods) doRemoveMods "${args[0]}" - continue + if [ $# -eq 0 ]; then + exit 0 + else + continue + fi ;; list-instances) doListAllInstances "${options[@]}" From cb22f09df283291f5aad28065a40df86d4774573 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 31 May 2016 18:46:37 +1000 Subject: [PATCH 040/169] Fix mod download not being retried --- tools/arkmanager | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 4263495..9c143c9 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -372,8 +372,8 @@ function runSteamCMDspinner(){ printf "Executing" printf " %q" "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 +login ${steamlogin:-anonymous} "$@" +quit printf "\n" - if command >&3; then - runSteamCMD "$@" | tee /dev/fd/3 + if (command >&3) 2>/dev/null; then + runSteamCMD "$@" > >(tee /dev/fd/3) else runSteamCMD "$@" fi @@ -1383,7 +1383,8 @@ doDownloadMod(){ while true; do echo -n "Downloading mod $modid" - local output=$(runSteamCMDspinnerSubst 5 +workshop_download_item $mod_appid $modid) + local output + output=$(runSteamCMDspinnerSubst 5 +workshop_download_item $mod_appid $modid) result=$? if [ $result -eq 0 ]; then modsrcdir="$(echo "$output" | sed -n 's@^Success. Downloaded item [0-9][0-9]* to "\([^"]*\)" .*@\1@p')" From eb99bb7391c8f5966c245e7c548ea51ff300ee36 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 6 Jun 2016 07:54:47 +1000 Subject: [PATCH 041/169] Add --no-download option to update --- tools/arkmanager | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 9c143c9..5b31a0d 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1166,6 +1166,7 @@ doUpdate() { local modupdate= local saveworld= local downloadonly= + local nodownload= for arg in "$@"; do if [ "$arg" == "--force" ]; then @@ -1189,6 +1190,8 @@ doUpdate() { arkStagingDir="${ark#--stagingdir=}" elif [ "$arg" == "--downloadonly" ]; then downloadonly=1 + elif [ "$arg" == "--no-download" ]; then + nodownload=1 else echo "Unrecognized option $arg" echo "Try 'arkmanager -h' or 'arkmanager --help' for more information." @@ -1213,8 +1216,10 @@ doUpdate() { rm -f "${arkserverroot}/.ark-update.lock.$$" if [ -n "$modupdate" ]; then - if ! doDownloadAllMods; then - modupdate= + if [ -z "$nodownload" ]; then + if ! doDownloadAllMods; then + modupdate= + fi fi if ! isAnyModUpdateNeeded; then modupdate= @@ -1244,12 +1249,14 @@ doUpdate() { rm -rf "$arkStagingDir/ShooterGame/Saved/"* fi - echo -n "Downloading ARK update" - cd "$steamcmdroot" - runSteamCMDAppUpdate "$arkStagingDir" $validate - if [ -d "${arkStagingDir}/steamapps/downloading/${appid}" ]; then - echo "Update download interrupted" - return 1 + if [ -z "$nodownload" ]; then + echo -n "Downloading ARK update" + cd "$steamcmdroot" + runSteamCMDAppUpdate "$arkStagingDir" $validate + if [ -d "${arkStagingDir}/steamapps/downloading/${appid}" ]; then + echo "Update download interrupted" + return 1 + fi fi fi fi From 91776b27a1078922721a023238583d6fdb39894f Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 9 Jun 2016 03:06:04 +1000 Subject: [PATCH 042/169] Clean up after SteamCMD if it returns successful --- tools/arkmanager | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 5b31a0d..a6a0e7f 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1252,8 +1252,11 @@ doUpdate() { if [ -z "$nodownload" ]; then echo -n "Downloading ARK update" cd "$steamcmdroot" - runSteamCMDAppUpdate "$arkStagingDir" $validate - if [ -d "${arkStagingDir}/steamapps/downloading/${appid}" ]; then + if runSteamCMDAppUpdate "$arkStagingDir" $validate; then + rm -rf "${arkStagingDir}/steamapps/downloading/${appid}" + fi + + if [ -d "${arkStagingDir}/steamapps/downloading/${appid}" ]; then echo "Update download interrupted" return 1 fi From 29ffa2f3a35f73b930666761f363f2fc32fbe9d3 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 11 Jun 2016 01:58:35 +1000 Subject: [PATCH 043/169] Make arkmanager script sourceable --- tools/arkmanager | 457 ++++++++++++++++++++++++----------------------- 1 file changed, 233 insertions(+), 224 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index a6a0e7f..a477210 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2114,254 +2114,263 @@ showUsage() { # Main program #--------------------- -# check the configuration and throw errors or warnings if needed -checkConfig +main(){ + # check the configuration and throw errors or warnings if needed + checkConfig -while true; do - options=( ) - allinstances=no - instances=( ) - args=( ) - command="$1" - shift - nrarg=0 + while true; do + options=( ) + allinstances=no + instances=( ) + args=( ) + command="$1" + shift + nrarg=0 - # Handle global options - case "$command" in - --verbose) - verbose=1 - continue - ;; - --dots) - progressDisplayType=dots - continue - ;; - --spinner) - progressDisplayType=spinner - continue - ;; - --cronjob) - inCronJob=true - continue - ;; - esac - - # get the number of arguments for commands that take arguments - case "$command" in - installmod) nrarg=1; ;; - uninstallmod) nrarg=1; ;; - reinstallmod) nrarg=1; ;; - broadcast) nrarg=1; ;; - rconcmd) nrarg=1; ;; - useconfig) nrarg=1; ;; - install-cronjob) nrarg=1; ;; - remove-cronjob) nrarg=1; ;; - remove-mods) nrarg=1; ;; - esac - - # Enumerate the options and arguments - while [ $# -ne 0 ]; do - case "$1" in - --) - shift - break - ;; - --args) - nrarg=$# - ;; + # Handle global options + case "$command" in --verbose) verbose=1 + continue ;; --dots) progressDisplayType=dots + continue ;; --spinner) progressDisplayType=spinner + continue ;; - --*) - options+=( "$1" ) + --cronjob) + inCronJob=true + continue ;; - @all) - allinstances=yes - ;; - @*) - instances+=( "${1#@}" ) - ;; - *) - if [ $nrarg -gt 0 ]; then - args+=( "$1" ) - (( nrarg-- )) - else + esac + + # get the number of arguments for commands that take arguments + case "$command" in + installmod) nrarg=1; ;; + uninstallmod) nrarg=1; ;; + reinstallmod) nrarg=1; ;; + broadcast) nrarg=1; ;; + rconcmd) nrarg=1; ;; + useconfig) nrarg=1; ;; + install-cronjob) nrarg=1; ;; + remove-cronjob) nrarg=1; ;; + remove-mods) nrarg=1; ;; + esac + + # Enumerate the options and arguments + while [ $# -ne 0 ]; do + case "$1" in + --) + shift break + ;; + --args) + nrarg=$# + ;; + --verbose) + verbose=1 + ;; + --dots) + progressDisplayType=dots + ;; + --spinner) + progressDisplayType=spinner + ;; + --*) + options+=( "$1" ) + ;; + @all) + allinstances=yes + ;; + @*) + instances+=( "${1#@}" ) + ;; + *) + if [ $nrarg -gt 0 ]; then + args+=( "$1" ) + (( nrarg-- )) + else + break + fi + ;; + esac + shift + done + + # handle non-instance separately + case "$command" in + upgrade-tools) + doUpgradeTools + exit + ;; + uninstall-tools) + doUninstallTools + exit + ;; + useconfig) + defaultinstance="${args[0]}" + continue + ;; + remove-mods) + doRemoveMods "${args[0]}" + if [ $# -eq 0 ]; then + exit 0 + else + continue fi ;; - esac - shift - done - - # handle non-instance separately - case "$command" in - upgrade-tools) - doUpgradeTools - exit - ;; - uninstall-tools) - doUninstallTools - exit - ;; - useconfig) - defaultinstance="${args[0]}" - continue - ;; - remove-mods) - doRemoveMods "${args[0]}" - if [ $# -eq 0 ]; then - exit 0 - else - continue - fi - ;; - list-instances) - doListAllInstances "${options[@]}" - exit - ;; - --version) - echo "Version: ${arkstVersion}" - echo "Channel: ${arkstChannel}" - if [ -n "${arkstCommit}" ]; then - echo "Commit: ${arkstCommit:0:7}" - fi - blobsize="$(sed "s@^arkstCommit=.*@arkstCommit=''@" "$0" | wc -c)" - echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" - exit 1 - ;; - -h|--help) - showUsage - exit 1 - ;; - "") - echo "arkmanager v${arkstVersion}: no command specified" - showUsage - exit 1 - ;; - esac - - # Handle no instances being specified - if [[ "${#instances[@]}" == 0 && "$allinstances" == "no" ]]; then - if [ -n "$defaultinstance" ]; then - instances=( "$defaultinstance" ) - else - echo "No instances supplied for command ${command} ${options[*]} ${args[*]}" - read -p "Do you wish to run this command for all instances?" -n 1 -r - echo - if [[ "$REPLY" =~ ^[Yy]$ ]]; then - allinstances=yes - else + list-instances) + doListAllInstances "${options[@]}" + exit + ;; + --version) + echo "Version: ${arkstVersion}" + echo "Channel: ${arkstChannel}" + if [ -n "${arkstCommit}" ]; then + echo "Commit: ${arkstCommit:0:7}" + fi + blobsize="$(sed "s@^arkstCommit=.*@arkstCommit=''@" "$0" | wc -c)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 + ;; + -h|--help) + showUsage + exit 1 + ;; + "") + echo "arkmanager v${arkstVersion}: no command specified" + showUsage + exit 1 + ;; + esac + + # Handle no instances being specified + if [[ "${#instances[@]}" == 0 && "$allinstances" == "no" ]]; then + if [ -n "$defaultinstance" ]; then + instances=( "$defaultinstance" ) + else + echo "No instances supplied for command ${command} ${options[*]} ${args[*]}" + read -p "Do you wish to run this command for all instances?" -n 1 -r + echo + if [[ "$REPLY" =~ ^[Yy]$ ]]; then + allinstances=yes + else + exit 1 + fi fi fi - fi - # Handle all instances being requested - if [[ "$allinstances" == "yes" ]]; then - instances=( $(getAllInstanceNames) ) - fi + # Handle all instances being requested + if [[ "$allinstances" == "yes" ]]; then + instances=( $(getAllInstanceNames) ) + fi - # Run the command for each instance requested - for instance in "${instances[@]}"; do - ( - echo "Running command '${command}' for instance '${instance}'" - useConfig "$instance" - checkConfig - - case "$command" in - run) - doRun - ;; - start) - doStart "${options[@]}" - ;; - stop) - doStop shutdown "${options[@]}" - ;; - restart) - doStop restart "${options[@]}" - echo "`timestamp`: stop" >> "$logdir/$arkmanagerLog" - ;; - cancelshutdown) - doCancelShutdown "${options[@]}" - ;; - install) - doInstall - ;; - update) - doUpdate "${options[@]}" - ;; - checkupdate) - checkForUpdate - ;; - installmod) - doInstallMod "${args[@]}" - ;; - uninstallmod) - doUninstallMod "${args[@]}" - ;; - reinstallmod) - doUninstallMod "${args[@]}" - doInstallMod "${args[@]}" - ;; - backup) - doBackup - ;; - broadcast) - doBroadcast "${args[@]}" - ;; - saveworld) - doSaveWorld - ;; - rconcmd) - rconcmd "${args[@]}" - ;; - status) - printStatus - ;; - install-cronjob) - doInstallCronJob "${args[@]}" "${options[@]}" - ;; - remove-cronjob) - doRemoveCronJob "${args[@]}" - ;; - *) - echo -n "arkmanager v${arkstVersion}: unknown command '$command' specified" - showUsage - exit 255 - ;; - esac - ) - laststatus=$? - if [ $laststatus -eq 255 ]; then - exit 1 - elif [ $laststatus -ne 0 ]; then - status=$laststatus - fi - done - - # Perform the restart portion of the restart command - if [[ "$command" == "restart" ]]; then - sleep 1 + # Run the command for each instance requested for instance in "${instances[@]}"; do ( + echo "Running command '${command}' for instance '${instance}'" useConfig "$instance" - doStart "${options[@]}" - echo "`timestamp`: start" >> "$logdir/$arkmanagerLog" - echo "`timestamp`: restart" >> "$logdir/$arkmanagerLog" + checkConfig + + case "$command" in + run) + doRun + ;; + start) + doStart "${options[@]}" + ;; + stop) + doStop shutdown "${options[@]}" + ;; + restart) + doStop restart "${options[@]}" + echo "`timestamp`: stop" >> "$logdir/$arkmanagerLog" + ;; + cancelshutdown) + doCancelShutdown "${options[@]}" + ;; + install) + doInstall + ;; + update) + doUpdate "${options[@]}" + ;; + checkupdate) + checkForUpdate + ;; + installmod) + doInstallMod "${args[@]}" + ;; + uninstallmod) + doUninstallMod "${args[@]}" + ;; + reinstallmod) + doUninstallMod "${args[@]}" + doInstallMod "${args[@]}" + ;; + backup) + doBackup + ;; + broadcast) + doBroadcast "${args[@]}" + ;; + saveworld) + doSaveWorld + ;; + rconcmd) + rconcmd "${args[@]}" + ;; + status) + printStatus + ;; + install-cronjob) + doInstallCronJob "${args[@]}" "${options[@]}" + ;; + remove-cronjob) + doRemoveCronJob "${args[@]}" + ;; + *) + echo -n "arkmanager v${arkstVersion}: unknown command '$command' specified" + showUsage + exit 255 + ;; + esac ) + laststatus=$? + if [ $laststatus -eq 255 ]; then + exit 1 + elif [ $laststatus -ne 0 ]; then + status=$laststatus + fi done - fi - if [ $# -eq 0 ]; then - break - fi -done + # Perform the restart portion of the restart command + if [[ "$command" == "restart" ]]; then + sleep 1 + for instance in "${instances[@]}"; do + ( + useConfig "$instance" + doStart "${options[@]}" + echo "`timestamp`: start" >> "$logdir/$arkmanagerLog" + echo "`timestamp`: restart" >> "$logdir/$arkmanagerLog" + ) + done + fi + + if [ $# -eq 0 ]; then + break + fi + done + + exit $status +} + +# Only execute main function if script is not being sourced +# by another script +if [[ "$(caller)" =~ ^0 ]]; then + main "$@" +fi -exit $status From 6e1627c80175013cba1253efdf362985416f1223 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 12 Jun 2016 15:12:18 +1000 Subject: [PATCH 044/169] Fix update --force with arkStagingDir --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index a477210..afd72cb 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1228,7 +1228,7 @@ doUpdate() { cd "$arkserverroot" - if isUpdateNeeded; then + if [ -n "$appupdate" ] || isUpdateNeeded; then appupdate=1 if [ -n "${arkStagingDir}" -a "${arkStagingDir}" != "${arkserverroot}" ]; then From 8aad9cd42eb6ea98e6de0db626305f5037895f4b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 27 Jun 2016 19:16:57 +1000 Subject: [PATCH 045/169] Don't print the warning message twice --- tools/arkmanager | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index afd72cb..ac73ec7 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -991,7 +991,6 @@ printWarnMessage(){ reason="${reason//\{time\}/${msgtime}}" reason="${reason//\{modnamesupdated\}/${modnamesupdated}}" msg="${msg//\{reason\}/${reason}}" - printf "%s\n" "$msg" else if [ "$1" == "update" ]; then if [ "$3" == "minutes" ]; then From c7053d8a9341032b411d49da95a607746610f0e0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 28 Jun 2016 19:58:26 +1000 Subject: [PATCH 046/169] Fix --stagingdir= parameter --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index ac73ec7..72795ae 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1185,7 +1185,7 @@ doUpdate() { modupdate=1 elif [ "$arg" == "--backup" ]; then arkBackupPreUpdate=true - elif [[ "$arg" =~ "^--stagingdir=" ]]; then + elif [[ "$arg" =~ ^--stagingdir= ]]; then arkStagingDir="${ark#--stagingdir=}" elif [ "$arg" == "--downloadonly" ]; then downloadonly=1 From e1b2cdb8c89d8221250fc41d1b988d23212435a7 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 1 Jul 2016 23:11:28 +1000 Subject: [PATCH 047/169] Add option to allow players to cancel restart --- tools/arkmanager | 30 ++++++++++++++++++++++++++++++ tools/arkmanager.cfg | 4 ++++ 2 files changed, 34 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 72795ae..4c06104 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1040,6 +1040,28 @@ printWarnMessage(){ doBroadcastWithEcho "$msg" } +# +# Checks if a player has requested an update cancel in the last 5 minutes +# +isUpdateCancelRequested(){ + if [ -n "$chatCommandRestartCancel" ]; then + local canceltime="$( + find ~/ARK/server1/ShooterGame/Saved/Logs -name 'ServerGame.*.log' -mmin -5 -print0 | + xargs -0 grep -F -e "${chatCommandRestartCancel}" | + sed 's@^[[]\(....\)\.\(..\)\.\(..\)-\(..\)\.\(..\)\.\(..\):.*@\1-\2-\3 \4:\5:\6 UTC@' | + head -n1)" + if [ -n canceltime ]; then + canceltime="$(date +%s --date="${canceltime}")" + local timenow="$(date +%s --date="now - 5 minutes")" + if (( canceltime > timenow )); then + return 0 + fi + fi + fi + + return 1 +} + # # Waits for a configurable number of minutes before updating the server # @@ -1107,6 +1129,10 @@ doWarn(){ rm -f "${arkserverroot}/.ark-warn.lock" return 0 fi + if isUpdateCancelRequested; then + doBroadcastWithEcho "Restart cancelled by player request" + return 1 + fi wait $sleeppid if (( $min > $warninterval )); then sleep 1m & @@ -1136,6 +1162,10 @@ doWarn(){ rm -f "${arkserverroot}/.ark-warn.lock" return 0 fi + if isUpdateCancelRequested; then + doBroadcastWithEcho "Restart cancelled by player request" + return 1 + fi fi wait $sleeppid warnseconds=$warninterval diff --git a/tools/arkmanager.cfg b/tools/arkmanager.cfg index b563ff2..750f866 100644 --- a/tools/arkmanager.cfg +++ b/tools/arkmanager.cfg @@ -32,6 +32,10 @@ msgWarnRestartMinutes="This ARK server will shutdown for a restart in %d minutes msgWarnRestartSeconds="This ARK server will shutdown for a restart in %d seconds" msgWarnShutdownMinutes="This ARK server will shutdown in %d minutes" msgWarnShutdownSeconds="This ARK server will shutdown in %d seconds" +msgWarnCancelled="Restart cancelled by player request" + +# Restart cancel chat command +#chatCommandRestartCancel="/cancelupdate" # ARK server common options - use ark_= # comment out these values if you want to define them From 3fe29777e6694b6100f26bda48bdb8b202b940d9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 8 Jul 2016 09:29:55 +1000 Subject: [PATCH 048/169] Add support for -automanagedmods --- tools/arkmanager | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 4c06104..76cfa12 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -607,7 +607,7 @@ function numPlayersConnected(){ # run function # doRun() { - cd "$arkserverroot" + cd "${arkserverroot}/${arkserverexec%/*}" arkserveropts="$serverMap" @@ -703,6 +703,14 @@ doRun() { fi done + if [[ " ${arkextraopts[*]} " =~ " -automanagedmods " ]]; then + if [ ! -f "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd.sh" ]; then + mkdir -p "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux" + curl -s "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" -o "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd_linux.tar.gz" + tar -xzf "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd_linux.tar.gz" -C "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux" + fi + fi + arkserveropts="${arkserveropts}?listen" # run the server in background echo "`timestamp`: start" From 4c8d9d53da88a36407f443245f00e4559880889a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 8 Jul 2016 09:43:26 +1000 Subject: [PATCH 049/169] Add -automanagedmods support to update --- tools/arkmanager | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 76cfa12..d12903c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1284,6 +1284,7 @@ doUpdate() { fi rm -rf "$arkStagingDir/ShooterGame/Content/Mods/"* rm -rf "$arkStagingDir/ShooterGame/Saved/"* + rm -rf "$arkStagingDir/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamapps" fi if [ -z "$nodownload" ]; then @@ -1384,7 +1385,7 @@ doUpdate() { echo "`timestamp`: update to $instver complete" >> "$logdir/update.log" fi - if [ -n "$modupdate" ]; then + if [ -n "$modupdate" ] && [ -z "$arkflag_automanagedmods" ]; then for modid in $(getModIds); do if isModUpdateNeeded $modid; then echo "Updating mod $modid" @@ -1423,6 +1424,10 @@ getModIds(){ # doDownloadMod(){ local modid=$1 + local steamcmdroot="$steamcmdroot" + if [ -n "$arkflag_automanagedmods" ]; then + steamcmdroot="$arkserverroot/Engine/Binaries/ThirdParty/SteamCMD/Linux" + fi local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid" local moddldir="$steamcmdroot/steamapps/workshop/downloads/$mod_appid" cd "$steamcmdroot" From 55f9a80dddd6ccf49ce02314393ccdcb5fd179e5 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 14:26:43 +1000 Subject: [PATCH 050/169] Change systemd service type to forking --- tools/systemd/arkmanager.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/systemd/arkmanager.service b/tools/systemd/arkmanager.service index c2d4053..97ec6bd 100644 --- a/tools/systemd/arkmanager.service +++ b/tools/systemd/arkmanager.service @@ -5,7 +5,7 @@ After=network.target [Service] ExecStart=/usr/libexec/arkmanager/arkmanager.init start ExecStop=/usr/libexec/arkmanager/arkmanager.init stop -Type=oneshot +Type=forking [Install] WantedBy=multi-user.target From 794171e7e457d90e4dc002b55862af4102de2309 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 15:50:25 +1000 Subject: [PATCH 051/169] Add option to always auto-restart --- tools/arkmanager | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index d12903c..ffa3dc0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -742,6 +742,9 @@ doRun() { # Disable auto-restart so we don't get caught in a restart loop rm -f "$arkserverroot/$arkautorestartfile" restartserver=0 + if [ -n "$arkAlwaysRestartOnCrash" ]; then + restartserver=1 + fi sleep 5 @@ -762,6 +765,8 @@ doRun() { echo "`timestamp`: Bad PID '$pid'; expected '$serverpid'" if [ "$pid" != "" ]; then # Another instance must be running - disable autorestart + echo "Error: another server instance is running from the same directory" + echo "Aborting - two servers MUST NOT run from the same directory" restartserver=0 fi break @@ -797,6 +802,10 @@ doStart() { doUpdate --update-mods fi fi + + if [[ " $* " =~ " --alwaysrestart " ]]; then + arkAlwaysRestartOnCrash=true + fi tput sc echo "The server is starting..." From f6a770c624e3837a9d2dd83ed9073a61a12cfe0b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 15:59:38 +1000 Subject: [PATCH 052/169] Add arkAlwaysRestartOnCrash to readme --- README.asciidoc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index 21c43a7..d295e60 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -149,6 +149,11 @@ instances. `--noautoupdate`;; Disables automatic updating on startup if it is enabled + `--alwaysrestart`;; + Enable automatically restarting the server even if it crashes + without becoming ready for player connections. + + `stop`:: Stops the server if it is running @@ -343,6 +348,12 @@ The following options can be overridden on a per-instance basis: The relative path within an ARK server install to place the autorestart lock file +`arkAlwaysRestartOnCrash`:: + Set to `true` to enable automatically restarting even when the + server has not become ready for player connections. + Be aware that this may cause the server to enter an endless + crash-restart loop if the cause of the crash is not resolved. + `arkAutoUpdateOnStart`:: Set to `true` to enable updating before server startup From 12198f8f3c6c77f5923d57e8f8c0fc00938af747 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 16:34:43 +1000 Subject: [PATCH 053/169] Add RemainAfterExit=yes to arkmanager.service --- tools/systemd/arkmanager.service | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/systemd/arkmanager.service b/tools/systemd/arkmanager.service index 97ec6bd..55ab37d 100644 --- a/tools/systemd/arkmanager.service +++ b/tools/systemd/arkmanager.service @@ -6,6 +6,7 @@ After=network.target ExecStart=/usr/libexec/arkmanager/arkmanager.init start ExecStop=/usr/libexec/arkmanager/arkmanager.init stop Type=forking +RemainAfterExit=yes [Install] WantedBy=multi-user.target From 2c877336d7024b8c31a251171c06fc1e15457b8a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 2 Mar 2016 00:47:14 +1000 Subject: [PATCH 054/169] 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 52c7633..92a8559 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 46e468d94112e1d4cd4d50ebf9f9a1a05291510d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 7 Mar 2016 15:56:33 +1000 Subject: [PATCH 055/169] 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 92a8559..88b30ff 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 1ea02d9f1ff5494e98a29c83c935edf3c3a608cd Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 9 Mar 2016 19:32:01 +1000 Subject: [PATCH 056/169] 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 88b30ff..58b0bde 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -913,7 +913,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 @@ -940,7 +940,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 @@ -1078,7 +1078,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 9b714824f544fe28bd2d140b8e9460525c67f814 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 17 May 2016 08:11:40 +1000 Subject: [PATCH 057/169] 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 92923df0ebc31a0ae9eddcbdf2502eabb8e90ae0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 28 May 2016 20:19:06 +1000 Subject: [PATCH 058/169] " \n " added to empty response message Server response when a command returns no response is "Server received, But no response!! \n " --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 58b0bde..4000b47 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -320,10 +320,10 @@ rconcmd() { auth($socket, $password); sendpkt($socket, 2, 2, $command); my ($resid, $restype, $rcvbody) = recvpkt($socket); - if ($rcvbody eq "Server received, But no response!!") { + if ($rcvbody eq "Server received, But no response!! \n ") { print "Command processed\n"; } else { - print $rcvbody, "\n"; + print "\"", $rcvbody, "\"\n"; } ' "$(getRconPort)" "${ark_MultiHome:-127.0.0.1}" "$adminpass" "$1" } From 273879aa23f657d95d8c2e5bc22b471c2aab03e9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 12 Jun 2016 15:12:18 +1000 Subject: [PATCH 059/169] Fix update --force with arkStagingDir --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 4000b47..37ffde6 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1025,7 +1025,7 @@ doUpdate() { cd "$arkserverroot" - if isUpdateNeeded; then + if [ -n "$appupdate" ] || isUpdateNeeded; then appupdate=1 if [ -n "${arkStagingDir}" -a "${arkStagingDir}" != "${arkserverroot}" ]; then From 9382c43b5b941330679e8b19a2e639191430c9de Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 28 Jun 2016 19:58:26 +1000 Subject: [PATCH 060/169] Fix --stagingdir= parameter --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 37ffde6..812cc10 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -987,7 +987,7 @@ doUpdate() { modupdate=1 elif [ "$arg" == "--backup" ]; then arkBackupPreUpdate=true - elif [[ "$arg" =~ "^--stagingdir=" ]]; then + elif [[ "$arg" =~ ^--stagingdir= ]]; then arkStagingDir="${ark#--stagingdir=}" elif [ "$arg" == "--downloadonly" ]; then downloadonly=1 From 8dda5784f1bdc71f81a3fd15dda3b8dfc73eafc9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 14:26:43 +1000 Subject: [PATCH 061/169] Change systemd service type to forking --- tools/systemd/arkmanager.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/systemd/arkmanager.service b/tools/systemd/arkmanager.service index c2d4053..97ec6bd 100644 --- a/tools/systemd/arkmanager.service +++ b/tools/systemd/arkmanager.service @@ -5,7 +5,7 @@ After=network.target [Service] ExecStart=/usr/libexec/arkmanager/arkmanager.init start ExecStop=/usr/libexec/arkmanager/arkmanager.init stop -Type=oneshot +Type=forking [Install] WantedBy=multi-user.target From 7fbb47ad5c892f1357db12778442a2c6e57e38a3 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 9 Jul 2016 16:34:43 +1000 Subject: [PATCH 062/169] Add RemainAfterExit=yes to arkmanager.service --- tools/systemd/arkmanager.service | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/systemd/arkmanager.service b/tools/systemd/arkmanager.service index 97ec6bd..55ab37d 100644 --- a/tools/systemd/arkmanager.service +++ b/tools/systemd/arkmanager.service @@ -6,6 +6,7 @@ After=network.target ExecStart=/usr/libexec/arkmanager/arkmanager.init start ExecStop=/usr/libexec/arkmanager/arkmanager.init stop Type=forking +RemainAfterExit=yes [Install] WantedBy=multi-user.target From 7de6c8ed245b2cc699d828ca93b5f42f3817c976 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 10 Jul 2016 18:44:49 +1000 Subject: [PATCH 063/169] Create the saved arks directory if it doesn't exist --- tools/arkmanager | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arkmanager b/tools/arkmanager index 812cc10..7d200ea 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -199,6 +199,7 @@ checkConfig() { # SavedArks directory if [ -n "$arkserverroot" ]; then local savedarksdir="${arkserverroot}/ShooterGame/Saved/${ark_AltSaveDirectoryName:-SavedArks}" + mkdir -p "${savedarksdir}" if [ ! -w "${savedarksdir}" ]; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tThe ARK SavedArks directory is not writable, and saveworld will fail" fi From b22b16b41db4176d1826f9342589d988bca69b7a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 10 Jul 2016 18:44:49 +1000 Subject: [PATCH 064/169] Create the saved arks directory if it doesn't exist --- tools/arkmanager | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arkmanager b/tools/arkmanager index ffa3dc0..14f557c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -202,6 +202,7 @@ checkConfig() { # SavedArks directory if [ -n "$arkserverroot" ]; then local savedarksdir="${arkserverroot}/ShooterGame/Saved/${ark_AltSaveDirectoryName:-SavedArks}" + mkdir -p "${savedarksdir}" if [ ! -w "${savedarksdir}" ]; then echo -e "[" "$RED" "ERROR" "$NORMAL" "]" "\tThe ARK SavedArks directory is not writable, and saveworld will fail" fi From 6d207952b5fdefd84462bb535d4a5d1f537cc620 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 11 Jul 2016 10:03:44 +1000 Subject: [PATCH 065/169] Fix arkAlwaysRestartOnCrash --- tools/arkmanager | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 14f557c..5c0e97b 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -745,6 +745,7 @@ doRun() { restartserver=0 if [ -n "$arkAlwaysRestartOnCrash" ]; then restartserver=1 + touch "$arkserverroot/$arkautorestartfile" fi sleep 5 @@ -782,6 +783,7 @@ doRun() { # doStop will remove the autorestart file if [ ! -f "$arkserverroot/$arkautorestartfile" ]; then restartserver=0 + fi if [ "$restartserver" -ne 0 ]; then From 7f8aa05e80102dc03719b2b79b4f594b97c5a1a8 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 11 Jul 2016 13:23:54 +1000 Subject: [PATCH 066/169] Add printconfig command This new command will print the file that each config option is taken from. --- tools/arkmanager | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 5c0e97b..3197a44 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2088,6 +2088,23 @@ doListAllInstances(){ fi } +doPrintConfig(){ + declare -A vars + declare -A vals + for v in $(eval echo \$\{\!{a..z}\*\} \$\{\!{A..Z}\*\} \$\{\!_\*\}); do + vals["$v"]="${!v}" + done + for cfgfile in "$configfile" "$HOME/.arkmanager.cfg" "/etc/arkmanager/arkmanager.cfg"; do + while read v; do + val="$(source "$cfgfile"; echo "${!v}")" + if [[ "$val" = "${vals[$v]}" && -z "${vars[$v]}" ]]; then + vars["$v"]="$cfgfile" + echo "${cfgfile} => ${v}" + fi + done < <(sed -n 's/^[[:space:]]*\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p' <"$cfgfile") + done +} + useConfig() { configfile= if [ -f "/etc/arkmanager/instances/${1}.cfg" ]; then @@ -2377,6 +2394,9 @@ main(){ rconcmd) rconcmd "${args[@]}" ;; + printconfig) + doPrintConfig + ;; status) printStatus ;; From 23757124c92d863ded13a21c8e3edcf2a45cd5cc Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 11 Jul 2016 11:17:45 +1000 Subject: [PATCH 067/169] Change config migration Write new example global config to `arkmanager.cfg.example` Write migrated global config to `arkmanager.cfg.NEW` Write migrated main instance config to `instances/main.cfg.NEW` --- tools/install.sh | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/tools/install.sh b/tools/install.sh index cf801ed..eac2d60 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -3,6 +3,7 @@ userinstall=no steamcmd_user= showusage=no +migrateconfig=no while [ -n "$1" ]; do case "$1" in @@ -63,6 +64,9 @@ while [ -n "$1" ]; do DATADIR="$2" shift ;; + --migrate-config) + migrateconfig=yes + ;; -*) echo "Invalid option '$1'" showusage=yes @@ -169,7 +173,7 @@ if [ "$userinstall" == "yes" ]; then "${INSTALL_ROOT}${INSTANCEDIR}/instance.cfg.example" # Copy arkmanager.cfg to ~/.arkmanager.cfg.NEW - cp arkmanager.cfg "${INSTALL_ROOT}${CONFIGFILE}.NEW" + cp arkmanager.cfg "${INSTALL_ROOT}${CONFIGFILE}.example" # Change the defaults in the new config file sed -i -e "s|^steamcmd_user=\"steam\"|steamcmd_user=\"--me\"|" \ -e "s|\"/home/steam|\"${PREFIX}|" \ @@ -177,18 +181,24 @@ if [ "$userinstall" == "yes" ]; then -e "s|^install_bindir=.*|install_bindir=\"${BINDIR}\"|" \ -e "s|^install_libexecdir=.*|install_libexecdir=\"${LIBEXECDIR}\"|" \ -e "s|^install_datadir=.*|install_datadir=\"${DATADIR}\"|" \ - "${INSTALL_ROOT}${CONFIGFILE}.NEW" + "${INSTALL_ROOT}${CONFIGFILE}.example" # Copy arkmanager.cfg to ~/.arkmanager.cfg if it doesn't already exist if [ -f "${INSTALL_ROOT}${CONFIGFILE}" ]; then - bash ./migrate-config.sh "${INSTALL_ROOT}${CONFIGFILE}" - bash ./migrate-main-instance.sh "${INSTALL_ROOT}${CONFIGFILE}" "${INSTALL_ROOT}${INSTANCEDIR}/main.cfg" + SUFFIX= + if [ "$migrateconfig" = "no" ]; then + SUFFIX=".NEW" + cp "${INSTALL_ROOT}${CONFIGFILE}" "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" + fi + + bash ./migrate-config.sh "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" + bash ./migrate-main-instance.sh "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" "${INSTALL_ROOT}${INSTANCEDIR}/main.cfg${SUFFIX}" echo "A previous version of ARK Server Tools was detected in your system, your old configuration was not overwritten. You may need to manually update it." echo "A copy of the new configuration file was included in '${CONFIGFILE}.NEW'. Make sure to review any changes and update your config accordingly!" exit 2 else - mv -n "${INSTALL_ROOT}${CONFIGFILE}.NEW" "${INSTALL_ROOT}${CONFIGFILE}" + cp -n "${INSTALL_ROOT}${CONFIGFILE}.example" "${INSTALL_ROOT}${CONFIGFILE}" cp -n "${INSTALL_ROOT}/${INSTANCEDIR}/instance.cfg.example" "${INSTALL_ROOT}/${INSTANCEDIR}/main.cfg" fi else @@ -301,24 +311,30 @@ else # Copy arkmanager.cfg inside linux configuation folder if it doesn't already exists mkdir -p "${INSTALL_ROOT}/etc/arkmanager" chown "$steamcmd_user" "${INSTALL_ROOT}/etc/arkmanager" - cp arkmanager.cfg "${INSTALL_ROOT}${CONFIGFILE}.NEW" - chown "$steamcmd_user" "${INSTALL_ROOT}${CONFIGFILE}.NEW" + cp arkmanager.cfg "${INSTALL_ROOT}${CONFIGFILE}.example" + chown "$steamcmd_user" "${INSTALL_ROOT}${CONFIGFILE}.example" sed -i -e "s|^steamcmd_user=\"steam\"|steamcmd_user=\"$steamcmd_user\"|" \ -e "s|\"/home/steam|\"/home/$steamcmd_user|" \ -e "s|^install_bindir=.*|install_bindir=\"${BINDIR}\"|" \ -e "s|^install_libexecdir=.*|install_libexecdir=\"${LIBEXECDIR}\"|" \ -e "s|^install_datadir=.*|install_datadir=\"${DATADIR}\"|" \ - "${INSTALL_ROOT}${CONFIGFILE}.NEW" + "${INSTALL_ROOT}${CONFIGFILE}.example" if [ -f "${INSTALL_ROOT}${CONFIGFILE}" ]; then - bash ./migrate-config.sh "${INSTALL_ROOT}${CONFIGFILE}" - bash ./migrate-main-instance.sh "${INSTALL_ROOT}${CONFIGFILE}" "${INSTALL_ROOT}${INSTANCEDIR}/main.cfg" + SUFFIX= + if [ "$migrateconfig" = "no" ]; then + SUFFIX=".NEW" + cp "${INSTALL_ROOT}${CONFIGFILE}" "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" + fi + + bash ./migrate-config.sh "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" + bash ./migrate-main-instance.sh "${INSTALL_ROOT}${CONFIGFILE}${SUFFIX}" "${INSTALL_ROOT}${INSTANCEDIR}/main.cfg${SUFFIX}" echo "A previous version of ARK Server Tools was detected in your system, your old configuration was not overwritten. You may need to manually update it." echo "A copy of the new configuration file was included in /etc/arkmanager. Make sure to review any changes and update your config accordingly!" exit 2 else - mv -n "${INSTALL_ROOT}${CONFIGFILE}.NEW" "${INSTALL_ROOT}${CONFIGFILE}" + cp -n "${INSTALL_ROOT}${CONFIGFILE}.example" "${INSTALL_ROOT}${CONFIGFILE}" cp -n "${INSTALL_ROOT}/${INSTANCEDIR}/instance.cfg.example" "${INSTALL_ROOT}/${INSTANCEDIR}/main.cfg" fi fi From 30af1a92a13d0ab35f2e7d77153e2db313a10230 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Wed, 13 Jul 2016 14:18:15 +0200 Subject: [PATCH 068/169] Default non-privileged instance-config path Default non-privileged instance-config path seems to have changed to ~/.config/ --- README.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index 31abc77..00ed4ac 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -368,7 +368,7 @@ Instance config files Instance config files are stored under `/etc/arkmanager/instances/.cfg`, -`~/.local/config/arkmanager/instances/.cfg` +`~/.config/arkmanager/instances/.cfg` or as specified in the `configfile_` options in the global config. From 4d4f4888638d3d4899c566eed46b0d18db242f7b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 13 Jul 2016 23:08:19 +1000 Subject: [PATCH 069/169] Improve restart behaviour using pid files --- tools/arkmanager | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 3197a44..bf672e3 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -151,6 +151,8 @@ arkserverLog="arkserver.log" # here is logged the output of ShooterGameServer appid="${appid:-376030}" mod_appid="${mod_appid:-346110}" arkautorestartfile="${arkautorestartfile:-ShooterGame/Saved/.autorestart}" +arkserverpidfile="${arkserverpidfile:-ShooterGame/Saved/.arkserver.pid}" +arkmanagerpidfile="${arkmanagerpidfile:-ShooterGame/Saved/.arkmanager.pid}" install_bindir="${install_bindir:-${0%/*}}" install_libexecdir="${install_libexecdir:-${install_bindir%/*}/libexec/arkmanager}" @@ -507,6 +509,13 @@ function getAvailableVersion(){ # Get the PID of the server process # function getServerPID(){ + if [ -f "${arkserverroot}/${arkserverpidfile}" ]; then + serverpid="$(<"${arkserverroot}/${arkserverpidfile}")" + if kill -0 "$serverpid" >/dev/null 2>&1; then + echo $serverpid + return + fi + fi ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}' } @@ -610,6 +619,14 @@ function numPlayersConnected(){ doRun() { cd "${arkserverroot}/${arkserverexec%/*}" + if isTheServerRunning; then + echo "Error: another server instance is running from the same directory" + echo "Aborting - two servers MUST NOT run from the same directory" + exit 1 + fi + + echo "$$" >"${arkserverroot}/${arkmanagerpidfile}" + arkserveropts="$serverMap" if [ -n "$serverMapModId" ]; then @@ -722,10 +739,11 @@ doRun() { # Shutdown the server when we are terminated shutdown_server(){ restartserver=0 - rm "$arkserverroot/$arkautorestartfile" + rm -f "$arkserverroot/$arkautorestartfile" if [ "$serverpid" -ne 0 ]; then - kill -INT $serverpid + kill -INT $serverpid >/dev/null 2>&1 fi + exit 0 } trap shutdown_server INT TERM @@ -739,6 +757,7 @@ doRun() { "$arkserverroot/$arkserverexec" "$arkserveropts" "${arkextraopts[@]}" & # Grab the server PID serverpid=$! + echo "$serverpid" >"${arkserverroot}/${arkserverpidfile}" echo "`timestamp`: Server PID: $serverpid" # Disable auto-restart so we don't get caught in a restart loop rm -f "$arkserverroot/$arkautorestartfile" @@ -767,8 +786,6 @@ doRun() { echo "`timestamp`: Bad PID '$pid'; expected '$serverpid'" if [ "$pid" != "" ]; then # Another instance must be running - disable autorestart - echo "Error: another server instance is running from the same directory" - echo "Aborting - two servers MUST NOT run from the same directory" restartserver=0 fi break @@ -882,6 +899,13 @@ doStop() { kill -KILL $PID fi + if [ -f "${arkserverroot}/${arkmanagerpidfile}" ]; then + PID="$(<"${arkserverroot}/${arkmanagerpidfile}")" + if [ -n "$PID" ]; then + kill $PID + fi + fi + tput rc; tput ed; echo "The server has been stopped" echo "`timestamp`: stopped" >> "$logdir/$arkmanagerLog" From 4786e5e9253bee0693726be1fbca686adf01649d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 15 Jul 2016 16:35:30 +1000 Subject: [PATCH 070/169] Fix --arg bug in install-cronjob --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index bf672e3..d28afda 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2002,7 +2002,7 @@ doInstallCronJob(){ output= ;; --arg=*) - cmdargs="${cmdargs} $(printf "%q" "${opt#--opt=}")" + cmdargs="${cmdargs} $(printf "%q" "${opt#--arg=}")" ;; --*) cmdopts="${cmdopts} $(printf "%q" "${opt}")" From dea6befbe65fb03934670b87033e1b8c1485437e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 15 Jul 2016 16:40:15 +1000 Subject: [PATCH 071/169] Use full arkmanager path --- tools/arkmanager | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index d28afda..7a2fd3c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1982,6 +1982,7 @@ doInstallCronJob(){ cmdopts="${arkCronExtraOpts}" cmdargs="" output=">/dev/null 2>&1" + arkmanagerpath="${0}" command="$1" shift @@ -2013,10 +2014,10 @@ doInstallCronJob(){ esac done - cronjob="${minute} ${hour} * * * arkmanager --cronjob ${command} @${instance} ${cmdopts} --args ${cmdargs} -- ${output}" + cronjob="${minute} ${hour} * * * ${arkmanagerpath} --cronjob ${command} @${instance} ${cmdopts} --args ${cmdargs} -- ${output}" (crontab -l | \ - sed -e "/ [*] [*] [*] arkmanager --cronjob ${command} @${instance} /d"; + sed -e "/ [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} /d"; echo "${cronjob}" ) | \ crontab - } @@ -2025,10 +2026,11 @@ doInstallCronJob(){ # Removes an installed cron job # doRemoveCronJob(){ + arkmanagerpath="${0}" command="$1" crontab -l | \ - sed -e "/ [*] [*] [*] arkmanager --cronjob ${command} @${instance} /d" | \ + sed -e "/ [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} /d" | \ crontab - } From 421c2c4c0b2ef59c71085330685f6205c4ae1de8 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 15 Jul 2016 20:03:31 +1000 Subject: [PATCH 072/169] Fix sed command in install-cronjob --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 7a2fd3c..da12cf7 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2017,7 +2017,7 @@ doInstallCronJob(){ cronjob="${minute} ${hour} * * * ${arkmanagerpath} --cronjob ${command} @${instance} ${cmdopts} --args ${cmdargs} -- ${output}" (crontab -l | \ - sed -e "/ [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} /d"; + sed -e "\\# [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} #d"; echo "${cronjob}" ) | \ crontab - } @@ -2030,7 +2030,7 @@ doRemoveCronJob(){ command="$1" crontab -l | \ - sed -e "/ [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} /d" | \ + sed -e "\\# [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} #d" | \ crontab - } From bab7832fc9a58cb4009de23e3caaa7bd2aabc609 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 15 Jul 2016 20:53:02 +1000 Subject: [PATCH 073/169] Elaborate on install-cronjob --minute and --hour --- README.asciidoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index d295e60..89edc23 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -272,10 +272,16 @@ instances. `--hour=`;; Specifies one or more hours when the command should execute. This is the hour field of the cron job. + If you want to have the command execute every n hours, then + use `--hour='*/n'` + Default: `*` (i.e. all hours) `--minute=`;; Specifies one or more minutes of the hour when the command should execute. This is the minute field of the cron job. + If you want to have the command execute every n minutes, + then use `--minute='*/n'` + Default: `0` (i.e. the first minute of the hour) `--enable-output`;; Enables the output from the command - the cron daemon usually From 915b5ace415686fef6d6f3f1ab2e985570f7005d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 15 Jul 2016 21:26:35 +1000 Subject: [PATCH 074/169] Point user to crontab(5) man page --- README.asciidoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index 89edc23..eb6b78a 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -262,6 +262,9 @@ instances. 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. + Please read your `man 5 crontab` manpage to determine what + minute and hour values are valid, as some implementations + may not accept e.g. the `*/n` minute / hour specification. `--daily`;; The command should be executed daily From 9a76dd8e1671d76b2d2e1be14f0a0b007f856a78 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 16 Jul 2016 13:11:27 +1000 Subject: [PATCH 075/169] Add --warnreason --- tools/arkmanager | 54 ++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index da12cf7..29f602a 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -865,7 +865,7 @@ doStop() { for arg in "$@"; do case "$arg" in --warn) dowarn=1; ;; - --warnreason=*) warnreason="${arg#*=}"; ;; + --warnreason=*) warnreason="${arg#--warnreason=}"; ;; --saveworld) dosave=1; ;; esac done @@ -995,6 +995,12 @@ printWarnMessage(){ fi fi msg="${msgWarnReason//\{time\}/$msgtime}" + if [ -n "$warnreason" ]; then + local v="warnreason_$warnreason" + reason="${!v}" + if [ -z "$reason" ]; then + reason="$warnreason" + fi if [ "$1" == "update" ]; then if [ -n "$appupdate" ]; then if [ -n "$modupdate" ]; then @@ -1242,34 +1248,24 @@ doUpdate() { local nodownload= for arg in "$@"; do - if [ "$arg" == "--force" ]; then - appupdate=1 - elif [ "$arg" == "--safe" ]; then - updatetype=safe - elif [ "$arg" == "--warn" ]; then - updatetype=warn - elif [ "$arg" == "--ifempty" ]; then - updatetype=ifempty - elif [ "$arg" == "--validate" ]; then - validate=validate - appupdate=1 - elif [ "$arg" == "--saveworld" ]; then - saveworld=1 - elif [ "$arg" == "--update-mods" ]; then - modupdate=1 - elif [ "$arg" == "--backup" ]; then - arkBackupPreUpdate=true - elif [[ "$arg" =~ ^--stagingdir= ]]; then - arkStagingDir="${ark#--stagingdir=}" - elif [ "$arg" == "--downloadonly" ]; then - downloadonly=1 - elif [ "$arg" == "--no-download" ]; then - nodownload=1 - else - echo "Unrecognized option $arg" - echo "Try 'arkmanager -h' or 'arkmanager --help' for more information." - exit 1 - fi + case "$arg" in + --force) appupdate=1; ;; + --safe) updatetype=safe; ;; + --warn) updatetype=warn; ;; + --ifempty) updatetype=ifempty; ;; + --warnreason=*) warnreason="${arg#--warnreason=}"; ;; + --validate) validate=validate; appupdate=1; ;; + --saveworld) saveworld=1; ;; + --update-mods) modupdate=1; ;; + --backup) arkBackupPreUpdate=true; ;; + --stagingdir=*) arkStagingDir="${arg#--stagingdir=}"; ;; + --downloadonly) downloadonly=1; ;; + --no-download) nodownload=1; ;; + *) + echo "Unrecognized option $arg" + echo "Try 'arkmanager -h' or 'arkmanager --help' for more information." + exit 1 + esac done echo "$$" >"${arkserverroot}/.ark-update.lock.$$" 2>/dev/null From ca9ea08ebe46b4c5be5a339a19ebbb9736accf69 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 16 Jul 2016 13:17:20 +1000 Subject: [PATCH 076/169] Fix error in last commit --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 29f602a..63d3743 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1001,7 +1001,7 @@ printWarnMessage(){ if [ -z "$reason" ]; then reason="$warnreason" fi - if [ "$1" == "update" ]; then + elif [ "$1" == "update" ]; then if [ -n "$appupdate" ]; then if [ -n "$modupdate" ]; then if [ -n "$msgReasonUpdateAppMod" ]; then From 94f3e9566d6bc19620845c458ad31eb68d02478a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 16 Jul 2016 13:21:25 +1000 Subject: [PATCH 077/169] Stop warning if server is offline --- tools/arkmanager | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 63d3743..bf6bd69 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1174,7 +1174,10 @@ doWarn(){ for (( min = warnminutes; min >= warninterval; min-- )); do numplayers=$(numPlayersConnected) echo "There are ${numplayers} players connected" - if (( (numplayers + 0) == 0 )); then + if [[ "numplayers" == "-1" ]]; then + echo "Server is not running. Shutting down immediately" + return 0 + elif (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" rm -f "${arkserverroot}/.ark-warn.lock" return 0 @@ -1207,7 +1210,10 @@ doWarn(){ if (( warnseconds >= 20 )); then numplayers=$(numPlayersConnected) echo "There are ${numplayers} players connected" - if (( (numplayers + 0) == 0 )); then + if [[ "numplayers" == "-1" ]]; then + echo "Server is not running. Shutting down immediately" + return 0 + elif (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" rm -f "${arkserverroot}/.ark-warn.lock" return 0 From 4b98f92ff8a158075922f462a143f50b1de581e9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 23 Jul 2016 02:18:51 +1000 Subject: [PATCH 078/169] Use the A2S_PLAYER query to get active players --- tools/arkmanager | 57 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index bf6bd69..788ed96 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -599,18 +599,39 @@ function isTheServerOnline(){ # Check if anybody is connected to the server # function numPlayersConnected(){ - perl -MSocket -e ' - my $port = int($ARGV[0]); - socket(my $socket, PF_INET, SOCK_DGRAM, 0); - setsockopt($socket, SOL_SOCKET, SO_RCVTIMEO, pack("i4", 1, 0, 0, 0)); - 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 "-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"; - ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" + if [ -n "$arkUsePlayerList" ]; then + perl -MSocket -e ' + my $port = int($ARGV[0]); + socket(my $socket, PF_INET, SOCK_DGRAM, 0); + setsockopt($socket, SOL_SOCKET, SO_RCVTIMEO, pack("i4", 1, 0, 0, 0)); + my $sockaddr = pack_sockaddr_in($port, inet_aton($ARGV[1])); + send($socket, "\xff\xff\xff\xff\x55\xff\xff\xff\xff", 0, $sockaddr); + my $data = ""; + recv($socket, $data, 1400, 0) or (print "-1" and exit(1)); + if (ord(substr($data, 4, 1)) == 0x41) { + my $chal = substr($data, 5); + send($socket, "\xff\xff\xff\xff\x55" . $chal, 0, $sockaddr); + $data = ""; + recv($socket, $data, 1400, 0) or (print "-1" and exit(1)); + } + ord(substr($data, 4, 1)) != 0x44 and (print "-1" and exit(1)); + my $players = ord(substr($data, 5, 1)); + print "$players\n"; + ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" + else + perl -MSocket -e ' + my $port = int($ARGV[0]); + socket(my $socket, PF_INET, SOCK_DGRAM, 0); + setsockopt($socket, SOL_SOCKET, SO_RCVTIMEO, pack("i4", 1, 0, 0, 0)); + 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 "-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"; + ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" + fi } # @@ -2063,6 +2084,18 @@ printStatus(){ my $maxplayers = ord(substr($rest, 3, 1)); print "Server Name: $servername\n"; print "Players: $players / $maxplayers\n"; + send($socket, "\xff\xff\xff\xff\x55\xff\xff\xff\xff", 0, $sockaddr); + $data = ""; + recv($socket, $data, 1400, 0) or (print "Challenge request failed" and exit(1)); + if (ord(substr($data, 4, 1)) == 0x41) { + my $chal = substr($data, 5); + send($socket, "\xff\xff\xff\xff\x55" . $chal, 0, $sockaddr); + $data = ""; + recv($socket, $data, 1400, 0) or (print "A2S_PLAYERS request failed" and exit(1)); + } + ord(substr($data, 4, 1)) != 0x44 and (print ("A2S_PLAYERS Response: : " . unpack("H*", $data)) and exit(1)); + my $players = ord(substr($data, 5, 1)); + print "Active Players: $players\n"; ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" if isTheServerOnline; then From 2d76c199e6054707023c4f88c5f00c37db828b50 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 23 Jul 2016 02:46:22 +1000 Subject: [PATCH 079/169] --warnreason now implies --warn --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 788ed96..90a4f23 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -886,7 +886,7 @@ doStop() { for arg in "$@"; do case "$arg" in --warn) dowarn=1; ;; - --warnreason=*) warnreason="${arg#--warnreason=}"; ;; + --warnreason=*) warnreason="${arg#--warnreason=}"; dowarn=1; ;; --saveworld) dosave=1; ;; esac done @@ -1280,7 +1280,7 @@ doUpdate() { --safe) updatetype=safe; ;; --warn) updatetype=warn; ;; --ifempty) updatetype=ifempty; ;; - --warnreason=*) warnreason="${arg#--warnreason=}"; ;; + --warnreason=*) warnreason="${arg#--warnreason=}"; updatetype=warn; ;; --validate) validate=validate; appupdate=1; ;; --saveworld) saveworld=1; ;; --update-mods) modupdate=1; ;; From beaa42d80f8ad371e0ac531b25438318780b4974 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 30 Jul 2016 03:32:00 +1000 Subject: [PATCH 080/169] Get version from version.txt --- tools/arkmanager | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 90a4f23..a54a668 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1061,6 +1061,7 @@ printWarnMessage(){ fi reason="${reason//\{time\}/${msgtime}}" reason="${reason//\{modnamesupdated\}/${modnamesupdated}}" + reason="${reason//\{version\}/${arkversion}}" msg="${msg//\{reason\}/${reason}}" else if [ "$1" == "update" ]; then @@ -1337,6 +1338,7 @@ doUpdate() { cp -al "$arkserverroot/linux64/." "$arkStagingDir/linux64" cp -al "$arkserverroot/PackageInfo.bin" "$arkStagingDir/PackageInfo.bin" cp -al "$arkserverroot/steamclient.so" "$arkStagingDir/steamclient.so" + cp -al "$arkserverroot/version.txt" "$arkStagingDir/version.txt" cp -a "$arkserverroot/steamapps/." "$arkStagingDir/steamapps" else rsync -a "$arkserverroot/." "$arkStagingDir/." @@ -1370,6 +1372,7 @@ doUpdate() { fi echo "Not applying update - download-only enabled" elif [ -n "$appupdate" -o -n "$modupdate" ]; then + arkversion="$(<"$arkserverroot/version.txt")" if isTheServerRunning; then if [ "$updatetype" == "safe" ]; then while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name ${serverMap##*/}.ark` ]; do @@ -1418,6 +1421,7 @@ doUpdate() { cp -alu --remove-destination "$arkStagingDir/linux64/." "$arkserverroot/linux64" cp -alu --remove-destination "$arkStagingDir/PackageInfo.bin" "$arkserverroot/PackageInfo.bin" cp -alu --remove-destination "$arkStagingDir/steamclient.so" "$arkserverroot/steamclient.so" + cp -alu --remove-destination "$arkStagingDir/version.txt" "$arkserverroot/version.txt" cp -au --remove-destination "$arkStagingDir/steamapps/." "$arkserverroot/steamapps" else rsync -a "$arkStagingDir/." "$arkserverroot" @@ -2107,7 +2111,8 @@ printStatus(){ fi getCurrentVersion - echo -e "$NORMAL" "Server version: " "$GREEN" $instver "$NORMAL" + echo -e "$NORMAL" "Server build ID: " "$GREEN" $instver "$NORMAL" + echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" } getAllInstanceNames(){ From 89f765eb7b4f8eedeacf227c1840fd757653028f Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 30 Jul 2016 03:35:15 +1000 Subject: [PATCH 081/169] Bypass Primitive+ modid --- tools/arkmanager | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 7d200ea..84e9b8e 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1218,6 +1218,10 @@ doDownloadMod(){ # doDownloadAllMods(){ for modid in $(getModIds); do + # Bypass the 111111111 modid used by Primitive+ + if [ "$modid" = "111111111" ]; then + continue + fi doDownloadMod $modid || return 1 done } From 8a59a8c78c2b1cc052207474e5be132a54fb10b5 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 31 Jul 2016 17:37:08 +1000 Subject: [PATCH 082/169] Exclude Primitive+ from mod download and extraction --- tools/arkmanager | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 84e9b8e..2b9fc93 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1184,6 +1184,11 @@ doDownloadMod(){ cd "$steamcmdroot" retries=10 + # Bypass the 111111111 modid used by Primitive+ + if [ "$modid" = "111111111" ]; then + return 0 + fi + while true; do echo -n "Downloading mod $modid" runSteamCMDspinner +workshop_download_item $mod_appid $modid @@ -1218,10 +1223,6 @@ doDownloadMod(){ # doDownloadAllMods(){ for modid in $(getModIds); do - # Bypass the 111111111 modid used by Primitive+ - if [ "$modid" = "111111111" ]; then - continue - fi doDownloadMod $modid || return 1 done } @@ -1235,6 +1236,11 @@ isModUpdateNeeded(){ local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid" local modbranch="${mod_branch:-Windows}" + # Bypass the 111111111 modid used by Primitive+ + if [ "$modid" = "111111111" ]; then + return 1 + fi + for varname in "${!mod_branch_@}"; do if [ "mod_branch_$modid" == "$varname" ]; then modbranch="${!varname}" @@ -1282,6 +1288,11 @@ doExtractMod(){ local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid" local modbranch="${mod_branch:-Windows}" + # Bypass the 111111111 modid used by Primitive+ + if [ "$modid" = "111111111" ]; then + return 0 + fi + for varname in "${!mod_branch_@}"; do if [ "mod_branch_$modid" == "$varname" ]; then modbranch="${!varname}" From eb1cdbb72b8ab5f43cbc29064b6ddcd17cfadae6 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 1 Aug 2016 10:43:47 +1000 Subject: [PATCH 083/169] Count players with names --- tools/arkmanager | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index aede241..0f77f3a 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -616,7 +616,17 @@ function numPlayersConnected(){ } ord(substr($data, 4, 1)) != 0x44 and (print "-1" and exit(1)); my $players = ord(substr($data, 5, 1)); - print "$players\n"; + my $active = 0; + my $pdata = substr($data, 6); + for my $i (0 .. $players) { + my $idx = ord(substr($pdata, 0, 1)); + my ($name, $rest) = split(/\x00/, substr($pdata, 1), 2); + $pdata = substr($rest, 8); + if ($name != "") { + $active = $active + 1; + } + } + print "$active\n"; ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" else perl -MSocket -e ' @@ -2114,7 +2124,17 @@ printStatus(){ } ord(substr($data, 4, 1)) != 0x44 and (print ("A2S_PLAYERS Response: : " . unpack("H*", $data)) and exit(1)); my $players = ord(substr($data, 5, 1)); - print "Active Players: $players\n"; + my $active = 0; + my $pdata = substr($data, 6); + for my $i (0 .. $players) { + my $idx = ord(substr($pdata, 0, 1)); + my ($name, $rest) = split(/\x00/, substr($pdata, 1), 2); + $pdata = substr($rest, 8); + if ($name != "") { + $active = $active + 1; + } + } + print "Active Players: $active\n"; ' "$(getQueryPort)" "${ark_MultiHome:-127.0.0.1}" if isTheServerOnline; then From ea03c35fafb74e8e6f478986841444adfd203f42 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 2 Aug 2016 02:48:31 +1000 Subject: [PATCH 084/169] Perl string inequality is "ne" --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0f77f3a..01d7814 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -622,7 +622,7 @@ function numPlayersConnected(){ my $idx = ord(substr($pdata, 0, 1)); my ($name, $rest) = split(/\x00/, substr($pdata, 1), 2); $pdata = substr($rest, 8); - if ($name != "") { + if ($name ne "") { $active = $active + 1; } } @@ -2130,7 +2130,7 @@ printStatus(){ my $idx = ord(substr($pdata, 0, 1)); my ($name, $rest) = split(/\x00/, substr($pdata, 1), 2); $pdata = substr($rest, 8); - if ($name != "") { + if ($name ne "") { $active = $active + 1; } } From af44f8df85c1a565d155af66c50a71857b21bec2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 7 Aug 2016 08:50:48 +1000 Subject: [PATCH 085/169] Add installmods command --- tools/arkmanager | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 01d7814..36577f1 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1802,6 +1802,15 @@ doInstallMod(){ fi } +# +# Downloads and installs all requested mods +# +doInstallAllMods(){ + for modid in $(getModids); do + doInstallMod "$modid" + done +} + # # Removes mod from mods directory # @@ -2476,6 +2485,9 @@ main(){ installmod) doInstallMod "${args[@]}" ;; + installmods) + doInstallAllMods + ;; uninstallmod) doUninstallMod "${args[@]}" ;; From 2bc7c3e9f2d6d47dc7fdfeab68e7db4ad88aa501 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 7 Aug 2016 09:01:46 +1000 Subject: [PATCH 086/169] Fix shift typo --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 36577f1..7b709d3 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1806,7 +1806,7 @@ doInstallMod(){ # Downloads and installs all requested mods # doInstallAllMods(){ - for modid in $(getModids); do + for modid in $(getModIds); do doInstallMod "$modid" done } From dfb35396c3f0da5c4ff0c4072a31e168ad7ee0a8 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 7 Aug 2016 09:12:48 +1000 Subject: [PATCH 087/169] Add installmods command to readme --- README.asciidoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index b73fd91..3bc4e16 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -226,6 +226,10 @@ instances. `checkupdate`:: Checks if an ARK server update is available +`installmods`:: + Installs all mods specified in the instance config into the + `ShooterGame/Content/Mods` directory + `installmod `:: Installs the specified mod into the `ShooterGame/Content/Mods` directory From 54d0e81ee8ede04e02802c6b1d835e03b68c1d22 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 7 Aug 2016 15:15:12 +1000 Subject: [PATCH 088/169] Add support for arkmod_* in config --- tools/arkmanager | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 7b709d3..c653be9 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -660,6 +660,22 @@ doRun() { arkserveropts="$serverMap" + while read varname; do + val="${!varname}" + modid="${varname#arkmod_}" + case "$val" in + game*|enabled) + ark_GameModIds="${ark_GameModIds}${ark_GameModIds:+,}${modid}" + ;; + map*) + serverMapModId="${modid}" + ;; + tc|total*) + ark_TotalConversionMod="${modid}" + ;; + esac + done < <(sed -n 's/^\(arkmod_[^= ]*\)=.*/\1/p' <"$configfile") + if [ -n "$serverMapModId" ]; then serverMap="$(perl -e ' my $data; @@ -1488,6 +1504,11 @@ getModIds(){ echo "${serverMapModId}" echo "${ark_TotalConversionMod}" echo "${ark_GameModIds}" | tr ',' '\n' + for v in "${!arkmod_@}"; do + if [ "${!v}" != "disabled" ]; then + echo "${v#arkmod_}" + fi + done find "${arkserverroot}/ShooterGame/Content/Mods" -maxdepth 1 -type d -printf "%P\n" ) | sort | uniq | grep '^[1-9][0-9]*$' } From 0403d2949519e8f32c65dfe5d4e9e75811e84967 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 7 Aug 2016 15:37:52 +1000 Subject: [PATCH 089/169] Add enablemod and disablemod commands --- README.asciidoc | 40 ++++++++++++++++++++++++++++++++++++++++ tools/arkmanager | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index 3bc4e16..d11ce84 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -242,6 +242,22 @@ instances. Runs the `uninstallmod` command followed by the `installmod` command +`enablemod `:: +`enablemod =`:: + Enables the `arkmod_` setting in the instance config. + modtype defaults to `game`. + Mod types: + + `game`;; + A mod in `GameModIds` + + `map`;; + The `MapModId` mod + + `tc`;; + `totalconversion`;; + The `TotalConversionMod` mod + `backup`:: Backs up the saved world and game config files to a compressed tar file in the backups directory specified in the config @@ -495,6 +511,30 @@ the global config. the `-StructureDestructionTag=DestroySwampSnowStructures` option. +`arkmod_=`:: + Specifies a mod that can be enabled or disabled using + `enablemod` and `disablemod`. Note that mod ids specified + using these options are in addition to those specified directly + in the `ark_GameModIds` option, and override those specified in the + `ark_MapModId`, `serverMapMod` and `ark_TotalConversionMod` + options. Options are processed in the order they are specified + in the instance config file, and `arkmod_*` options in the + common config file are not applied. + Mod types: + + `game`;; + A mod to be specified in `GameModIds` + + `map`;; + The mod to be specified in `MapModId` + + `tc`;; + `totalconversion`;; + The mod to be specified in `TotalConversionMod` + + `disabled`;; + A disabled mod + Common ARK options ~~~~~~~~~~~~~~~~~~ diff --git a/tools/arkmanager b/tools/arkmanager index c653be9..6fe9697 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1843,6 +1843,37 @@ doUninstallMod(){ fi } +# +# Enables a mod in the config +# +doEnableMod(){ + local modid="${1%=*}" + local modtype="${1#*=}" + if [ "$modtype" = "$1" ]; then + modtype=game + fi + local modvar="arkmod_${modid}" + if [ -n "${!modvar}" ]; then + sed -i "s|^\(${modvar}\)=[^ ]*|\1=${modtype}|" "$configfile" + else + echo "${modvar}=${modtype}" >>"$configfile" + fi +} + +# +# Disable a mod in the config +# +doDisableMod(){ + local modid="$1" + local modvar="arkmod_$modid" + if [ "$ark_GameModIds" = *"$modid"* ]; then + sed -i "s|^\(ark_GameModIds=\(\|[\"']\)\(\|[^\"' ]*,\)\)${modid},*|\1|" "$configfile" + fi + if [ -n "$modvar" ]; then + sed -i "s|^\(arkmod_${modid}\)=[^ ]*|\1=disabled|" "$configfile" + fi +} + # # Removes mod from steamcmd workshop directory # @@ -2506,6 +2537,12 @@ main(){ installmod) doInstallMod "${args[@]}" ;; + enablemod) + doEnableMod "${args[@]}" + ;; + disablemod) + doDisableMod "${args[@]}" + ;; installmods) doInstallAllMods ;; From 09843fc8697087e3a31035811a4b06c2f2cd4ad9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 17 Aug 2016 17:02:37 +1000 Subject: [PATCH 090/169] Use release tags by default for lastest version --- tools/arkmanager | 125 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 100 insertions(+), 25 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 6fe9697..ddce8bf 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,8 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion='1.6' +arkstVersion='1.6-pre1' +arkstTag='' arkstCommit='' doUpgradeTools() { @@ -15,9 +16,57 @@ doUpgradeTools() { if [ "$UID" == 0 -o "$steamcmd_user" == "--me" ]; then sudo= fi + + local reinstall_args=() + if [ -n "$install_bindir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--bindir" "$install_bindir" ) + fi + if [ -n "$install_libexecdir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--libexecdir" "$install_libexecdir" ) + fi + if [ -n "$install_datadir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--datadir" "$install_datadir" ) + fi + echo "arkmanager v${arkstVersion}: Checking for updates..." - arkstLatestVersion=`curl -s https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version` - arkstLatestCommit=`curl -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${arkstChannel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` + + if [ -n "$arkstUnstable" ] || [ "$arkstChannel" != "master" ]; then + doUpgradeToolsFromBranch + else + doUpgradeToolsFromRelease + fi +} + +doUpgradeToolsFromCommit(){ + local commit="$1" + tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" + if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi + cd "$tmpdir" + echo "Downloading installer" + curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + cd "ark-server-tools-${commit}/tools" + if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi + sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ + -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ + arkmanager + echo "Running install.sh" + bash install.sh "$steamcmd_user" "${reinstall_args[@]}" + result=$? + cd / + rm -rf "$tmpdir" + + if [ "$result" = 0 ] || [ "$result" = 2 ]; then + "ARK Server Tools successfully upgraded" + "$0" --version + else + "ARK Server Tools upgrade failed" + fi + exit $result +} + +doUpgradeToolsFromBranch(){ + arkstLatestVersion=`curl -s "https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version"` + arkstLatestCommit=`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${arkstChannel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` if [ "$arkstLatestVersion" == "Not Found" ]; then echo "Channel ${arkstChannel} does not exist" @@ -28,33 +77,53 @@ doUpgradeTools() { return fi - reinstall_args=() - if [ -n "$install_bindir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--bindir" "$install_bindir" ) - fi - if [ -n "$install_libexecdir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--libexecdir" "$install_libexecdir" ) - fi - if [ -n "$install_datadir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--datadir" "$install_datadir" ) - fi + REPLY= + 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} "${reinstall_args[@]}" - exit 0 - fi + echo elif [[ $arkstLatestVersion == $arkstVersion && "$arkstLatestCommit" != "$arkstCommit" ]]; then read -p "A hotfix is available for v${arkstLatestVersion}. Do you wish to install it?" -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} "${reinstall_args[@]}" - exit 0 - fi + echo else echo "Your ARK server tools are already up to date" fi + + if [[ "$REPLY" =~ ^[Yy]$ ]]; then + doUpgradeToolsFromCommit "$arkstLatestCommit" + fi +} + +doUpgradeToolsFromRelease(){ + local tagname= + local desc= + + echo "Getting latest release..." + # Read the variables from github + while IFS=$'\t' read n v; do + case "${n}" in + tag_name) tagname="${v}"; ;; + body) desc="${v}" + esac + done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + + if [ -n "$tagname" ]; then + if [ "$tagname" != "$arkstTag" ]; then + echo "A new version has been released: ${tagname}" + echo -e "$desc" + read -p "Do you want to upgrade to ${tagname}? [Y/N] " -n 1 -r + echo + if [[ "$REPLY" =~ ^[Yy]$ ]]; then + echo "Getting commit for latest release..." + local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + doUpgradeToolsFromCommit "$commit" + fi + else + echo "Your ARK server tools are already up to date" + fi + else + echo "Unable to get latest release" + fi } doUninstallTools() { @@ -86,7 +155,10 @@ runAsRoot(){ fi } + cd / + arkstChannel="$(getConfigVar arkstChannel "master")" + arkstUnstable="$(getConfigVar arkstUnstable "")" install_bindir="$(getConfigVar install_bindir "${0%/*}")" install_libexecdir="$(getConfigVar install_libexecdir "${install_bindir%/*}/libexec/arkmanager")" install_datadir="$(getConfigVar install_datadir "${install_bindir%/*}/share/arkmanager")" @@ -2465,8 +2537,11 @@ main(){ if [ -n "${arkstCommit}" ]; then echo "Commit: ${arkstCommit:0:7}" fi - blobsize="$(sed "s@^arkstCommit=.*@arkstCommit=''@" "$0" | wc -c)" - echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" + if [ -n "${arkstTag}" ]; then + echo "Release Tag: ${arkstTag}" + fi + blobsize="$(sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0" | wc -c)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From c7dd01d06e63f6e5612c4887e6fe8f5e8d6ba811 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 17 Aug 2016 17:33:55 +1000 Subject: [PATCH 091/169] Switch netinstall.sh to using release tag --- netinstall.sh | 116 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 41 deletions(-) diff --git a/netinstall.sh b/netinstall.sh index 564b3d9..f1a6924 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -19,48 +19,82 @@ elif [[ "$1" =~ ^--output= ]]; then shift fi -# Download and untar installation files -cd /tmp -COMMIT="`curl -L -k -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" +unstable= +if [ "$1" = "--unstable" ]; then + unstable=1 +fi -if [ -z "$COMMIT" ]; then - if [ "$channel" != "master" ]; then - echo "Channel ${channel} not found - trying master" - channel=master - COMMIT="`curl -L -k -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" +function doInstallFromCommit(){ + local commit="$1" + tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" + if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi + cd "$tmpdir" + echo "Downloading installer" + curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + cd "ark-server-tools-${commit}/tools" + if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi + sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ + -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ + arkmanager + echo "Running install.sh" + bash install.sh "$steamcmd_user" "${reinstall_args[@]}" + result=$? + cd / + rm -rf "$tmpdir" + + if [ "$result" = 0 ] || [ "$result" = 2 ]; then + "ARK Server Tools successfully installed" + else + "ARK Server Tools install failed" fi + exit $result +} + +function doInstallFromRelease(){ + local tagname= + local desc= + + echo "Getting latest release..." + # Read the variables from github + while IFS=$'\t' read n v; do + case "${n}" in + tag_name) tagname="${v}"; ;; + body) desc="${v}" + esac + done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + + if [ -n "$tagname" ]; then + echo "Latest release is ${tagname}" + echo "Getting commit for latest release..." + local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + doUpgradeToolsFromCommit "$commit" + else + echo "Unable to get latest release" + fi +} + +function doInstallFromBranch(){ + channel="$1" + commit="`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" + + if [ -z "$commit" ]; then + if [ -n "$unstable" ]; then + echo "Channel ${channel} not found - trying master" + doInstallFromBranch master + else + doInstallFromRelease + fi + fi + + doInstallFromCommit "$commit" +} + +# Download and untar installation files +cd "$TEMP" + +if [ "$channel" = "master" ] && [ -z "$unstable" ]; then + doInstallFromRelease +else + doInstallFromBranch "$channel" fi -if [ -z "$COMMIT" ]; then - echo "Unable to retrieve latest commit" - exit 1 -fi - -mkdir ark-server-tools-${channel} -cd ark-server-tools-${channel} -curl -L -k -s https://github.com/FezVrasta/ark-server-tools/archive/${COMMIT}.tar.gz | tar xz - -# Install ARK Server Tools -cd ark-server-tools-${COMMIT}/tools -sed -i "s|^arkstCommit='.*'$|arkstCommit='${COMMIT}'|" arkmanager -chmod +x install.sh -bash install.sh "$steamcmd_user" "$@" >"$output" 2>&1 - -status=$? - -rm -rf /tmp/ark-server-tools-${channel} - -# Print messages -case "$status" in - "0") - echo "ARK Server Tools were correctly installed in your system inside the home directory of $steamcmd_user!" - ;; - - "1") - echo "Something where wrong :(" - ;; - "2") - echo "WARNING: A previous version of ARK Server Tools was detected in your system, your old configuration was not overwritten. You may need to manually update it." - echo "ARK Server Tools were correctly installed in your system inside the home directory of $steamcmd_user!" - ;; -esac From 653006a66c4a70dd3e14444ad790e62944f7c0d3 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 21 Aug 2016 22:27:18 +1000 Subject: [PATCH 092/169] Prevent server start during update --- tools/arkmanager | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2b9fc93..0cdf58d 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -591,6 +591,14 @@ function numPlayersConnected(){ doRun() { cd "$arkserverroot" + if [ -f "${arkserverroot}/.ark-update.lock" ]; then + local updatepid="$(<"${arkserverroot}/.ark-update.lock")" + if kill -0 "$updatepid" >/dev/null 2>&1; then + echo "An update is currently in progress. Start aborted" + return 1 + fi + fi + arkserveropts="$serverMap" if [ -n "$serverMapModId" ]; then @@ -728,6 +736,15 @@ doRun() { # start function # doStart() { + if [ -f "${arkserverroot}/.ark-update.lock" ]; then + local updatepid="$(<"${arkserverroot}/.ark-update.lock")" + if kill -0 "$updatepid" >/dev/null 2>&1; then + touch "${arkserverroot}/.startAfterUpdate" + echo "An update is currently in progress. Start aborted" + return 1 + fi + fi + if isTheServerRunning; then echo "The server is already running" else @@ -766,6 +783,8 @@ doStartAll(){ # stop the ARK server # doStop() { + rm -f "${arkserverroot}/.startAfterUpdate" + if isTheServerRunning; then if [[ " $* " =~ " --warn " ]]; then doWarn "$1" @@ -1151,7 +1170,9 @@ doUpdate() { fi # we restart the server only if it was started before the update - if [ $serverWasAlive -eq 1 ]; then + if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then + rm -f "${arkserverroot}/.startAfterUpdate" + rm -f "${arkserverroot}/.ark-update.lock" doStart --noautoupdate fi else From 7efbbd3fdf6a35da09ee10a314e67accfa482ea6 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 26 Aug 2016 17:25:56 +1000 Subject: [PATCH 093/169] Add arkPriorityBoost --- tools/arkmanager | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 281333d..8ef7826 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -666,6 +666,12 @@ doRun() { fi fi + if [ " $* " = *" --wait "* ]; then + # This requires bash 4+ + # $$ returns the main process, $BASHPID returns the current process + kill -STOP $BASHPID # wait for caller to renice us + fi + arkserveropts="$serverMap" while read varname; do @@ -893,7 +899,20 @@ doStart() { tput sc echo "The server is starting..." - doRun >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged + local pid=$! + if [ -n "$arkPriorityBoost" ]; then + doRun --wait >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged + local pid="$!" + + # Wait for monitor process to suspend itself + wait + + echo "Boosting priority of ark server" + sudo renice -n "$arkPriorityBoost" "$pid" + kill -CONT "$pid" + else + doRun >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged + fi echo "`timestamp`: start" >> "$logdir/$arkmanagerLog" tput rc; tput ed; echo "The server is now running, and should be up within 10 minutes" From fac21dd9a87b3fe49003568f921999427d12f696 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 26 Aug 2016 17:28:03 +1000 Subject: [PATCH 094/169] Fix doRun writing the wrong PID to the run file --- tools/arkmanager | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 8ef7826..f121fd5 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -656,7 +656,8 @@ doRun() { exit 1 fi - echo "$$" >"${arkserverroot}/${arkmanagerpidfile}" + # $$ returns the main process, $BASHPID returns the current process + echo "$BASHPID" >"${arkserverroot}/${arkmanagerpidfile}" if [ -f "${arkserverroot}/.ark-update.lock" ]; then local updatepid="$(<"${arkserverroot}/.ark-update.lock")" From d6d6e3cc58b8674783e66676a50fcb1c7adc6fd4 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 26 Aug 2016 17:35:30 +1000 Subject: [PATCH 095/169] Add arkPriorityBoost to documentation --- README.asciidoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index d11ce84..94bcf59 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -396,6 +396,11 @@ The following options can be overridden on a per-instance basis: `arkMaxBackupSizeMB`:: Limits the size of the stored backups +`arkPriorityBoost`:: + Attempts to boost the priority of the ARK server. + Negative values give a higher priority, and positive values give a lower priority. + Requires `sudo` and `renice` + `msgWarnUpdateMinutes`:: `msgWarnUpdateSeconds`:: `msgWarnRestartMinutes`:: From 05e8511e2233f59a17aee9fdeb81f7f4ad5837a4 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 29 Aug 2016 20:44:11 +1000 Subject: [PATCH 096/169] Fix interaction between start and update --- tools/arkmanager | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0cdf58d..5400da7 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -736,10 +736,11 @@ doRun() { # start function # doStart() { + touch "${arkserverroot}/.startAfterUpdate" + if [ -f "${arkserverroot}/.ark-update.lock" ]; then local updatepid="$(<"${arkserverroot}/.ark-update.lock")" if kill -0 "$updatepid" >/dev/null 2>&1; then - touch "${arkserverroot}/.startAfterUpdate" echo "An update is currently in progress. Start aborted" return 1 fi @@ -783,7 +784,9 @@ doStartAll(){ # stop the ARK server # doStop() { - rm -f "${arkserverroot}/.startAfterUpdate" + if [ "$1" != "update" ]; then + rm -f "${arkserverroot}/.startAfterUpdate" + fi if isTheServerRunning; then if [[ " $* " =~ " --warn " ]]; then @@ -1116,7 +1119,7 @@ doUpdate() { doSaveWorld fi - doStop + doStop update # If user wants to back-up, we do it here. From c0c56ab6874dcf292729548fcc15ecde2bfdb5c7 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 30 Aug 2016 14:41:02 +1000 Subject: [PATCH 097/169] Fix interaction between update and start --- tools/arkmanager | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arkmanager b/tools/arkmanager index 5400da7..70e34b1 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1172,6 +1172,7 @@ doUpdate() { done fi + rm -f "${arkserverroot}/.ark-update.lock" # we restart the server only if it was started before the update if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then rm -f "${arkserverroot}/.startAfterUpdate" From e0ab6c98ef5e88d0fef50b1196199789546cd633 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 31 Aug 2016 16:01:53 +1000 Subject: [PATCH 098/169] Use full yyyy-mm-dd HH:MM:SS timestamp --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0ed033d..922d3fd 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -172,7 +172,7 @@ declare -A modsrcdirs # timestamp # timestamp() { - date +%T + date +"%Y-%m-%d %H:%M:%S" } # From a46ef5ad23136bf7bf2ef05258ab1c83dc90308b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 31 Aug 2016 16:27:48 +1000 Subject: [PATCH 099/169] Restart server if necessary after update check --- tools/arkmanager | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 922d3fd..cf7f0f0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -881,12 +881,14 @@ doStart() { local updatepid="$(<"${arkserverroot}/.ark-update.lock")" if kill -0 "$updatepid" >/dev/null 2>&1; then echo "An update is currently in progress. Start aborted" + echo "`timestamp`: Start aborted due to running update - pid: $updatepid" >>"$logdir/$arkserverLog" return 1 fi fi if isTheServerRunning; then echo "The server is already running" + echo "`timestamp`: Start aborted due to server already running" else if [ "$arkAutoUpdateOnStart" == "true" ]; then if ! [[ " $* " =~ " --noautoupdate " ]]; then @@ -969,7 +971,7 @@ doStop() { fi tput sc echo "Stopping server..." - echo "`timestamp`: stopping" >> "$logdir/$arkmanagerLog" + echo "`timestamp`: stopping; reason: $stopreason" >> "$logdir/$arkmanagerLog" rm -f "$arkserverroot/$arkautorestartfile" # kill the server with the PID PID=`getServerPID` @@ -1364,6 +1366,12 @@ doUpdate() { esac done + # 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 + echo "$$" >"${arkserverroot}/.ark-update.lock.$$" 2>/dev/null while true; do if ! ln "${arkserverroot}/.ark-update.lock.$$" "${arkserverroot}/.ark-update.lock" 2>/dev/null; then @@ -1380,6 +1388,8 @@ doUpdate() { done rm -f "${arkserverroot}/.ark-update.lock.$$" + echo "`timestamp`: checking for update; PID: $$" + if [ -n "$modupdate" ]; then if [ -z "$nodownload" ]; then if ! doDownloadAllMods; then @@ -1461,12 +1471,6 @@ doUpdate() { fi fi - # 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 - if [ -n "$saveworld" ]; then echo "Saving world" doSaveWorld @@ -1525,20 +1529,21 @@ doUpdate() { fi done fi - - rm -f "${arkserverroot}/.ark-update.lock" - # we restart the server only if it was started before the update - if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then - rm -f "${arkserverroot}/.startAfterUpdate" - rm -f "${arkserverroot}/.ark-update.lock" - doStart --noautoupdate - fi else echo "Your server is already up to date! The most recent version is ${bnumber}." echo "`timestamp`: No update needed." >> "$logdir/update.log" fi; rm -f "${arkserverroot}/.ark-update.lock" + + if ! isTheServerRunning; then + # we restart the server only if it was started before the update + if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then + rm -f "${arkserverroot}/.startAfterUpdate" + rm -f "${arkserverroot}/.ark-update.lock" + doStart --noautoupdate + fi + fi } # @@ -2642,10 +2647,9 @@ main(){ sleep 1 for instance in "${instances[@]}"; do ( + echo "`timestamp`: restart" >> "$logdir/$arkmanagerLog" useConfig "$instance" doStart "${options[@]}" - echo "`timestamp`: start" >> "$logdir/$arkmanagerLog" - echo "`timestamp`: restart" >> "$logdir/$arkmanagerLog" ) done fi From ac56f438f1363c5b372e50affca7b73171a2afc9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 1 Sep 2016 20:08:05 +1000 Subject: [PATCH 100/169] Allow multiple mods to be installed or uninstalled --- README.asciidoc | 13 ++++++++----- tools/arkmanager | 31 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 94bcf59..df5559b 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -230,15 +230,18 @@ instances. Installs all mods specified in the instance config into the `ShooterGame/Content/Mods` directory -`installmod `:: - Installs the specified mod into the `ShooterGame/Content/Mods` +`installmod [,[,...]]`:: + Installs the specified mods into the `ShooterGame/Content/Mods` directory -`uninstallmod `:: - Deletes the specified mod from the `ShooterGame/Content/Mods` +`uninstallmod [,[,...]]`:: + Deletes the specified mods from the `ShooterGame/Content/Mods` directory -`reinstallmod `:: +`removemod [,[,...]]`:: + Deletes the specified mods from the SteamCMD workshop directory + +`reinstallmod [,[,...]]`:: Runs the `uninstallmod` command followed by the `installmod` command diff --git a/tools/arkmanager b/tools/arkmanager index cf7f0f0..6c438d7 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1861,16 +1861,17 @@ doExtractMod(){ # Downloads mod and installs it into mods directory # doInstallMod(){ - local modid=$1 + local modid + for modid in "${1//,/ }"; do + if [ -f "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" ]; then + sed -i "/^\\t\\t\"${modid}\"/,/^\\t\\t}/d" "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" + fi - if [ -f "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" ]; then - sed -i "/^\\t\\t\"${modid}\"/,/^\\t\\t}/d" "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" - fi - - if doDownloadMod $modid; then - doExtractMod $modid - echo "Mod $modid installed" - fi + if doDownloadMod $modid; then + doExtractMod $modid + echo "Mod $modid installed" + fi + done } # @@ -1886,11 +1887,13 @@ doInstallAllMods(){ # Removes mod from mods directory # doUninstallMod(){ - local modid=$1 - local moddir="$arkserverroot/ShooterGame/Content/Mods/$modid" - if [ -d "${moddir}" ]; then - rm -rf "${moddir}" - fi + local modid + for modid in "${1//,/ }"; do + local moddir="$arkserverroot/ShooterGame/Content/Mods/$modid" + if [ -d "${moddir}" ]; then + rm -rf "${moddir}" + fi + done } # From 2e8475cdc1f44c626abb5afc1f273ffdf8495f22 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 1 Sep 2016 20:19:56 +1000 Subject: [PATCH 101/169] Add uninstallmods command --- README.asciidoc | 3 +++ tools/arkmanager | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/README.asciidoc b/README.asciidoc index df5559b..45ca324 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -230,6 +230,9 @@ instances. Installs all mods specified in the instance config into the `ShooterGame/Content/Mods` directory +`uninstallmods`:: + Deletes all mods from the `ShooterGame/Content/Mods` directory + `installmod [,[,...]]`:: Installs the specified mods into the `ShooterGame/Content/Mods` directory diff --git a/tools/arkmanager b/tools/arkmanager index 6c438d7..51ecddf 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1883,6 +1883,17 @@ doInstallAllMods(){ done } +# +# Removes all mods from the mods directory +# +doUninstallAllMods(){ + for modid in $(getModIds); do + if [[ "$modid" != "111111111" && "$modid" != "TheCenter" ]]; then + doUninstallMod "$modid" + fi + done +} + # # Removes mod from mods directory # @@ -1890,9 +1901,13 @@ doUninstallMod(){ local modid for modid in "${1//,/ }"; do local moddir="$arkserverroot/ShooterGame/Content/Mods/$modid" + local modfile="$arkserverroot/ShooterGame/Content/Mods/${modid}.mod" if [ -d "${moddir}" ]; then rm -rf "${moddir}" fi + if [ -f "${modfile}" ]; then + rm -f "$modfile" + fi done } @@ -2599,6 +2614,9 @@ main(){ installmods) doInstallAllMods ;; + uninstallmods) + doUninstallAllMods + ;; uninstallmod) doUninstallMod "${args[@]}" ;; From 80b8d491acdc004f4aee485987a78c0ddea28d6b Mon Sep 17 00:00:00 2001 From: Roeland Reyniers Date: Sat, 3 Sep 2016 13:49:49 -0600 Subject: [PATCH 102/169] Fix error typo --- netinstall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netinstall.sh b/netinstall.sh index e1e679a..a8bee95 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -59,7 +59,7 @@ case "$status" in ;; "1") - echo "Something where wrong :(" + echo "Something went wrong :( Make sure you meet the Prerequisites found in the readme." ;; "2") echo "WARNING: A previous version of ARK Server Tools was detected in your system, your old configuration was not overwritten. You may need to manually update it." From 0c2bb68b2e333f585ea2b40774b8a36908bdbb99 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 7 Sep 2016 05:32:11 +1000 Subject: [PATCH 103/169] Fix double-start when auto-update is enabled --- tools/arkmanager | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 70e34b1..2ddb4d0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -752,7 +752,7 @@ doStart() { if [ "$arkAutoUpdateOnStart" == "true" ]; then if ! [[ " $* " =~ " --noautoupdate " ]]; then echo "Updating server" - doUpdate --update-mods + doUpdate --update-mods --no-autostart fi fi tput sc @@ -991,6 +991,7 @@ doUpdate() { local modupdate= local saveworld= local downloadonly= + local noautostart= for arg in "$@"; do if [ "$arg" == "--force" ]; then @@ -1010,6 +1011,8 @@ doUpdate() { modupdate=1 elif [ "$arg" == "--backup" ]; then arkBackupPreUpdate=true + elif [ "$arg" == "--no-autostart" ]; then + noautostart=1 elif [[ "$arg" =~ ^--stagingdir= ]]; then arkStagingDir="${ark#--stagingdir=}" elif [ "$arg" == "--downloadonly" ]; then @@ -1174,10 +1177,12 @@ doUpdate() { rm -f "${arkserverroot}/.ark-update.lock" # we restart the server only if it was started before the update - if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then - rm -f "${arkserverroot}/.startAfterUpdate" - rm -f "${arkserverroot}/.ark-update.lock" - doStart --noautoupdate + if [ -z "$noautostart" ]; then + if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then + rm -f "${arkserverroot}/.startAfterUpdate" + rm -f "${arkserverroot}/.ark-update.lock" + doStart --noautoupdate + fi fi else echo "Your server is already up to date! The most recent version is ${bnumber}." From 3dc8ef100e06107dfe8b2bb07a239183a1483355 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 9 Sep 2016 04:25:26 +1000 Subject: [PATCH 104/169] Restart the server if it was updated while running --- tools/arkmanager | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2ddb4d0..a8d03c6 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -986,6 +986,7 @@ doWarn(){ # doUpdate() { local appupdate= + local bgupdate= local updatetype=normal local validate= local modupdate= @@ -1082,6 +1083,11 @@ doUpdate() { fi fi + if [[ -f "$arkserverroot/$arkautorestartfile" && "$arkserverroot/$arkautorestartfile" -ot "${arkserverroot}/steamapps/appmanifest_${appid}.acf" ]]; then + echo "Server was updated while it was running" + bgupdate=1 + fi + if [ -n "$downloadonly" ]; then if [ -n "$appupdate" -a -n "$arkStagingDir" -a "$arkStagingDir" != "$arkserverroot" ]; then echo "Server update downloaded" @@ -1090,7 +1096,7 @@ doUpdate() { echo "Mod update downloaded" fi echo "Not applying update - download-only enabled" - elif [ -n "$appupdate" -o -n "$modupdate" ]; then + elif [ -n "$appupdate" -o -n "$modupdate" -o -n "$bgupdate" ]; then if isTheServerRunning; then if [ "$updatetype" == "safe" ]; then while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name ${serverMap##*/}.ark` ]; do From 8c05d7bf1e2558855bd7455169d4e116b660c50f Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 9 Sep 2016 13:17:43 +1000 Subject: [PATCH 105/169] Touch app manifest on update Touch the app manifest on update in order to force other instances to restart when an update is run. --- tools/arkmanager | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index a8d03c6..85b3d8c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1190,6 +1190,10 @@ doUpdate() { doStart --noautoupdate fi fi + + if [ -z "$bgupdate" ]; then + touch "${arkserverroot}/steamapps/appmanifest_${appid}.acf" + fi else echo "Your server is already up to date! The most recent version is ${bnumber}." echo "`timestamp`: No update needed." >> "$logdir/update.log" From 9a08add72a1875bf83bb1fbf05c7fa76aae5ce39 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 13 Sep 2016 20:29:32 +1000 Subject: [PATCH 106/169] Sync more files; accept missing version.txt --- tools/arkmanager | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 1f5f5fc..1175383 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1417,16 +1417,16 @@ doUpdate() { cp -al "$arkserverroot/ShooterGame/." "$arkStagingDir/ShooterGame" cp -al "$arkserverroot/Engine/." "$arkStagingDir/Engine" cp -al "$arkserverroot/linux64/." "$arkStagingDir/linux64" - cp -al "$arkserverroot/PackageInfo.bin" "$arkStagingDir/PackageInfo.bin" - cp -al "$arkserverroot/steamclient.so" "$arkStagingDir/steamclient.so" - cp -al "$arkserverroot/version.txt" "$arkStagingDir/version.txt" cp -a "$arkserverroot/steamapps/." "$arkStagingDir/steamapps" + cp -l "$arkserverroot/"* "$arkStagingDir" else rsync -a "$arkserverroot/." "$arkStagingDir/." fi rm -rf "$arkStagingDir/ShooterGame/Content/Mods/"* rm -rf "$arkStagingDir/ShooterGame/Saved/"* rm -rf "$arkStagingDir/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamapps" + cp -al "$arkserverroot/ShooterGame/Content/Mods/111111111/." "$arkStagingDir/ShooterGame/Content/Mods/111111111" + cp -l "$arkserverroot/ShooterGame/Content/Mods/111111111.mod" "$arkStagingDir/ShooterGame/Content/Mods/111111111.mod" fi if [ -z "$nodownload" ]; then @@ -1458,7 +1458,12 @@ doUpdate() { fi echo "Not applying update - download-only enabled" elif [ -n "$appupdate" -o -n "$modupdate" -o -n "$bgupdate" ]; then - arkversion="$(<"$arkserverroot/version.txt")" + if [ -f "$arkserverroot/version.txt" ]; then + arkversion="$(<"$arkserverroot/version.txt")" + else + arkversion="$(getCurrentVersion; echo "$instver")" + fi + if isTheServerRunning; then if [ "$updatetype" == "safe" ]; then while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name ${serverMap##*/}.ark` ]; do @@ -1499,9 +1504,7 @@ doUpdate() { cp -alu --remove-destination "$arkStagingDir/ShooterGame/." "$arkserverroot/ShooterGame" cp -alu --remove-destination "$arkStagingDir/Engine/." "$arkserverroot/Engine" cp -alu --remove-destination "$arkStagingDir/linux64/." "$arkserverroot/linux64" - cp -alu --remove-destination "$arkStagingDir/PackageInfo.bin" "$arkserverroot/PackageInfo.bin" - cp -alu --remove-destination "$arkStagingDir/steamclient.so" "$arkserverroot/steamclient.so" - cp -alu --remove-destination "$arkStagingDir/version.txt" "$arkserverroot/version.txt" + cp -lu --remove-destination "$arkStagingDir/"* "$arkserverroot" cp -au --remove-destination "$arkStagingDir/steamapps/." "$arkserverroot/steamapps" else rsync -a "$arkStagingDir/." "$arkserverroot" @@ -2286,7 +2289,9 @@ printStatus(){ getCurrentVersion echo -e "$NORMAL" "Server build ID: " "$GREEN" $instver "$NORMAL" - echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" + if [ -f "$arkserverroot/version.txt" ]; then + echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" + fi } getAllInstanceNames(){ From bd5ef349bc30ccbcab0badfe06156cd816e4f95c Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 19:55:07 +1000 Subject: [PATCH 107/169] Suffix autostart and autorestart with instance name --- tools/arkmanager | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 85b3d8c..93d9f46 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -148,7 +148,6 @@ arkserverLog="arkserver.log" # here is logged the output of ShooterGameServer appid="${appid:-376030}" mod_appid="${mod_appid:-346110}" -arkautorestartfile="${arkautorestartfile:-ShooterGame/Saved/.autorestart}" install_bindir="${install_bindir:-${0%/*}}" install_libexecdir="${install_libexecdir:-${install_bindir%/*}/libexec/arkmanager}" @@ -736,7 +735,7 @@ doRun() { # start function # doStart() { - touch "${arkserverroot}/.startAfterUpdate" + touch "${arkserverroot}/.startAfterUpdate-${instance}" if [ -f "${arkserverroot}/.ark-update.lock" ]; then local updatepid="$(<"${arkserverroot}/.ark-update.lock")" @@ -785,7 +784,7 @@ doStartAll(){ # doStop() { if [ "$1" != "update" ]; then - rm -f "${arkserverroot}/.startAfterUpdate" + rm -f "${arkserverroot}/.startAfterUpdate-${instance}" fi if isTheServerRunning; then @@ -1184,8 +1183,8 @@ doUpdate() { rm -f "${arkserverroot}/.ark-update.lock" # we restart the server only if it was started before the update if [ -z "$noautostart" ]; then - if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate" ]; then - rm -f "${arkserverroot}/.startAfterUpdate" + if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate-${instance}" ]; then + rm -f "${arkserverroot}/.startAfterUpdate-${instance}" rm -f "${arkserverroot}/.ark-update.lock" doStart --noautoupdate fi @@ -1725,6 +1724,7 @@ useConfig() { echo "Error: arkserverroot not set" exit 1 fi + arkautorestartfile="${arkautorestartfile:-ShooterGame/Saved/.autorestart-${1}}" } showUsage() { From 5770903960f9c45265f8190ae691d24b06fc20e9 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 20:13:44 +1000 Subject: [PATCH 108/169] Don't use the old `ps -ef` method with clusterid --- tools/arkmanager | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2395b88..f0e1e29 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -513,7 +513,9 @@ function getServerPID(){ return fi fi - ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}' + if [ -z "$arkopt_clusterid" ]; then + ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}' + fi } # From 437d628a008b4647d5439a4a6282644f944df46e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 20:18:46 +1000 Subject: [PATCH 109/169] Add old PID file; remove PID files on stop --- tools/arkmanager | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index f0e1e29..f0cc933 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -513,6 +513,14 @@ function getServerPID(){ return fi fi + if [ -f "${arkserverroot}/${arkserveroldpidfile}" ]; then + serverpid="$(<"${arkserverroot}/${arkserveroldpidfile}")" + if kill -0 "$serverpid" >/dev/null 2>&1; then + echo $serverpid + return + fi + fi + if [ -z "$arkopt_clusterid" ]; then ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}' fi @@ -996,6 +1004,10 @@ doStop() { fi fi + rm -f "${arkserverroot}/${arkserverpidfile}" + rm -f "${arkserverroot}/${arkserveroldpidfile}" + rm -f "${arkserverroot}/${arkmanagerpidfile}" + tput rc; tput ed; echo "The server has been stopped" echo "`timestamp`: stopped" >> "$logdir/$arkmanagerLog" @@ -2375,6 +2387,7 @@ useConfig() { fi arkautorestartfile="${arkautorestartfile:-ShooterGame/Saved/.autorestart-${1}}" arkserverpidfile="${arkserverpidfile:-ShooterGame/Saved/.arkserver-${1}.pid}" + arkserveroldpidfile="ShooterGame/Saved/.arkserver.pid" arkmanagerpidfile="${arkmanagerpidfile:-ShooterGame/Saved/.arkmanager-${1}.pid}" } From fd23dac69647cee5bf2b487b1b04d04123ece056 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 13 Sep 2016 20:29:32 +1000 Subject: [PATCH 110/169] Sync more files; accept missing version.txt --- tools/arkmanager | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index f0cc933..c89b000 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1428,16 +1428,16 @@ doUpdate() { cp -al "$arkserverroot/ShooterGame/." "$arkStagingDir/ShooterGame" cp -al "$arkserverroot/Engine/." "$arkStagingDir/Engine" cp -al "$arkserverroot/linux64/." "$arkStagingDir/linux64" - cp -al "$arkserverroot/PackageInfo.bin" "$arkStagingDir/PackageInfo.bin" - cp -al "$arkserverroot/steamclient.so" "$arkStagingDir/steamclient.so" - cp -al "$arkserverroot/version.txt" "$arkStagingDir/version.txt" cp -a "$arkserverroot/steamapps/." "$arkStagingDir/steamapps" + cp -l "$arkserverroot/"* "$arkStagingDir" else rsync -a "$arkserverroot/." "$arkStagingDir/." fi rm -rf "$arkStagingDir/ShooterGame/Content/Mods/"* rm -rf "$arkStagingDir/ShooterGame/Saved/"* rm -rf "$arkStagingDir/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamapps" + cp -al "$arkserverroot/ShooterGame/Content/Mods/111111111/." "$arkStagingDir/ShooterGame/Content/Mods/111111111" + cp -l "$arkserverroot/ShooterGame/Content/Mods/111111111.mod" "$arkStagingDir/ShooterGame/Content/Mods/111111111.mod" fi if [ -z "$nodownload" ]; then @@ -1469,7 +1469,12 @@ doUpdate() { fi echo "Not applying update - download-only enabled" elif [ -n "$appupdate" -o -n "$modupdate" -o -n "$bgupdate" ]; then - arkversion="$(<"$arkserverroot/version.txt")" + if [ -f "$arkserverroot/version.txt" ]; then + arkversion="$(<"$arkserverroot/version.txt")" + else + arkversion="$(getCurrentVersion; echo "$instver")" + fi + if isTheServerRunning; then if [ "$updatetype" == "safe" ]; then while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name ${serverMap##*/}.ark` ]; do @@ -1510,9 +1515,7 @@ doUpdate() { cp -alu --remove-destination "$arkStagingDir/ShooterGame/." "$arkserverroot/ShooterGame" cp -alu --remove-destination "$arkStagingDir/Engine/." "$arkserverroot/Engine" cp -alu --remove-destination "$arkStagingDir/linux64/." "$arkserverroot/linux64" - cp -alu --remove-destination "$arkStagingDir/PackageInfo.bin" "$arkserverroot/PackageInfo.bin" - cp -alu --remove-destination "$arkStagingDir/steamclient.so" "$arkserverroot/steamclient.so" - cp -alu --remove-destination "$arkStagingDir/version.txt" "$arkserverroot/version.txt" + cp -lu --remove-destination "$arkStagingDir/"* "$arkserverroot" cp -au --remove-destination "$arkStagingDir/steamapps/." "$arkserverroot/steamapps" else rsync -a "$arkStagingDir/." "$arkserverroot" @@ -2299,7 +2302,9 @@ printStatus(){ getCurrentVersion echo -e "$NORMAL" "Server build ID: " "$GREEN" $instver "$NORMAL" - echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" + if [ -f "$arkserverroot/version.txt" ]; then + echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" + fi } getAllInstanceNames(){ From 50039710aee739615f61cc331cf43e1e3911a766 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 17 Aug 2016 17:02:37 +1000 Subject: [PATCH 111/169] Use release tags by default for lastest version --- tools/arkmanager | 125 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 100 insertions(+), 25 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index c89b000..3d51f84 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,8 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion='1.6' +arkstVersion='1.6-pre1' +arkstTag='' arkstCommit='' doUpgradeTools() { @@ -15,9 +16,57 @@ doUpgradeTools() { if [ "$UID" == 0 -o "$steamcmd_user" == "--me" ]; then sudo= fi + + local reinstall_args=() + if [ -n "$install_bindir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--bindir" "$install_bindir" ) + fi + if [ -n "$install_libexecdir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--libexecdir" "$install_libexecdir" ) + fi + if [ -n "$install_datadir" ]; then + reinstall_args=( "${reinstall_args[@]}" "--datadir" "$install_datadir" ) + fi + echo "arkmanager v${arkstVersion}: Checking for updates..." - arkstLatestVersion=`curl -s https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version` - arkstLatestCommit=`curl -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${arkstChannel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` + + if [ -n "$arkstUnstable" ] || [ "$arkstChannel" != "master" ]; then + doUpgradeToolsFromBranch + else + doUpgradeToolsFromRelease + fi +} + +doUpgradeToolsFromCommit(){ + local commit="$1" + tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" + if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi + cd "$tmpdir" + echo "Downloading installer" + curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + cd "ark-server-tools-${commit}/tools" + if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi + sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ + -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ + arkmanager + echo "Running install.sh" + bash install.sh "$steamcmd_user" "${reinstall_args[@]}" + result=$? + cd / + rm -rf "$tmpdir" + + if [ "$result" = 0 ] || [ "$result" = 2 ]; then + "ARK Server Tools successfully upgraded" + "$0" --version + else + "ARK Server Tools upgrade failed" + fi + exit $result +} + +doUpgradeToolsFromBranch(){ + arkstLatestVersion=`curl -s "https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version"` + arkstLatestCommit=`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${arkstChannel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` if [ "$arkstLatestVersion" == "Not Found" ]; then echo "Channel ${arkstChannel} does not exist" @@ -28,33 +77,53 @@ doUpgradeTools() { return fi - reinstall_args=() - if [ -n "$install_bindir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--bindir" "$install_bindir" ) - fi - if [ -n "$install_libexecdir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--libexecdir" "$install_libexecdir" ) - fi - if [ -n "$install_datadir" ]; then - reinstall_args=( "${reinstall_args[@]}" "--datadir" "$install_datadir" ) - fi + REPLY= + 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} "${reinstall_args[@]}" - exit 0 - fi + echo elif [[ $arkstLatestVersion == $arkstVersion && "$arkstLatestCommit" != "$arkstCommit" ]]; then read -p "A hotfix is available for v${arkstLatestVersion}. Do you wish to install it?" -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} "${reinstall_args[@]}" - exit 0 - fi + echo else echo "Your ARK server tools are already up to date" fi + + if [[ "$REPLY" =~ ^[Yy]$ ]]; then + doUpgradeToolsFromCommit "$arkstLatestCommit" + fi +} + +doUpgradeToolsFromRelease(){ + local tagname= + local desc= + + echo "Getting latest release..." + # Read the variables from github + while IFS=$'\t' read n v; do + case "${n}" in + tag_name) tagname="${v}"; ;; + body) desc="${v}" + esac + done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + + if [ -n "$tagname" ]; then + if [ "$tagname" != "$arkstTag" ]; then + echo "A new version has been released: ${tagname}" + echo -e "$desc" + read -p "Do you want to upgrade to ${tagname}? [Y/N] " -n 1 -r + echo + if [[ "$REPLY" =~ ^[Yy]$ ]]; then + echo "Getting commit for latest release..." + local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + doUpgradeToolsFromCommit "$commit" + fi + else + echo "Your ARK server tools are already up to date" + fi + else + echo "Unable to get latest release" + fi } doUninstallTools() { @@ -86,7 +155,10 @@ runAsRoot(){ fi } + cd / + arkstChannel="$(getConfigVar arkstChannel "master")" + arkstUnstable="$(getConfigVar arkstUnstable "")" install_bindir="$(getConfigVar install_bindir "${0%/*}")" install_libexecdir="$(getConfigVar install_libexecdir "${install_bindir%/*}/libexec/arkmanager")" install_datadir="$(getConfigVar install_datadir "${install_bindir%/*}/share/arkmanager")" @@ -2565,8 +2637,11 @@ main(){ if [ -n "${arkstCommit}" ]; then echo "Commit: ${arkstCommit:0:7}" fi - blobsize="$(sed "s@^arkstCommit=.*@arkstCommit=''@" "$0" | wc -c)" - echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkstCommit=.*@arkstCommit=''@" "$0") | sha1sum | cut -d' ' -f1)" + if [ -n "${arkstTag}" ]; then + echo "Release Tag: ${arkstTag}" + fi + blobsize="$(sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0" | wc -c)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From e0fddd6a6c5d5b302670cb04441f2e0c7fc63ea1 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 17 Aug 2016 17:33:55 +1000 Subject: [PATCH 112/169] Switch netinstall.sh to using release tag --- netinstall.sh | 117 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/netinstall.sh b/netinstall.sh index a8c9336..006b2bb 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -19,48 +19,83 @@ elif [[ "$1" =~ ^--output= ]]; then shift fi -# Download and untar installation files -cd /tmp -COMMIT="`curl -L -k -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" +unstable= +if [ "$1" = "--unstable" ]; then + unstable=1 +fi -if [ -z "$COMMIT" ]; then - if [ "$channel" != "master" ]; then - echo "Channel ${channel} not found - trying master" - channel=master - COMMIT="`curl -L -k -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel} | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" +function doInstallFromCommit(){ + local commit="$1" + tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" + if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi + cd "$tmpdir" + echo "Downloading installer" + curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + cd "ark-server-tools-${commit}/tools" + if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi + sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ + -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ + arkmanager + echo "Running install.sh" + bash install.sh "$steamcmd_user" "${reinstall_args[@]}" + result=$? + cd / + rm -rf "$tmpdir" + + if [ "$result" = 0 ] || [ "$result" = 2 ]; then + "ARK Server Tools successfully installed" + else + "ARK Server Tools install failed" fi + return $result +} + +function doInstallFromRelease(){ + local tagname= + local desc= + + echo "Getting latest release..." + # Read the variables from github + while IFS=$'\t' read n v; do + case "${n}" in + tag_name) tagname="${v}"; ;; + body) desc="${v}" + esac + done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + + if [ -n "$tagname" ]; then + echo "Latest release is ${tagname}" + echo "Getting commit for latest release..." + local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + doUpgradeToolsFromCommit "$commit" + else + echo "Unable to get latest release" + return 1 + fi +} + +function doInstallFromBranch(){ + channel="$1" + commit="`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" + + if [ -z "$commit" ]; then + if [ -n "$unstable" ]; then + echo "Channel ${channel} not found - trying master" + doInstallFromBranch master + else + doInstallFromRelease + fi + else + doInstallFromCommit "$commit" + fi +} + +# Download and untar installation files +cd "$TEMP" + +if [ "$channel" = "master" ] && [ -z "$unstable" ]; then + doInstallFromRelease +else + doInstallFromBranch "$channel" fi -if [ -z "$COMMIT" ]; then - echo "Unable to retrieve latest commit" - exit 1 -fi - -mkdir ark-server-tools-${channel} -cd ark-server-tools-${channel} -curl -L -k -s https://github.com/FezVrasta/ark-server-tools/archive/${COMMIT}.tar.gz | tar xz - -# Install ARK Server Tools -cd ark-server-tools-${COMMIT}/tools -sed -i "s|^arkstCommit='.*'$|arkstCommit='${COMMIT}'|" arkmanager -chmod +x install.sh -bash install.sh "$steamcmd_user" "$@" >"$output" 2>&1 - -status=$? - -rm -rf /tmp/ark-server-tools-${channel} - -# Print messages -case "$status" in - "0") - echo "ARK Server Tools were correctly installed in your system inside the home directory of $steamcmd_user!" - ;; - - "1") - echo "Something went wrong :( Make sure you meet the Prerequisites found in the readme." - ;; - "2") - echo "WARNING: A previous version of ARK Server Tools was detected in your system, your old configuration was not overwritten. You may need to manually update it." - echo "ARK Server Tools were correctly installed in your system inside the home directory of $steamcmd_user!" - ;; -esac From 6d0af94ee535a56d916fcd6ddb45b90fc349f813 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 21:11:46 +1000 Subject: [PATCH 113/169] Add .arktributetribe files to backup --- tools/arkmanager | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 93d9f46..6af84de 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1557,6 +1557,27 @@ doBackup(){ fi done + # ARK server uses Lock-Truncate-Write-Unlock + echo -e "${NORMAL} Copying ARK tribute tribe files " + for f in "${arkserverroot}/ShooterGame/Saved/${savedir}/"*.arktributetribe; do + echo -ne "${NORMAL} ${f##*/} " + cp -p "${f}" "${backupdir}/${f##*/}" + if [ ! -s "${backupdir}/${f##*/}" ]; then + sleep 2 + cp -p "${f}" "${backupdir}/${f##*/}" + fi + # If both attempts fail, server may have + # crashed between truncate and write + if [ ! -s "${backupdir}/${f##*/}" ]; then + cp -p "${f%.arktribe}.tmptributetribe" "${backupdir}/${f##*/}" + fi + if [ -s "${backupdir}/${f##*/}" ]; then + echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" + else + echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + fi + done + # 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" From 85e717a85f269763cbab5574e22f2bdab95b2271 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 22:55:47 +1000 Subject: [PATCH 114/169] v1.6-pre3 --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 7e149e4..db53abd 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,7 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion='1.6-pre1' +arkstVersion='1.6-pre3' arkstTag='' arkstCommit='' From 02173e86dfe4097525c487f8e312aae2f7bb358d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 17 Sep 2016 23:03:37 +1000 Subject: [PATCH 115/169] Fix blob SHA Commit/Tag fixup --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index db53abd..dea38d6 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2662,7 +2662,7 @@ main(){ echo "Release Tag: ${arkstTag}" fi blobsize="$(sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0" | wc -c)" - echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^\\(arkst\\(Commit\\|Tag\\)\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From b7bb6e5b48737046c326a2de93ba4bbe0bb72141 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 01:20:47 +1000 Subject: [PATCH 116/169] Move repo name to top of files --- netinstall.sh | 10 ++++++---- tools/arkmanager | 13 +++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/netinstall.sh b/netinstall.sh index 006b2bb..1ae38db 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -4,6 +4,8 @@ # Net Installer, used with curl # +arkstGithubRepo="FezVrasta/ark-server-tools" + steamcmd_user="$1" channel=${2:-master} # if defined by 2nd argument install the defined version, otherwise install master shift @@ -30,7 +32,7 @@ function doInstallFromCommit(){ if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi cd "$tmpdir" echo "Downloading installer" - curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + curl -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz cd "ark-server-tools-${commit}/tools" if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ @@ -61,12 +63,12 @@ function doInstallFromRelease(){ tag_name) tagname="${v}"; ;; body) desc="${v}" esac - done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + done < <(curl -s "https://api.github.com/repos/${arkstGithubRepo}/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') if [ -n "$tagname" ]; then echo "Latest release is ${tagname}" echo "Getting commit for latest release..." - local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + local commit="$(curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" doUpgradeToolsFromCommit "$commit" else echo "Unable to get latest release" @@ -76,7 +78,7 @@ function doInstallFromRelease(){ function doInstallFromBranch(){ channel="$1" - commit="`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${channel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" + commit="`curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/heads/${channel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'`" if [ -z "$commit" ]; then if [ -n "$unstable" ]; then diff --git a/tools/arkmanager b/tools/arkmanager index dea38d6..18774ac 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -10,6 +10,7 @@ arkstVersion='1.6-pre3' arkstTag='' arkstCommit='' +arkstGithubRepo="FezVrasta/ark-server-tools" doUpgradeTools() { local sudo=sudo @@ -43,7 +44,7 @@ doUpgradeToolsFromCommit(){ if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi cd "$tmpdir" echo "Downloading installer" - curl -L "https://github.com/FezVrasta/ark-server-tools/archive/${commit}.tar.gz" | tar -xz + curl -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz cd "ark-server-tools-${commit}/tools" if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ @@ -65,14 +66,14 @@ doUpgradeToolsFromCommit(){ } doUpgradeToolsFromBranch(){ - arkstLatestVersion=`curl -s "https://raw.githubusercontent.com/FezVrasta/ark-server-tools/${arkstChannel}/.version"` - arkstLatestCommit=`curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads/${arkstChannel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` + arkstLatestVersion=`curl -s "https://raw.githubusercontent.com/${arkstGithubRepo}/${arkstChannel}/.version"` + arkstLatestCommit=`curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/heads/${arkstChannel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` if [ "$arkstLatestVersion" == "Not Found" ]; then echo "Channel ${arkstChannel} does not exist" echo echo "Available channels:" - curl -s https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/heads | sed -n 's|^ *"ref": "refs/heads/\(.*\)",|\1|p' + curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/heads" | sed -n 's|^ *"ref": "refs/heads/\(.*\)",|\1|p' echo return fi @@ -105,7 +106,7 @@ doUpgradeToolsFromRelease(){ tag_name) tagname="${v}"; ;; body) desc="${v}" esac - done < <(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') + done < <(curl -s "https://api.github.com/repos/${arkstGithubRepo}/releases/latest" | sed -n 's/^ "\([^"]*\)": "*\([^"]*\)"*,*/\1\t\2/p') if [ -n "$tagname" ]; then if [ "$tagname" != "$arkstTag" ]; then @@ -115,7 +116,7 @@ doUpgradeToolsFromRelease(){ echo if [[ "$REPLY" =~ ^[Yy]$ ]]; then echo "Getting commit for latest release..." - local commit="$(curl -s "https://api.github.com/repos/FezVrasta/ark-server-tools/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" + local commit="$(curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" doUpgradeToolsFromCommit "$commit" fi else From 18f19b40045c2489a202c0bd3d3101ac27b61489 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 01:43:02 +1000 Subject: [PATCH 117/169] Fix netinstall --- netinstall.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/netinstall.sh b/netinstall.sh index 1ae38db..c69a2de 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -28,11 +28,11 @@ fi function doInstallFromCommit(){ local commit="$1" - tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" + tmpdir="$(mktemp -t -d "ark-server-tools-XXXXXXXX")" if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi cd "$tmpdir" echo "Downloading installer" - curl -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz + curl -s -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz cd "ark-server-tools-${commit}/tools" if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ @@ -45,9 +45,9 @@ function doInstallFromCommit(){ rm -rf "$tmpdir" if [ "$result" = 0 ] || [ "$result" = 2 ]; then - "ARK Server Tools successfully installed" + echo "ARK Server Tools successfully installed" else - "ARK Server Tools install failed" + echo "ARK Server Tools install failed" fi return $result } @@ -69,7 +69,7 @@ function doInstallFromRelease(){ echo "Latest release is ${tagname}" echo "Getting commit for latest release..." local commit="$(curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/tags/${tagname}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p')" - doUpgradeToolsFromCommit "$commit" + doInstallFromCommit "$commit" else echo "Unable to get latest release" return 1 From 63590c4fb5fc83b93a6698e8892fa216710a87a4 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 02:08:45 +1000 Subject: [PATCH 118/169] Fix upgrade-tools --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 18774ac..e3dbd3e 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -57,10 +57,10 @@ doUpgradeToolsFromCommit(){ rm -rf "$tmpdir" if [ "$result" = 0 ] || [ "$result" = 2 ]; then - "ARK Server Tools successfully upgraded" + echo "ARK Server Tools successfully upgraded" "$0" --version else - "ARK Server Tools upgrade failed" + echo "ARK Server Tools upgrade failed" fi exit $result } From 984eb0f9e954f5f9a212fba558c1aa9842e331b7 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 02:38:53 +1000 Subject: [PATCH 119/169] Make update download slightly more silent --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index e3dbd3e..6ad1fd8 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -44,7 +44,7 @@ doUpgradeToolsFromCommit(){ if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi cd "$tmpdir" echo "Downloading installer" - curl -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz + curl -s -L "https://github.com/${arkstGithubRepo}/archive/${commit}.tar.gz" | tar -xz cd "ark-server-tools-${commit}/tools" if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ From 69aced9a79e1ec0237a52546a86e6b4e808c9852 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 02:56:06 +1000 Subject: [PATCH 120/169] Fix Blob SHA calculation --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 6ad1fd8..ebe2fcc 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2662,7 +2662,7 @@ main(){ if [ -n "${arkstTag}" ]; then echo "Release Tag: ${arkstTag}" fi - blobsize="$(sed "s@^arkst\\(Commit\\|Tag\\)=.*@\\1=''@" "$0" | wc -c)" + blobsize="$(sed "s@^\\(arkst\\(Commit\\|Tag\\)\\)=.*@\\1=''@" "$0" | wc -c)" echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^\\(arkst\\(Commit\\|Tag\\)\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; From 26407a5530e0622aff621f34d2229817636303a0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 05:05:20 +1000 Subject: [PATCH 121/169] Fix display of release notes --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index ebe2fcc..06ebbbd 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -101,7 +101,7 @@ doUpgradeToolsFromRelease(){ echo "Getting latest release..." # Read the variables from github - while IFS=$'\t' read n v; do + while IFS=$'\t' read -r n v; do case "${n}" in tag_name) tagname="${v}"; ;; body) desc="${v}" From 44f5cccd388cb08e69d8246c077181b4c848de95 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 18 Sep 2016 16:32:00 +1000 Subject: [PATCH 122/169] Add support for restarting using service --- tools/arkmanager | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 06ebbbd..1bccfaf 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1430,6 +1430,9 @@ doUpdate() { local downloadonly= local nodownload= local noautostart= + local use_systemd= + local use_service= + local use_upstart= for arg in "$@"; do case "$arg" in @@ -1446,6 +1449,9 @@ doUpdate() { --stagingdir=*) arkStagingDir="${arg#--stagingdir=}"; ;; --downloadonly) downloadonly=1; ;; --no-download) nodownload=1; ;; + --systemd) use_systemd=1; ;; + --service) use_service=1; ;; + --upstart) use_upstart=1; ;; *) echo "Unrecognized option $arg" echo "Try 'arkmanager -h' or 'arkmanager --help' for more information." @@ -1639,7 +1645,19 @@ doUpdate() { if [ -z "$noautostart" ]; then if [ $serverWasAlive -eq 1 ] || [ -f "${arkserverroot}/.startAfterUpdate-${instance}" ]; then rm -f "${arkserverroot}/.startAfterUpdate-${instance}" - doStart --noautoupdate + if [ -n "$use_systemd" ]; then + sudo systemctl start "arkmanager@$instance" + elif [ -n "$use_service" ]; then + if [ -f "/etc/init.d/arkmanager" ]; then + sudo "/etc/init.d/arkmanager" start "$instance" + elif [ -f "/etc/rc.d/init.d/arkmanager" ]; then + sudo "/etc/rc.d/init.d/arkmanager" start "$instance" + fi + elif [ -n "$use_upstart" ]; then + sudo start arkmanager "service=$instance" + else + doStart --noautoupdate + fi fi fi fi From dc6497d18123eb2361c0d29f1d9a5a2ca467e7d6 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 19 Sep 2016 04:36:44 +1000 Subject: [PATCH 123/169] Fix error in isUpdateCancelRequested --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 06ebbbd..ce1c464 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1272,7 +1272,7 @@ printWarnMessage(){ isUpdateCancelRequested(){ if [ -n "$chatCommandRestartCancel" ]; then local canceltime="$( - find ~/ARK/server1/ShooterGame/Saved/Logs -name 'ServerGame.*.log' -mmin -5 -print0 | + find "${arkserverrroot}/ShooterGame/Saved/Logs" -name 'ServerGame.*.log' -mmin -5 -print0 | xargs -0 grep -F -e "${chatCommandRestartCancel}" | sed 's@^[[]\(....\)\.\(..\)\.\(..\)-\(..\)\.\(..\)\.\(..\):.*@\1-\2-\3 \4:\5:\6 UTC@' | head -n1)" From 33851a849bdaf80f5a52fb4ccc679260aa58f3e1 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 19 Sep 2016 04:43:03 +1000 Subject: [PATCH 124/169] v1.6 --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index ce1c464..55368b0 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -7,7 +7,7 @@ # Contributors: Sispheor, Atriusftw, klightspeed, lexat, puseidr # Script version -arkstVersion='1.6-pre3' +arkstVersion='1.6' arkstTag='' arkstCommit='' arkstGithubRepo="FezVrasta/ark-server-tools" From a0f464d72c4691e786162cdc1820f45c7a4a86d0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 22 Sep 2016 19:00:09 +1000 Subject: [PATCH 125/169] Fix a couple of issues with stopping --- tools/arkmanager | 59 ++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 55368b0..426bbe2 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -594,7 +594,7 @@ function getServerPID(){ fi fi - if [ -z "$arkopt_clusterid" ]; then + if [[ -z "$arkopt_clusterid" || -f "${arkserverroot}/${arkoldautorestartfile}" ]]; then ps -ef | grep "$arkserverroot/$arkserverexec" | grep -v grep | awk '{print $2}' fi } @@ -739,8 +739,8 @@ doRun() { # $$ returns the main process, $BASHPID returns the current process echo "$BASHPID" >"${arkserverroot}/${arkmanagerpidfile}" - if [ -f "${arkserverroot}/.ark-update.lock" ]; then - local updatepid="$(<"${arkserverroot}/.ark-update.lock")" + if [ -f "${arkserverroot}/${arkupdatelockfile}" ]; then + local updatepid="$(<"${arkserverroot}/${arkupdatelockfile}")" if kill -0 "$updatepid" >/dev/null 2>&1; then echo "An update is currently in progress. Start aborted" return 1 @@ -957,8 +957,8 @@ doRun() { doStart() { touch "${arkserverroot}/.startAfterUpdate-${instance}" - if [ -f "${arkserverroot}/.ark-update.lock" ]; then - local updatepid="$(<"${arkserverroot}/.ark-update.lock")" + if [ -f "${arkserverroot}/${arkupdatelockfile}" ]; then + local updatepid="$(<"${arkserverroot}/${arkupdatelockfile}")" if kill -0 "$updatepid" >/dev/null 2>&1; then echo "An update is currently in progress. Start aborted" echo "`timestamp`: Start aborted due to running update - pid: $updatepid" >>"$logdir/$arkserverLog" @@ -1053,6 +1053,7 @@ doStop() { echo "Stopping server..." echo "`timestamp`: stopping; reason: $stopreason" >> "$logdir/$arkmanagerLog" rm -f "$arkserverroot/$arkautorestartfile" + rm -f "$arkserverroot/$arkoldautorestartfile" # kill the server with the PID PID=`getServerPID` kill -INT $PID @@ -1139,11 +1140,11 @@ doInstall() { # Cancels a pending shutdown # doCancelShutdown(){ - if [ -f "${arkserverroot}/.ark-warn.lock" ]; then - local lockpid="$(<"${arkserverroot}/.ark-warn.lock")" + if [ -f "${arkserverroot}/${arkwarnlockfile}" ]; then + local lockpid="$(<"${arkserverroot}/${arkwarnlockfile}")" if [ -n "$lockpid" ]; then kill "$lockpid" - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" fi fi } @@ -1295,21 +1296,21 @@ doWarn(){ cd "$arkserverroot" ( - echo "$$" >"${arkserverroot}/.ark-warn.lock.$$" 2>/dev/null + echo "$$" >"${arkserverroot}/${arkwarnlockfile}.${BASHPID}" 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 ! ln "${arkserverroot}/${arkwarnlockfile}.${BASHPID}" "${arkserverroot}/${arkwarnlockfile}" 2>/dev/null; then + local lockpid="$(<"${arkserverroot}/${arkwarnlockfile}")" 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 + rm -f "${arkserverroot}/${arkwarnlockfile}.${BASHPID}" 2>/dev/null exit 1 fi - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" else break fi done - rm -f "${arkserverroot}/.ark-warn.lock.$$" + rm -f "${arkserverroot}/${arkwarnlockfile}.${BASHPID}" update_cancelled(){ if [ -n "$msgUpdateCancelled" ]; then @@ -1340,7 +1341,7 @@ doWarn(){ for warninterval in "${warnintervals[@]}"; do if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting $1" - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" return 1 fi if (( warnminutes >= warninterval )); then @@ -1355,7 +1356,7 @@ doWarn(){ return 0 elif (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" return 0 fi if isUpdateCancelRequested; then @@ -1379,7 +1380,7 @@ doWarn(){ sleeppid=$! if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting update" - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" return 1 fi printWarnMessage "$1" "$2" "seconds" "$warnseconds" @@ -1391,7 +1392,7 @@ doWarn(){ return 0 elif (( (numplayers + 0) == 0 )); then doBroadcastWithEcho "Nobody is connected. Shutting down immediately" - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" return 0 fi if isUpdateCancelRequested; then @@ -1404,7 +1405,7 @@ doWarn(){ done fi - rm -f "${arkserverroot}/.ark-warn.lock" + rm -f "${arkserverroot}/${arkwarnlockfile}" if [ "`getServerPID`" != "$pid" ]; then echo "Server has stopped. Aborting $1" @@ -1459,23 +1460,23 @@ doUpdate() { serverWasAlive=1 fi - echo "$$" >"${arkserverroot}/.ark-update.lock.$$" 2>/dev/null + echo "$$" >"${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null while true; do - if ! ln "${arkserverroot}/.ark-update.lock.$$" "${arkserverroot}/.ark-update.lock" 2>/dev/null; then - local lockpid="$(<"${arkserverroot}/.ark-update.lock")" + if ! ln "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" "${arkserverroot}/${arkupdatelockfile}" 2>/dev/null; then + local lockpid="$(<"${arkserverroot}/${arkupdatelockfile}")" if [ -n "$lockpid" ] && [ "$lockpid" != "$$" ] && kill -0 "$lockpid" 2>/dev/null; then echo "Update already in progress (PID: $lockpid)" - rm -f "${arkserverroot}/.ark-update.lock.$$" 2>/dev/null + rm -f "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null return 1 fi - rm -f "${arkserverroot}/.ark-update.lock" + rm -f "${arkserverroot}/${arkupdatelockfile}" else break fi done - rm -f "${arkserverroot}/.ark-update.lock.$$" + rm -f "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" - echo "`timestamp`: checking for update; PID: $$" + echo "`timestamp`: checking for update; PID: ${BASHPID}" if [ -n "$modupdate" ]; then if [ -z "$nodownload" ]; then @@ -1632,7 +1633,7 @@ doUpdate() { echo "`timestamp`: No update needed." >> "$logdir/update.log" fi; - rm -f "${arkserverroot}/.ark-update.lock" + rm -f "${arkserverroot}/${arkupdatelockfile}" if ! isTheServerRunning; then # we restart the server only if it was started before the update @@ -2485,9 +2486,13 @@ useConfig() { exit 1 fi arkautorestartfile="${arkautorestartfile:-ShooterGame/Saved/.autorestart-${1}}" + arkoldautorestartfile="ShooterGame/Saved/.autorestart" arkserverpidfile="${arkserverpidfile:-ShooterGame/Saved/.arkserver-${1}.pid}" arkserveroldpidfile="ShooterGame/Saved/.arkserver.pid" arkmanagerpidfile="${arkmanagerpidfile:-ShooterGame/Saved/.arkmanager-${1}.pid}" + arkwarnlockfile="${arkwarnlockfile:-ShooterGame/Saved/.ark-warn-${instance}.lock}" + # This is linked to the directory, not to the instance + arkupdatelockfile="${arkupdatelockfile:-ShooterGame/Saved/.ark-update.lock}" } showUsage() { From 3de778be82fb2aef8ccd1776489cf932157b3211 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 22 Sep 2016 23:58:00 +1000 Subject: [PATCH 126/169] Remove files that don't exist in staging dir --- tools/arkmanager | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 210b82d..fa0c5c8 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1612,6 +1612,11 @@ doUpdate() { fi fi done + for f in *; do + if [[ -f "${f}" && ! -e "${arkStagingDir}/${f}" ]]; then + rm "${f}" + fi + done else echo -n "Performing ARK update" cd "$steamcmdroot" From 2ea910b7632d2f73760bcad68f7269b04f0f5e19 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 25 Sep 2016 22:59:12 +1000 Subject: [PATCH 127/169] Get the latest mod version before requesting mod update --- tools/arkmanager | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index fa0c5c8..3c28795 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1686,6 +1686,18 @@ getModIds(){ ) | sort | uniq | grep '^[1-9][0-9]*$' } +# +# Checks if a mod update is available before trying to download it +isModUpdateAvailable(){ + local modid="$1" + local instmft="$(sed -n '/^\t"WorkshopItemsInstalled"$/,/^\t[}]$/{/^\t\t"'"${modid}"'"$/,/^\t\t[}]$/{s|^\t\t\t"manifest"\t\t"\(.*\)"$|\1|p}}' <"$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf")" + local remmft="$(curl -s -d "itemcount=1&publishedfileids[0]=${modid}" http://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1 | sed -n 's|^[[:space:]]*"hcontent_file": "\(.*\)",|\1|p')" + if [[ -n "${remmft}" && "${instmft}" != "${remmft}" ]]; then + return 0 # true + fi + return 1 # false +} + # # Downloads a mod from the Steam workshop # @@ -1742,7 +1754,9 @@ doDownloadMod(){ # doDownloadAllMods(){ for modid in $(getModIds); do - doDownloadMod $modid || return 1 + if isModUpdateAvailable $nodid; then + doDownloadMod $modid || return 1 + fi done } From 36249c56cee522824905ed1c94285a14d490e097 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 26 Sep 2016 00:51:18 +1000 Subject: [PATCH 128/169] Silence cp command during update --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 3c28795..59e1d20 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1509,7 +1509,7 @@ doUpdate() { cp -al "$arkserverroot/Engine/." "$arkStagingDir/Engine" cp -al "$arkserverroot/linux64/." "$arkStagingDir/linux64" cp -a "$arkserverroot/steamapps/." "$arkStagingDir/steamapps" - cp -l "$arkserverroot/"* "$arkStagingDir" + cp -l "$arkserverroot/"* "$arkStagingDir" >/dev/null 2>&1 else rsync -a "$arkserverroot/." "$arkStagingDir/." fi @@ -1595,7 +1595,7 @@ doUpdate() { cp -alu --remove-destination "$arkStagingDir/ShooterGame/." "$arkserverroot/ShooterGame" cp -alu --remove-destination "$arkStagingDir/Engine/." "$arkserverroot/Engine" cp -alu --remove-destination "$arkStagingDir/linux64/." "$arkserverroot/linux64" - cp -lu --remove-destination "$arkStagingDir/"* "$arkserverroot" + cp -lu --remove-destination "$arkStagingDir/"* "$arkserverroot" >/dev/null 2>&1 cp -au --remove-destination "$arkStagingDir/steamapps/." "$arkserverroot/steamapps" else rsync -a "$arkStagingDir/." "$arkserverroot" From 2f1d3cabe5642eeb956be2091f3228ef2e3df7b0 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 27 Sep 2016 19:05:55 +1000 Subject: [PATCH 129/169] Fix a couple of backup issues --- tools/arkmanager | 92 ++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 59e1d20..f257805 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2193,63 +2193,69 @@ doBackup(){ # fail to update the file if the lock fails. echo -e "${NORMAL} Copying ARK profile files" for f in "${savedir}/"*.arkprofile; do - echo -ne "${NORMAL} ${f##*/} " - cp -p "${f}" "${backupdir}/${f##*/}" - if [ ! -s "${backupdir}/${f##*/}" ]; then - sleep 2 + if [ -f "${f}" ]; then + echo -ne "${NORMAL} ${f##*/} " cp -p "${f}" "${backupdir}/${f##*/}" - fi - # If both attempts fail, server may have - # crashed between truncate and write - if [ ! -s "${backupdir}/${f##*/}" ]; then - cp -p "${f%.arkprofile}.tmpprofile" "${backupdir}/${f##*/}" - fi - if [ -s "${backupdir}/${f##*/}" ]; then - echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" - else - echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + if [ ! -s "${backupdir}/${f##*/}" ]; then + sleep 2 + cp -p "${f}" "${backupdir}/${f##*/}" + fi + # If both attempts fail, server may have + # crashed between truncate and write + if [[ ! -s "${backupdir}/${f##*/}" && -f "${f%.arkprofile}.tmpprofile" ]]; then + cp -p "${f%.arkprofile}.tmpprofile" "${backupdir}/${f##*/}" + fi + if [ -s "${backupdir}/${f##*/}" ]; then + echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" + else + echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + fi fi done # ARK server uses Lock-Truncate-Write-Unlock echo -e "${NORMAL} Copying ARK tribe files " for f in "${savedir}/"*.arktribe; do - echo -ne "${NORMAL} ${f##*/} " - cp -p "${f}" "${backupdir}/${f##*/}" - if [ ! -s "${backupdir}/${f##*/}" ]; then - sleep 2 + if [ -f "${f}" ]; then + echo -ne "${NORMAL} ${f##*/} " cp -p "${f}" "${backupdir}/${f##*/}" - fi - # If both attempts fail, server may have - # crashed between truncate and write - if [ ! -s "${backupdir}/${f##*/}" ]; then - cp -p "${f%.arktribe}.tmptribe" "${backupdir}/${f##*/}" - fi - if [ -s "${backupdir}/${f##*/}" ]; then - echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" - else - echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + if [ ! -s "${backupdir}/${f##*/}" ]; then + sleep 2 + cp -p "${f}" "${backupdir}/${f##*/}" + fi + # If both attempts fail, server may have + # crashed between truncate and write + if [[ ! -s "${backupdir}/${f##*/}" && -f "${f%.arktribe}.tmptribe" ]]; then + cp -p "${f%.arktribe}.tmptribe" "${backupdir}/${f##*/}" + fi + if [ -s "${backupdir}/${f##*/}" ]; then + echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" + else + echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + fi fi done # ARK server uses Lock-Truncate-Write-Unlock echo -e "${NORMAL} Copying ARK tribute tribe files " - for f in "${arkserverroot}/ShooterGame/Saved/${savedir}/"*.arktributetribe; do - echo -ne "${NORMAL} ${f##*/} " - cp -p "${f}" "${backupdir}/${f##*/}" - if [ ! -s "${backupdir}/${f##*/}" ]; then - sleep 2 + for f in "${savedir}/"*.arktributetribe; do + if [ -f "${f}" ]; then + echo -ne "${NORMAL} ${f##*/} " cp -p "${f}" "${backupdir}/${f##*/}" - fi - # If both attempts fail, server may have - # crashed between truncate and write - if [ ! -s "${backupdir}/${f##*/}" ]; then - cp -p "${f%.arktribe}.tmptributetribe" "${backupdir}/${f##*/}" - fi - if [ -s "${backupdir}/${f##*/}" ]; then - echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" - else - echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + if [ ! -s "${backupdir}/${f##*/}" ]; then + sleep 2 + cp -p "${f}" "${backupdir}/${f##*/}" + fi + # If both attempts fail, server may have + # crashed between truncate and write + if [[ ! -s "${backupdir}/${f##*/}" && -f "${f%.arktributetribe}.tmptributetribe" ]]; then + cp -p "${f%.arktributetribe}.tmptributetribe" "${backupdir}/${f##*/}" + fi + if [ -s "${backupdir}/${f##*/}" ]; then + echo -e "${NORMAL}\e[68G[ ${GREEN}OK${NORMAL} ]" + else + echo -e "${NORMAL}\e[68G[ ${RED}FAILED${NORMAL} ]" + fi fi done From 95fe90b15f5dd9c98aebc4f94a1f8fb399776117 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 27 Sep 2016 21:22:29 +1000 Subject: [PATCH 130/169] Disable version.txt support It looks like `version.txt` might have been an accident. --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index f257805..f6400ee 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1549,7 +1549,7 @@ doUpdate() { fi echo "Not applying update - download-only enabled" elif [ -n "$appupdate" -o -n "$modupdate" -o -n "$bgupdate" ]; then - if [ -f "$arkserverroot/version.txt" ]; then + if false && [ -f "$arkserverroot/version.txt" ]; then arkversion="$(<"$arkserverroot/version.txt")" else arkversion="$(getCurrentVersion; echo "$instver")" @@ -2440,7 +2440,7 @@ printStatus(){ getCurrentVersion echo -e "$NORMAL" "Server build ID: " "$GREEN" $instver "$NORMAL" - if [ -f "$arkserverroot/version.txt" ]; then + if false && [ -f "$arkserverroot/version.txt" ]; then echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" fi } From f4a3cfd97d3321d99262db03d4c070404d0c2694 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 28 Sep 2016 07:34:33 +1000 Subject: [PATCH 131/169] Fix channel not found test --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index f6400ee..70e06f8 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -69,8 +69,8 @@ doUpgradeToolsFromBranch(){ arkstLatestVersion=`curl -s "https://raw.githubusercontent.com/${arkstGithubRepo}/${arkstChannel}/.version"` arkstLatestCommit=`curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/heads/${arkstChannel}" | sed -n 's/^ *"sha": "\(.*\)",.*/\1/p'` - if [ "$arkstLatestVersion" == "Not Found" ]; then - echo "Channel ${arkstChannel} does not exist" + if [[ "$arkstLatestVersion" == "404: Not Found" ]]; then + echo "Channel '${arkstChannel}' does not exist" echo echo "Available channels:" curl -s "https://api.github.com/repos/${arkstGithubRepo}/git/refs/heads" | sed -n 's|^ *"ref": "refs/heads/\(.*\)",|\1|p' From 94908f6986bf7b4881d3a7a9fe963766c2ca5bd8 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 28 Sep 2016 18:25:23 +1000 Subject: [PATCH 132/169] Use sudo if necessary when installing from commit --- tools/arkmanager | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 70e06f8..be9f204 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -39,6 +39,11 @@ doUpgradeTools() { } doUpgradeToolsFromCommit(){ + local sudo=sudo + if [ "$UID" == 0 -o "$steamcmd_user" == "--me" ]; then + sudo= + fi + local commit="$1" tmpdir="$(mktemp -d "ark-server-tools-XXXXXXXX")" if [ -z "$tmpdir" ]; then echo "Unable to create temporary directory"; exit 1; fi @@ -51,7 +56,7 @@ doUpgradeToolsFromCommit(){ -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ arkmanager echo "Running install.sh" - bash install.sh "$steamcmd_user" "${reinstall_args[@]}" + $sudo bash install.sh "$steamcmd_user" "${reinstall_args[@]}" result=$? cd / rm -rf "$tmpdir" From 0a02cc2e6af97195f6cab1086ddac06bc938d17a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 28 Sep 2016 18:33:23 +1000 Subject: [PATCH 133/169] Add environment variable support when upgrading --- tools/arkmanager | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index be9f204..9a32289 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -11,6 +11,7 @@ arkstVersion='1.6' arkstTag='' arkstCommit='' arkstGithubRepo="FezVrasta/ark-server-tools" +arkstRootUseEnv='' doUpgradeTools() { local sudo=sudo @@ -54,6 +55,7 @@ doUpgradeToolsFromCommit(){ if [ ! -f "install.sh" ]; then echo "install.sh not found in $PWD"; exit 1; fi sed -i -e "s|^arkstCommit='.*'|arkstCommit='${commit}'|" \ -e "s|^arkstTag='.*'|arkstTag='${tagname}'|" \ + -e "s|^arkstRootUseEnv='.*'|arkstRootUseEnv='${arkstRootUseEnv}'|" \ arkmanager echo "Running install.sh" $sudo bash install.sh "$steamcmd_user" "${reinstall_args[@]}" @@ -154,6 +156,11 @@ doUninstallTools() { runAsRoot(){ getConfigVar(){ val="$(echo -ne "$(sed -n "/^$1=/{s|^[^=]*=||;s|[[:space:]]*\\(#.*\\)*\$||;s|^\"\\(.*\\)\"\$|\\1|;s|^'\\(.*\\)'\$|\\1|;p}" <"/etc/arkmanager/arkmanager.cfg" | tail -n1)")" + + if [ -n "$arkstRootUseEnv" ]; then + val="$(eval printf "%s" "$(printf "%q" "${val}" | sed 's|\\[$]\\[{]\([A-Za-z][A-Za-z0-9_]*\)\\[}]|${\1}|g;s|\\[$]\([A-Za-z][A-Za-z0-9_]*\)|${\1}|g')")" + fi + if [ -n "$val" ]; then echo "$val" else @@ -2715,8 +2722,8 @@ main(){ if [ -n "${arkstTag}" ]; then echo "Release Tag: ${arkstTag}" fi - blobsize="$(sed "s@^\\(arkst\\(Commit\\|Tag\\)\\)=.*@\\1=''@" "$0" | wc -c)" - echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^\\(arkst\\(Commit\\|Tag\\)\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" + blobsize="$(sed "s@^\\(arkst\\(Commit\\|Tag\\|RootUseEnv\\)\\)=.*@\\1=''@" "$0" | wc -c)" + echo "Blob SHA: $( (echo -ne "blob ${blobsize}\0"; sed "s@^\\(arkst\\(Commit\\|Tag\\|RootUseEnv\\)\\)=.*@\\1=''@" "$0") | sha1sum | cut -d' ' -f1)" exit 1 ;; -h|--help) From b6c41ca5e2678af0a983b62da0a9b7da9c51654a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 29 Sep 2016 22:54:00 +1000 Subject: [PATCH 134/169] Restart the server if it stops listening --- tools/arkmanager | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 9a32289..f690b68 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -920,6 +920,8 @@ doRun() { restartserver=1 touch "$arkserverroot/$arkautorestartfile" fi + # Retries for checking it the server comes back up after going down + serverdowntries=0 sleep 5 @@ -927,6 +929,7 @@ doRun() { # Grab the current server PID local pid="`getServerPID`" if [ "$pid" == "$serverpid" ]; then + serverdowntries=0 if [ "$restartserver" -eq 0 ]; then # Check if the server has fully started if ! isTheServerUp; then @@ -935,6 +938,28 @@ doRun() { touch "$arkserverroot/$arkautorestartfile" restartserver=1 fi + elif isTheServerUp; then + (( serverdowntries++ )) + + if (( serverdowntries > 12 )); then + # Server has not been listening for 60 seconds, so restart it. + echo "`timestamp`: The server has stopped listening" + echo "`timestamp`: Restarting server" + for (( i = 0; i < 5; i++ )); do + if ! kill -0 "$serverpid"; then + break + fi + kill -INT "$serverpid" + sleep 5 + done + if kill -0 "$serverpid"; then + echo "`timestamp`: Graceful restart failed - killing server" + kill -KILL "$serverpid" + fi + + # Exit the server check loop + break + fi fi else echo "`timestamp`: Bad PID '$pid'; expected '$serverpid'" From ec5151e31cca08a4006ad4730f927cc3cde95c84 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 1 Oct 2016 06:39:12 +1000 Subject: [PATCH 135/169] Download SteamCMD if necessary --- tools/arkmanager | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index f690b68..dbb086f 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -445,6 +445,17 @@ doBroadcastWithEcho(){ doBroadcast "$1" } +# +# Download SteamCMD +# +function doDownloadSteamCMD(){ + if [ ! -f "${steamcmdroot}/${steamcmdexec}" ]; then + mkdir -p "${steamcmdroot}" + curl -s "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" -o "${steamcmdroot}/steamcmd_linux.tar.gz" + tar -xzf "${steamcmdroot}/steamcmd_linux.tar.gz" -C "${steamcmdroot}" + fi +} + # # SteamCMD helper function # @@ -876,11 +887,9 @@ doRun() { done if [[ " ${arkextraopts[*]} " =~ " -automanagedmods " ]]; then - if [ ! -f "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd.sh" ]; then - mkdir -p "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux" - curl -s "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" -o "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd_linux.tar.gz" - tar -xzf "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd_linux.tar.gz" -C "${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux" - fi + steamcmdroot="${arkserverroot}/Engine/Binaries/ThirdParty/SteamCMD/Linux" + steamcmdexec="steamcmd.sh" + doDownloadSteamCMD fi arkserveropts="${arkserveropts}?listen" @@ -1167,6 +1176,7 @@ doInstall() { cd "$steamcmdroot" echo -n "Installing ARK server" # install the server + doDownloadSteamCMD runSteamCMDAppUpdate "$arkserverroot" validate # the current version should be the last version. We set our version getCurrentVersion @@ -1559,6 +1569,7 @@ doUpdate() { if [ -z "$nodownload" ]; then echo -n "Downloading ARK update" + doDownloadSteamCMD cd "$steamcmdroot" if runSteamCMDAppUpdate "$arkStagingDir" $validate; then rm -rf "${arkStagingDir}/steamapps/downloading/${appid}" @@ -1656,6 +1667,7 @@ doUpdate() { done else echo -n "Performing ARK update" + doDownloadSteamCMD cd "$steamcmdroot" runSteamCMDAppUpdate "$arkserverroot" $validate fi @@ -1744,6 +1756,7 @@ doDownloadMod(){ if [ -n "$arkflag_automanagedmods" ]; then steamcmdroot="$arkserverroot/Engine/Binaries/ThirdParty/SteamCMD/Linux" fi + doDownloadSteamCMD local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid" local moddldir="$steamcmdroot/steamapps/workshop/downloads/$mod_appid" cd "$steamcmdroot" From 461729259c1ee44b6fbaacef0f83df96d12f1263 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 1 Oct 2016 07:22:19 +1000 Subject: [PATCH 136/169] Silence errors killing arkmanager process --- tools/arkmanager | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index dbb086f..4737cb5 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1102,7 +1102,7 @@ doStop() { rm -f "$arkserverroot/$arkoldautorestartfile" # kill the server with the PID PID=`getServerPID` - kill -INT $PID + kill -INT $PID >/dev/null 2>&1 for (( i = 0; i < 20; i++ )); do sleep 1 @@ -1114,13 +1114,13 @@ doStop() { if isTheServerRunning; then tput rc echo "Killing server..." - kill -KILL $PID + kill -KILL $PID >/dev/null 2>&1 fi if [ -f "${arkserverroot}/${arkmanagerpidfile}" ]; then PID="$(<"${arkserverroot}/${arkmanagerpidfile}")" if [ -n "$PID" ]; then - kill $PID + kill $PID >/dev/null 2>&1 fi fi From 2bc099f1a3210180004bed4d987f88aaa7fa4a7c Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 1 Oct 2016 07:48:58 +1000 Subject: [PATCH 137/169] Fix RCON authentication failed test --- tools/.arkmanager.swp | Bin 0 -> 110592 bytes tools/arkmanager | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tools/.arkmanager.swp diff --git a/tools/.arkmanager.swp b/tools/.arkmanager.swp new file mode 100644 index 0000000000000000000000000000000000000000..f31fe7dbb2388b61a2b3a78f859461143c681d4e GIT binary patch literal 110592 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
^Oe2?)pC;9Qie&(C5>XaZ=lc3L{4KrU$0HW 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 Yy3D*M>ujo`%zi{#y2N+*8}cvzAAGOgQ2+n{ literal 0 HcmV?d00001 diff --git a/tools/arkmanager b/tools/arkmanager index 4737cb5..bcac987 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -394,7 +394,7 @@ rconcmd() { my $reqid = 1; sendpkt($sock, $reqid, 3, $password); my ($resid, $restype, $rcvbody) = recvpkt($sock); - die "Authentication failed" if $resid == -1; + die "Authentication failed" if $resid == -1 or $resid == 0xFFFFFFFF; } my $port = $ARGV[0]; From 4c4f2f05f3fcbd2b4299fac25bb970961a22c23d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 2 Oct 2016 11:19:41 +1000 Subject: [PATCH 138/169] Remove swap file --- tools/.arkmanager.swp | Bin 110592 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tools/.arkmanager.swp diff --git a/tools/.arkmanager.swp b/tools/.arkmanager.swp deleted file mode 100644 index f31fe7dbb2388b61a2b3a78f859461143c681d4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110592 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
^Oe2?)pC;9Qie&(C5>XaZ=lc3L{4KrU$0HW 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 Yy3D*M>ujo`%zi{#y2N+*8}cvzAAGOgQ2+n{ From 992baeb23a9fe269a990dc64dcd014058512fe81 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 2 Oct 2016 11:42:57 +1000 Subject: [PATCH 139/169] Exclude some temp files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e43b0f9..6259ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .DS_Store +.*.sw? +*~ From 60465a178a08bad91e1af432a6d2821bbbaaba96 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 2 Oct 2016 12:23:21 +1000 Subject: [PATCH 140/169] Add arkCpuAffinity setting --- README.asciidoc | 5 +++++ tools/arkmanager | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 45ca324..c224142 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -407,6 +407,11 @@ The following options can be overridden on a per-instance basis: Negative values give a higher priority, and positive values give a lower priority. Requires `sudo` and `renice` +`arkCpuAffinity`:: + Attempts to set the CPU affinity of the ARK server. + Setting is a comma-delimited list of processor indices on which the server should run. + Requires `sudo` and `taskset` + `msgWarnUpdateMinutes`:: `msgWarnUpdateSeconds`:: `msgWarnRestartMinutes`:: diff --git a/tools/arkmanager b/tools/arkmanager index bcac987..9833d9c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1030,15 +1030,23 @@ doStart() { echo "The server is starting..." local pid=$! - if [ -n "$arkPriorityBoost" ]; then + if [[ -n "$arkPriorityBoost" || -n "$arkCpuAffinity" ]]; then doRun --wait >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged local pid="$!" # Wait for monitor process to suspend itself wait - echo "Boosting priority of ark server" - sudo renice -n "$arkPriorityBoost" "$pid" + if [ -n "$arkPriorityBoost" ]; then + echo "Boosting priority of ark server" + sudo renice -n "$arkPriorityBoost" "$pid" + fi + + if [ -n "$arkCpuAffinity" ]; then + echo "Setting CPU affinity for ark server" + sudo taskset -c "$arkCpuAffinity" -p "$pid" + fi + kill -CONT "$pid" else doRun >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged From 4a2699bf2ea46fa8be18eae168477de0fe282271 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 3 Oct 2016 02:03:21 +1000 Subject: [PATCH 141/169] Fix a couple of errors in isModUpdateAvailable --- tools/arkmanager | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index 9833d9c..2a33012 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1747,7 +1747,9 @@ getModIds(){ # Checks if a mod update is available before trying to download it isModUpdateAvailable(){ local modid="$1" + if [ ! -f "$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf" ]; then return 0; fi local instmft="$(sed -n '/^\t"WorkshopItemsInstalled"$/,/^\t[}]$/{/^\t\t"'"${modid}"'"$/,/^\t\t[}]$/{s|^\t\t\t"manifest"\t\t"\(.*\)"$|\1|p}}' <"$steamcmdroot/steamapps/workshop/appworkshop_${mod_appid}.acf")" + if [ -z "$instmft" ]; then return 0; fi local remmft="$(curl -s -d "itemcount=1&publishedfileids[0]=${modid}" http://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1 | sed -n 's|^[[:space:]]*"hcontent_file": "\(.*\)",|\1|p')" if [[ -n "${remmft}" && "${instmft}" != "${remmft}" ]]; then return 0 # true From fc4d6442beaa5c83019b79a7d257ed1c9bdf04ac Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 3 Oct 2016 16:31:14 +1000 Subject: [PATCH 142/169] Allow single cronjob to execute command on multiple instances --- tools/arkmanager | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2a33012..580aad3 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2386,6 +2386,7 @@ doInstallCronJob(){ minute='0' cmdopts="${arkCronExtraOpts}" cmdargs="" + instargs="" output=">/dev/null 2>&1" arkmanagerpath="${0}" command="$1" @@ -2414,15 +2415,23 @@ doInstallCronJob(){ cmdopts="${cmdopts} $(printf "%q" "${opt}")" ;; *) - cmdargs="${args} $(printf "%q" "${opt}")" + cmdargs="${cmdargs} $(printf "%q" "${opt}")" ;; esac done - cronjob="${minute} ${hour} * * * ${arkmanagerpath} --cronjob ${command} @${instance} ${cmdopts} --args ${cmdargs} -- ${output}" + if [ -n "$allinstances" ]; then + instargs="@all" + else + for inst in "${instances[@]}"; do + instargs="${instargs} $(printf "%q" "@${inst}")" + done + fi + + cronjob="${minute} ${hour} * * * ${arkmanagerpath} --cronjob ${command} ${instargs} ${cmdopts} --args ${cmdargs} -- ${output}" (crontab -l | \ - sed -e "\\# [*] [*] [*] ${arkmanagerpath} --cronjob ${command} @${instance} #d"; + sed -e "\\# [*] [*] [*] ${arkmanagerpath} --cronjob ${command} ${instargs} #d"; echo "${cronjob}" ) | \ crontab - } @@ -2801,6 +2810,18 @@ main(){ fi fi + # Handle cronjob commands specially + case "$command" in + install-cronjob) + doInstallCronJob "${args[@]}" "${options[@]}" "$@" + exit + ;; + remove-cronjob) + doRemoveCronJob "${args[@]}" + exit + ;; + esac + # Handle all instances being requested if [[ "$allinstances" == "yes" ]]; then instances=( $(getAllInstanceNames) ) @@ -2879,12 +2900,6 @@ main(){ status) printStatus ;; - install-cronjob) - doInstallCronJob "${args[@]}" "${options[@]}" - ;; - remove-cronjob) - doRemoveCronJob "${args[@]}" - ;; *) echo -n "arkmanager v${arkstVersion}: unknown command '$command' specified" showUsage From 5405c642d9ef8fe2ed54261a076afc07d7920bec Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 4 Oct 2016 04:17:53 +1000 Subject: [PATCH 143/169] Work around SIGSTOP not notifying the parent --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 580aad3..e90df35 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1035,7 +1035,7 @@ doStart() { local pid="$!" # Wait for monitor process to suspend itself - wait + sleep 1 if [ -n "$arkPriorityBoost" ]; then echo "Boosting priority of ark server" From 1a32ac00123dccc6f4aa0bf92c23616be7a2df52 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 4 Oct 2016 04:26:03 +1000 Subject: [PATCH 144/169] sudo not needed to set CPU affinity on our own processes --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index e90df35..56ea003 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1044,7 +1044,7 @@ doStart() { if [ -n "$arkCpuAffinity" ]; then echo "Setting CPU affinity for ark server" - sudo taskset -c "$arkCpuAffinity" -p "$pid" + taskset -c "$arkCpuAffinity" -p "$pid" fi kill -CONT "$pid" From bfd3c0e4f5f4c02b25f530bb75a1a7b9b1ca52a8 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Fri, 7 Oct 2016 04:41:14 +1000 Subject: [PATCH 145/169] taskset uses non-standard option processing --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 56ea003..578ff05 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1044,7 +1044,7 @@ doStart() { if [ -n "$arkCpuAffinity" ]; then echo "Setting CPU affinity for ark server" - taskset -c "$arkCpuAffinity" -p "$pid" + taskset -pc "$arkCpuAffinity" "$pid" fi kill -CONT "$pid" From fe1594bcd050b21f59f97b653bc6fee5984c0270 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 8 Oct 2016 18:35:54 +1000 Subject: [PATCH 146/169] Remove failing workshop items when downloading mods --- tools/arkmanager | 7 ++++++- tools/arkmanager.cfg | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 578ff05..38de77b 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -237,6 +237,7 @@ appid="${appid:-376030}" mod_appid="${mod_appid:-346110}" install_bindir="${install_bindir:-${0%/*}}" install_libexecdir="${install_libexecdir:-${install_bindir%/*}/libexec/arkmanager}" +steamcmd_workshoplog="${steamcmd_workshoplog:-${HOME}/Steam/logs/workshop_log.txt}" if [ "$steamcmd_user" == "--me" ]; then install_datadir="${install_datadir:-${HOME}/.share/local/arkmanager}" @@ -1787,7 +1788,11 @@ doDownloadMod(){ break else echo - if [ ! -d "$moddldir" ]; then + failedmod="$(sed -n 's|.* Download item \([0-9]*\) result : \(.*\)|\1\t\2|p' "${steamcmd_workshoplog}" | grep -v ' OK' | tail -n1 | cut -f1)" + if [[ -n "$failedmod" && "$failedmod" != "$modid" ]]; then + echo "Mod $failedmod prevented mod update - removing failed mod" + doRemoveMods "$failedmod" + elif [ ! -d "$moddldir" ]; then echo "Mod $modid download failed" break fi diff --git a/tools/arkmanager.cfg b/tools/arkmanager.cfg index 750f866..34391a0 100644 --- a/tools/arkmanager.cfg +++ b/tools/arkmanager.cfg @@ -8,6 +8,7 @@ steamcmdroot="/home/steam/steamcmd" # path of yo steamcmdexec="steamcmd.sh" # name of steamcmd executable steamcmd_user="steam" # name of the system user who own steamcmd folder steamcmd_appinfocache="/home/steam/Steam/appcache/appinfo.vdf" # cache of the appinfo command +steamcmd_workshoplog="/home/steam/Steam/logs/workshop_log.txt" # Steam workshop log #steamlogin="anonymous" # Uncomment this to specify steam login instead of using anonymous login # config environment From d50fdd1b33dbd4fac648b9b1d4c2336b8a9386ee Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sat, 8 Oct 2016 18:38:36 +1000 Subject: [PATCH 147/169] Fix last commit - only take recent failures --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 38de77b..cfdc4c6 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1788,7 +1788,7 @@ doDownloadMod(){ break else echo - failedmod="$(sed -n 's|.* Download item \([0-9]*\) result : \(.*\)|\1\t\2|p' "${steamcmd_workshoplog}" | grep -v ' OK' | tail -n1 | cut -f1)" + failedmod="$(tail -n 20 "${steamcmd_workshoplog}" | sed -n 's|.* Download item \([0-9]*\) result : \(.*\)|\1\t\2|p' | grep -v $'\tOK' | tail -n1 | cut -f1)" if [[ -n "$failedmod" && "$failedmod" != "$modid" ]]; then echo "Mod $failedmod prevented mod update - removing failed mod" doRemoveMods "$failedmod" From c4db8f665ef4fc0cb6c279d91e03fd1a5c3ef40c Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 18 Oct 2016 09:12:21 +1000 Subject: [PATCH 148/169] Don't migrate to main.cfg if arkSingleInstance is set --- tools/migrate-main-instance.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/migrate-main-instance.sh b/tools/migrate-main-instance.sh index 79cdfd6..4d32a84 100755 --- a/tools/migrate-main-instance.sh +++ b/tools/migrate-main-instance.sh @@ -3,7 +3,7 @@ configfile="$1" instancefile="$2" -if grep "^arkserverroot=" <"$configfile" >/dev/null 2>&1 && [ ! -f "$instancefile" ]; then +if ! grep '^arkSingleInstance=' <"$configfile" >/dev/null 2>&1 && grep "^arkserverroot=" <"$configfile" >/dev/null 2>&1 && [ ! -f "$instancefile" ]; then sed -n '/^#*\(ark\(\|flag\|opt\)_[^=]*\|arkserverroot\|serverMap\(\|ModId\)\)=/p' <"$configfile" >"$instancefile" sed -i '/^ark\(serverroot\|_\(RCONPort\|Port\|QueryPort\)\)=/d' "$configfile" echo 'defaultinstance="main"' >>"$configfile" From 653f9a5cd001aab469c2797e7ed5f3505d6a5e3c Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 18 Oct 2016 09:30:05 +1000 Subject: [PATCH 149/169] Use arkSingleInstance to skip multi-instance --- tools/arkmanager | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index cfdc4c6..442cf92 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -12,6 +12,8 @@ arkstTag='' arkstCommit='' arkstGithubRepo="FezVrasta/ark-server-tools" arkstRootUseEnv='' +arkstGlobalCfgFile='/etc/arkmanager/arkmanager.cfg' +arkstUserCfgFile='.arkmanager.cfg' doUpgradeTools() { local sudo=sudo @@ -155,7 +157,7 @@ doUninstallTools() { runAsRoot(){ getConfigVar(){ - val="$(echo -ne "$(sed -n "/^$1=/{s|^[^=]*=||;s|[[:space:]]*\\(#.*\\)*\$||;s|^\"\\(.*\\)\"\$|\\1|;s|^'\\(.*\\)'\$|\\1|;p}" <"/etc/arkmanager/arkmanager.cfg" | tail -n1)")" + val="$(echo -ne "$(sed -n "/^$1=/{s|^[^=]*=||;s|[[:space:]]*\\(#.*\\)*\$||;s|^\"\\(.*\\)\"\$|\\1|;s|^'\\(.*\\)'\$|\\1|;p}" <"${arkstGlobalCfgFile}" | tail -n1)")" if [ -n "$arkstRootUseEnv" ]; then val="$(eval printf "%s" "$(printf "%q" "${val}" | sed 's|\\[$]\\[{]\([A-Za-z][A-Za-z0-9_]*\)\\[}]|${\1}|g;s|\\[$]\([A-Za-z][A-Za-z0-9_]*\)|${\1}|g')")" @@ -203,12 +205,12 @@ fi #--------------------- # Global variables -if [ -f "/etc/arkmanager/arkmanager.cfg" ]; then - source /etc/arkmanager/arkmanager.cfg +if [ -f "${arkstGlobalCfgFile}" ]; then + source "${arkstGlobalCfgFile}" fi -if [ -f "${HOME}/.arkmanager.cfg" ]; then - source "${HOME}/.arkmanager.cfg" +if [ -f "${HOME}/${arkstUserCfgFile}" ]; then + source "${HOME}/${arkstUserCfgFile}" fi cd "$HOME" @@ -2564,7 +2566,7 @@ doPrintConfig(){ for v in $(eval echo \$\{\!{a..z}\*\} \$\{\!{A..Z}\*\} \$\{\!_\*\}); do vals["$v"]="${!v}" done - for cfgfile in "$configfile" "$HOME/.arkmanager.cfg" "/etc/arkmanager/arkmanager.cfg"; do + for cfgfile in "$configfile" "${HOME}/${arkstUserCfgFile}" "${arkstGlobalCfgFile}"; do while read v; do val="$(source "$cfgfile"; echo "${!v}")" if [[ "$val" = "${vals[$v]}" && -z "${vars[$v]}" ]]; then @@ -2589,15 +2591,23 @@ useConfig() { break fi done - if [ -z "$configfile" ]; then - echo "Error: no config files for instance $1" - exit 1 + if [[ -z "$configfile" && -n "$arkSingleInstance" ]]; then + if [ -f "${HOME}/${arkstUserCfgFile}" ]; then + configfile="${HOME}/${arkstUserCfgFile}" + else + configfile="${arkstGlobalCfgFile}" + fi + else + if [ -z "$configfile" ]; then + echo "Error: no config files for instance $1" + exit 1 + fi + if [ ! -f "$configfile" ]; then + echo "Error: config file $configfile does not exist" + exit 1 + fi + source "$configfile" fi - if [ ! -f "$configfile" ]; then - echo "Error: config file $configfile does not exist" - exit 1 - fi - source "$configfile" if [ -z "$arkserverroot" ]; then echo "Error: arkserverroot not set" exit 1 @@ -2607,7 +2617,7 @@ useConfig() { arkserverpidfile="${arkserverpidfile:-ShooterGame/Saved/.arkserver-${1}.pid}" arkserveroldpidfile="ShooterGame/Saved/.arkserver.pid" arkmanagerpidfile="${arkmanagerpidfile:-ShooterGame/Saved/.arkmanager-${1}.pid}" - arkwarnlockfile="${arkwarnlockfile:-ShooterGame/Saved/.ark-warn-${instance}.lock}" + arkwarnlockfile="${arkwarnlockfile:-ShooterGame/Saved/.ark-warn-${1}.lock}" # This is linked to the directory, not to the instance arkupdatelockfile="${arkupdatelockfile:-ShooterGame/Saved/.ark-update.lock}" } From 772398ffc082b976a6e64b65055d3bc26bfa58dd Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 23 Oct 2016 14:10:10 +1000 Subject: [PATCH 150/169] Check if lsof exists before using it --- tools/arkmanager | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 442cf92..2e5db57 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -641,8 +641,11 @@ function isTheServerRunning(){ # # function isTheServerUp(){ - $lsof -i "${ark_MultiHome:+udp@}${ark_MultiHome}:$(getGamePort)" > /dev/null - result=$? + result=1 + if [ ! -x "$lsof" ]; then + "$lsof" -i "${ark_MultiHome:+udp@}${ark_MultiHome}:$(getGamePort)" > /dev/null + result=$? + fi if [ $result -ne 0 ]; then perl -MSocket -MFcntl -e ' my $port = int($ARGV[0]); From c9c385deb716fb1751dd222725581d6977bab73b Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 24 Oct 2016 13:11:50 +1000 Subject: [PATCH 151/169] Add prelogin and postlogin custom steamcmd commands --- tools/arkmanager | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2e5db57..71fadd4 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -463,13 +463,13 @@ function doDownloadSteamCMD(){ # SteamCMD helper function # function runSteamCMD(){ - "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 +login ${steamlogin:-anonymous} "$@" +quit + "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 ${steamcmd_cmds_prelogin} +login ${steamlogin:-anonymous} ${steamcmd_cmds_postlogin} "$@" +quit } function runSteamCMDspinner(){ if [ -n "$verbose" ]; then printf "Executing" - printf " %q" "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 +login ${steamlogin:-anonymous} "$@" +quit + printf " %q" "$steamcmdroot/$steamcmdexec" +@NoPromptForPassword 1 ${steamcmd_cmds_prelogin} +login ${steamlogin:-anonymous} ${steamcmd_cmds_postlogin} "$@" +quit printf "\n" if (command >&3) 2>/dev/null; then runSteamCMD "$@" > >(tee /dev/fd/3) From 385a90915372098982e1cd3cfcbecd36ff4fabff Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 30 Oct 2016 23:31:30 +1000 Subject: [PATCH 152/169] Fix typo in isUpdateCancelRequested --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 71fadd4..b3edb80 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1334,7 +1334,7 @@ printWarnMessage(){ isUpdateCancelRequested(){ if [ -n "$chatCommandRestartCancel" ]; then local canceltime="$( - find "${arkserverrroot}/ShooterGame/Saved/Logs" -name 'ServerGame.*.log' -mmin -5 -print0 | + find "${arkserverroot}/ShooterGame/Saved/Logs" -name 'ServerGame.*.log' -mmin -5 -print0 | xargs -0 grep -F -e "${chatCommandRestartCancel}" | sed 's@^[[]\(....\)\.\(..\)\.\(..\)-\(..\)\.\(..\)\.\(..\):.*@\1-\2-\3 \4:\5:\6 UTC@' | head -n1)" From 241b35a8f5d13e4709679e9481fae5350f8f2e92 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 7 Nov 2016 06:10:26 +1000 Subject: [PATCH 153/169] Exclude Primitive+ from mods returned by getModIds Requested in #657 --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index b3edb80..2742f7a 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1746,7 +1746,7 @@ getModIds(){ fi done find "${arkserverroot}/ShooterGame/Content/Mods" -maxdepth 1 -type d -printf "%P\n" - ) | sort | uniq | grep '^[1-9][0-9]*$' + ) | sort | uniq | grep '^[1-9][0-9]*$' | grep -v '^111111111$' } # From a4621389c909a193ebc47e9826e1602098d0ed6a Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 13 Nov 2016 09:55:29 +1000 Subject: [PATCH 154/169] Add warning about user-installs Too many tickets have been opened where the user has performed a user-install and then is wondering why their settings in `/etc/arkmanager/instances/main.cfg` are being overridden. Give the user a big warning if they try to perform a user-install without knowing what they're doing. --- netinstall.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/netinstall.sh b/netinstall.sh index c69a2de..7ddab9b 100644 --- a/netinstall.sh +++ b/netinstall.sh @@ -26,6 +26,19 @@ if [ "$1" = "--unstable" ]; then unstable=1 fi +userinstall= +if [ "$1" = "--perform-user-install" ]; then + userinstall=yes +fi + +if [[ "$steamcmd_user" == "--me" && -z "$userinstall" ]]; then + echo "You have requested a user-install. You probably don't want this." + echo "A user-install will create ~/.config/arkmanager/instances/main.cfg" + echo "This config file will override /etc/arkmanager/instances/main.cfg" + echo "Add --perform-user-install if you really want this." + exit 1 +fi + function doInstallFromCommit(){ local commit="$1" tmpdir="$(mktemp -t -d "ark-server-tools-XXXXXXXX")" From b8c64830bbbb12679d1cae456a3813b7985056e6 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 13 Nov 2016 10:05:46 +1000 Subject: [PATCH 155/169] Don't load user-instance if older than global-instance Too many people have performed a user-install and then opened a ticket wondering why their settings in /etc/arkmanager/instances/main.cfg won't apply. Avoid this by not loading the instance.cfg in ~/.config/arkmanager/instances if it's older than the instance.cfg in /etc/arkmanager/instances --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 2742f7a..42672a2 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2585,7 +2585,7 @@ useConfig() { if [ -f "/etc/arkmanager/instances/${1}.cfg" ]; then configfile="/etc/arkmanager/instances/${1}.cfg" fi - if [ -f "${HOME}/.config/arkmanager/instances/${1}.cfg" ]; then + if [[ -f "${HOME}/.config/arkmanager/instances/${1}.cfg" && "${HOME}/.config/arkmanager/instances/${1}.cfg" -nt "/etc/arkmanager/instances/${1}.cfg" ]]; then configfile="${HOME}/.config/arkmanager/instances/${1}.cfg" fi for varname in "${!configfile_@}"; do From d7d6f3e5a50e7f23911e7e69292d2d20b9ed02ec Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 02:34:58 +1000 Subject: [PATCH 156/169] Fix wrong PID being written to log file --- tools/arkmanager | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 42672a2..5ef2874 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1357,11 +1357,11 @@ doWarn(){ cd "$arkserverroot" ( - echo "$$" >"${arkserverroot}/${arkwarnlockfile}.${BASHPID}" 2>/dev/null + echo "${BASHPID}" >"${arkserverroot}/${arkwarnlockfile}.${BASHPID}" 2>/dev/null while true; do if ! ln "${arkserverroot}/${arkwarnlockfile}.${BASHPID}" "${arkserverroot}/${arkwarnlockfile}" 2>/dev/null; then local lockpid="$(<"${arkserverroot}/${arkwarnlockfile}")" - if [ -n "$lockpid" ] && [ "$lockpid" != "$$" ] && kill -0 "$lockpid" 2>/dev/null; then + if [ -n "$lockpid" ] && [ "$lockpid" != "${BASHPID}" ] && kill -0 "$lockpid" 2>/dev/null; then echo "Shutdown warning already in progress (PID: $lockpid)" rm -f "${arkserverroot}/${arkwarnlockfile}.${BASHPID}" 2>/dev/null exit 1 @@ -1527,11 +1527,11 @@ doUpdate() { serverWasAlive=1 fi - echo "$$" >"${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null + echo "${BASHPID}" >"${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null while true; do if ! ln "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" "${arkserverroot}/${arkupdatelockfile}" 2>/dev/null; then local lockpid="$(<"${arkserverroot}/${arkupdatelockfile}")" - if [ -n "$lockpid" ] && [ "$lockpid" != "$$" ] && kill -0 "$lockpid" 2>/dev/null; then + if [ -n "$lockpid" ] && [ "$lockpid" != "${BASHPID}" ] && kill -0 "$lockpid" 2>/dev/null; then echo "Update already in progress (PID: $lockpid)" rm -f "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null return 1 From 04185bee4cdd6a657d3613385edf1a3576061cc2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 02:53:13 +1000 Subject: [PATCH 157/169] Fix get*Version; check if staging dir was updated --- tools/arkmanager | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index 5ef2874..e171cb2 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -542,9 +542,9 @@ function checkForUpdate(){ # Return 0 if update is needed, else return 1 # function isUpdateNeeded(){ - getCurrentVersion - getAvailableVersion - if [[ "$bnumber" == "Unknown" || "$bnumber" -eq "$instver" ]]; then + instver="$(getCurrentVersion)" + bnumber="$(getAvailableVersion)" + if [[ -z "$bnumber" || "$bnumber" -eq "$instver" ]]; then return 1 # no update needed else return 0 # update needed @@ -583,10 +583,16 @@ function parseSteamACF(){ # 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="" + while read name val; do if [ "${name}" == "{" ]; then parseSteamACF "" "buildid"; break; fi; done <"${arkserverroot}/steamapps/appmanifest_${appid}.acf" + fi +} + +# +# Return the version from the staging directory +# +function getStagingVersion(){ + if [ -f "${arkStagingDir}/steamapps/appmanifest_${appid}.acf" ]; then + while read name val; do if [ "${name}" == "{" ]; then parseSteamACF "" "buildid"; break; fi; done <"${arkStagingDir}/steamapps/appmanifest_${appid}.acf" fi } @@ -595,10 +601,7 @@ function getCurrentVersion(){ # function getAvailableVersion(){ rm -f "$steamcmd_appinfocache" - bnumber=`runSteamCMD +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` - if [ -z "$bnumber" ]; then - bnumber="Unknown" - fi + runSteamCMD +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 } # @@ -1193,7 +1196,7 @@ doInstall() { doDownloadSteamCMD runSteamCMDAppUpdate "$arkserverroot" validate # the current version should be the last version. We set our version - getCurrentVersion + instver="$(getCurrentVersion)" } @@ -1595,6 +1598,13 @@ doUpdate() { fi fi fi + + local curver="$(getCurrentVersion)" + local newver="$(getStagingVersion)" + if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + echo "Update download unsuccessful" + return 1 + fi fi if [[ -f "$arkserverroot/$arkautorestartfile" && "$arkserverroot/$arkautorestartfile" -ot "${arkserverroot}/steamapps/appmanifest_${appid}.acf" ]]; then @@ -1614,7 +1624,7 @@ doUpdate() { if false && [ -f "$arkserverroot/version.txt" ]; then arkversion="$(<"$arkserverroot/version.txt")" else - arkversion="$(getCurrentVersion; echo "$instver")" + arkversion="$(getCurrentVersion)" fi if isTheServerRunning; then @@ -1686,7 +1696,7 @@ doUpdate() { runSteamCMDAppUpdate "$arkserverroot" $validate fi # the current version should be the last version. We set our version - getCurrentVersion + instver="$(getCurrentVersion)" echo "`timestamp`: update to $instver complete" >> "$logdir/update.log" fi @@ -2517,7 +2527,7 @@ printStatus(){ fi fi - getCurrentVersion + instver="$(getCurrentVersion)" echo -e "$NORMAL" "Server build ID: " "$GREEN" $instver "$NORMAL" if false && [ -f "$arkserverroot/version.txt" ]; then echo -e "$NORMAL" "Server version: " "$GREEN" "$(<"$arkserverroot/version.txt")" "$NORMAL" From e2d6a44a98e5eff64ff11c04a1f18b058ef74157 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 07:13:59 +1000 Subject: [PATCH 158/169] Don't check version when using --force --- tools/arkmanager | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index e171cb2..dac791c 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1498,10 +1498,11 @@ doUpdate() { local use_systemd= local use_service= local use_upstart= + local force= for arg in "$@"; do case "$arg" in - --force) appupdate=1; ;; + --force) appupdate=1; force=1; ;; --safe) updatetype=safe; ;; --warn) updatetype=warn; ;; --ifempty) updatetype=ifempty; ;; @@ -1599,11 +1600,13 @@ doUpdate() { fi fi - local curver="$(getCurrentVersion)" - local newver="$(getStagingVersion)" - if [[ -z "${newver}" || "$curver" == "$newver" ]]; then - echo "Update download unsuccessful" - return 1 + if [ -z "${force}" ]; then + local curver="$(getCurrentVersion)" + local newver="$(getStagingVersion)" + if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + echo "Update download unsuccessful" + return 1 + fi fi fi From 256d59e1b29d017e418a8d3ca6463acc02fe1963 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 07:20:10 +1000 Subject: [PATCH 159/169] Warn when update has failed when using --force --- tools/arkmanager | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index dac791c..e5aad75 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1600,12 +1600,15 @@ doUpdate() { fi fi - if [ -z "${force}" ]; then - local curver="$(getCurrentVersion)" - local newver="$(getStagingVersion)" - if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + local curver="$(getCurrentVersion)" + local newver="$(getStagingVersion)" + local nextver="$(getAvailableVersion)" + if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + if [ -z "$force" ]; then echo "Update download unsuccessful" return 1 + elif [ "${newver}" != "${nextver}" ]; then + echo "Warning: staging directory update was unsuccessful" fi fi fi From 5222c5d6c79f0f1721075e1fe176557645e21e6d Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 07:23:21 +1000 Subject: [PATCH 160/169] Ignore unchanging version with --validate --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index e5aad75..deb8fea 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1507,7 +1507,7 @@ doUpdate() { --warn) updatetype=warn; ;; --ifempty) updatetype=ifempty; ;; --warnreason=*) warnreason="${arg#--warnreason=}"; updatetype=warn; ;; - --validate) validate=validate; appupdate=1; ;; + --validate) validate=validate; appupdate=1; force=1; ;; --saveworld) saveworld=1; ;; --update-mods) modupdate=1; ;; --backup) arkBackupPreUpdate=true; ;; From a5d3fd72c238eec3d33d21cf8a146c6b4129ac23 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 07:28:00 +1000 Subject: [PATCH 161/169] Fix failure when not using staging dir --- tools/arkmanager | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index deb8fea..c5819c8 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1598,17 +1598,17 @@ doUpdate() { return 1 fi fi - fi - local curver="$(getCurrentVersion)" - local newver="$(getStagingVersion)" - local nextver="$(getAvailableVersion)" - if [[ -z "${newver}" || "$curver" == "$newver" ]]; then - if [ -z "$force" ]; then - echo "Update download unsuccessful" - return 1 - elif [ "${newver}" != "${nextver}" ]; then - echo "Warning: staging directory update was unsuccessful" + local curver="$(getCurrentVersion)" + local newver="$(getStagingVersion)" + local nextver="$(getAvailableVersion)" + if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + if [ -z "$force" ]; then + echo "Update download unsuccessful" + return 1 + elif [ "${newver}" != "${nextver}" ]; then + echo "Warning: staging directory update was unsuccessful" + fi fi fi fi From 6f244a02fa6d06b1c01e1cd1dba7587d101bfc85 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 07:30:04 +1000 Subject: [PATCH 162/169] Fix failure when using --nodownload --- tools/arkmanager | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index c5819c8..bdb6823 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1597,17 +1597,17 @@ doUpdate() { echo "Update download interrupted" return 1 fi - fi - local curver="$(getCurrentVersion)" - local newver="$(getStagingVersion)" - local nextver="$(getAvailableVersion)" - if [[ -z "${newver}" || "$curver" == "$newver" ]]; then - if [ -z "$force" ]; then - echo "Update download unsuccessful" - return 1 - elif [ "${newver}" != "${nextver}" ]; then - echo "Warning: staging directory update was unsuccessful" + local curver="$(getCurrentVersion)" + local newver="$(getStagingVersion)" + local nextver="$(getAvailableVersion)" + if [[ -z "${newver}" || "$curver" == "$newver" ]]; then + if [ -z "$force" ]; then + echo "Update download unsuccessful" + return 1 + elif [ "${newver}" != "${nextver}" ]; then + echo "Warning: staging directory update was unsuccessful" + fi fi fi fi From 567f899725ac4494bede7b12ffdc2b03cb2ea057 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 29 Nov 2016 16:01:29 +1000 Subject: [PATCH 163/169] Check if depot manifests have changed --- tools/arkmanager | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/arkmanager b/tools/arkmanager index bdb6823..b70021d 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -546,6 +546,9 @@ function isUpdateNeeded(){ bnumber="$(getAvailableVersion)" if [[ -z "$bnumber" || "$bnumber" -eq "$instver" ]]; then return 1 # no update needed + elif checkUpdateManifests; then + echo "Build ID changed but manifests have not changed" + return 1 else return 0 # update needed fi @@ -604,6 +607,20 @@ function getAvailableVersion(){ runSteamCMD +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 } +# +# Check if the update manifest matches the current manifest +# +function checkUpdateManifests(){ + appinfo="$(runSteamCMD +app_info_print "$appid" +quit)" + while read depot manifest <&3; do + newmanifest="$(echo "${appinfo}" | while read name val; do if [ "${name}" == "{" ]; then parseSteamACF ".depots.${depot}.manifests" "public"; break; fi; done)" + if [ "${newmanifest}" != "${manifest}" ]; then + return 1 + fi + done 3< <(sed -n '/^[{]$/,/^[}]$/{/^\t"MountedDepots"$/,/^\t[}]$/{/^\t\t/p}}' "${arkserverroot}/steamapps/appmanifest_${appid}.acf") + return 0 +} + # # Get the PID of the server process # From 77c66161798122468a08f7b7885f9ccc0cd82896 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Wed, 7 Dec 2016 17:03:33 +1000 Subject: [PATCH 164/169] Improve update logging a little bit --- tools/arkmanager | 75 ++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/tools/arkmanager b/tools/arkmanager index b70021d..00dd481 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -260,6 +260,14 @@ timestamp() { date +"%Y-%m-%d %H:%M:%S" } +# +# Log a message to arkmanager.log, and exho it to the console +# +logprint(){ + printf "%s\n" "$*" + printf "%s: %s\n" "$(timestamp)" "$*" >>"${logdir}/${arkmanagerLog}" +} + # # check configuration and report errors # @@ -1032,19 +1040,18 @@ doStart() { if [ -f "${arkserverroot}/${arkupdatelockfile}" ]; then local updatepid="$(<"${arkserverroot}/${arkupdatelockfile}")" if kill -0 "$updatepid" >/dev/null 2>&1; then - echo "An update is currently in progress. Start aborted" - echo "`timestamp`: Start aborted due to running update - pid: $updatepid" >>"$logdir/$arkserverLog" + logprint "Start aborted due to running update - pid: $updatepid" return 1 fi fi - if isTheServerRunning; then - echo "The server is already running" - echo "`timestamp`: Start aborted due to server already running" + serverpid="$(getServerPid)" + if [ -n "$serverpid" ] && kill -0 "$serverpid"; then + logprint "Start aborted due to server already running - pid: $serverpid" else if [ "$arkAutoUpdateOnStart" == "true" ]; then if ! [[ " $* " =~ " --noautoupdate " ]]; then - echo "Updating server" + logprint "Checking for updates before starting" doUpdate --update-mods --no-autostart fi fi @@ -1053,7 +1060,7 @@ doStart() { arkAlwaysRestartOnCrash=true fi tput sc - echo "The server is starting..." + logprint "The server is starting..." local pid=$! if [[ -n "$arkPriorityBoost" || -n "$arkCpuAffinity" ]]; then @@ -1064,7 +1071,7 @@ doStart() { sleep 1 if [ -n "$arkPriorityBoost" ]; then - echo "Boosting priority of ark server" + logprint "Boosting priority of ark server" sudo renice -n "$arkPriorityBoost" "$pid" fi @@ -1077,9 +1084,8 @@ doStart() { else doRun >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged fi - echo "`timestamp`: start" >> "$logdir/$arkmanagerLog" tput rc; tput ed; - echo "The server is now running, and should be up within 10 minutes" + logprint "The server is now running, and should be up within 10 minutes" fi } @@ -1130,8 +1136,7 @@ doStop() { doSaveWorld fi tput sc - echo "Stopping server..." - echo "`timestamp`: stopping; reason: $stopreason" >> "$logdir/$arkmanagerLog" + logprint "Stopping server; reason: $stopreason" rm -f "$arkserverroot/$arkautorestartfile" rm -f "$arkserverroot/$arkoldautorestartfile" # kill the server with the PID @@ -1147,7 +1152,7 @@ doStop() { if isTheServerRunning; then tput rc - echo "Killing server..." + logprint "Killing server" kill -KILL $PID >/dev/null 2>&1 fi @@ -1163,8 +1168,7 @@ doStop() { rm -f "${arkserverroot}/${arkmanagerpidfile}" tput rc; tput ed; - echo "The server has been stopped" - echo "`timestamp`: stopped" >> "$logdir/$arkmanagerLog" + logprint "The server has been stopped" else echo "The server is already stopped" fi @@ -1553,7 +1557,7 @@ doUpdate() { if ! ln "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" "${arkserverroot}/${arkupdatelockfile}" 2>/dev/null; then local lockpid="$(<"${arkserverroot}/${arkupdatelockfile}")" if [ -n "$lockpid" ] && [ "$lockpid" != "${BASHPID}" ] && kill -0 "$lockpid" 2>/dev/null; then - echo "Update already in progress (PID: $lockpid)" + logprint "Update already in progress (PID: $lockpid)" rm -f "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" 2>/dev/null return 1 fi @@ -1564,7 +1568,7 @@ doUpdate() { done rm -f "${arkserverroot}/${arkupdatelockfile}.${BASHPID}" - echo "`timestamp`: checking for update; PID: ${BASHPID}" + logprint "Checking for update; PID: ${BASHPID}" if [ -n "$modupdate" ]; then if [ -z "$nodownload" ]; then @@ -1584,7 +1588,7 @@ doUpdate() { if [ -n "${arkStagingDir}" -a "${arkStagingDir}" != "${arkserverroot}" ]; then if [ ! -d "$arkStagingDir/ShooterGame" ]; then - echo "Copying to staging directory" + logprint "Copying to staging directory" mkdir -p "$arkStagingDir" if [ "$(stat -c "%d" "$arkserverroot")" == "$(stat -c "%d" "$arkStagingDir")" ]; then cp -al "$arkserverroot/ShooterGame/." "$arkStagingDir/ShooterGame" @@ -1604,6 +1608,7 @@ doUpdate() { if [ -z "$nodownload" ]; then echo -n "Downloading ARK update" + logprint "Downloading ARK update" >/dev/null doDownloadSteamCMD cd "$steamcmdroot" if runSteamCMDAppUpdate "$arkStagingDir" $validate; then @@ -1611,7 +1616,7 @@ doUpdate() { fi if [ -d "${arkStagingDir}/steamapps/downloading/${appid}" ]; then - echo "Update download interrupted" + logprint "Update download interrupted" return 1 fi @@ -1620,10 +1625,10 @@ doUpdate() { local nextver="$(getAvailableVersion)" if [[ -z "${newver}" || "$curver" == "$newver" ]]; then if [ -z "$force" ]; then - echo "Update download unsuccessful" + logprint "Update download unsuccessful" return 1 elif [ "${newver}" != "${nextver}" ]; then - echo "Warning: staging directory update was unsuccessful" + logprint "Warning: staging directory update was unsuccessful" fi fi fi @@ -1631,18 +1636,18 @@ doUpdate() { fi if [[ -f "$arkserverroot/$arkautorestartfile" && "$arkserverroot/$arkautorestartfile" -ot "${arkserverroot}/steamapps/appmanifest_${appid}.acf" ]]; then - echo "Server was updated while it was running" + logprint "Server was updated while it was running" bgupdate=1 fi if [ -n "$downloadonly" ]; then if [ -n "$appupdate" -a -n "$arkStagingDir" -a "$arkStagingDir" != "$arkserverroot" ]; then - echo "Server update downloaded" + logprint "Server update downloaded" fi if [ -n "$modupdate" ]; then - echo "Mod update downloaded" + logprint "Mod update downloaded" fi - echo "Not applying update - download-only enabled" + logprint "Not applying update - download-only requested" elif [ -n "$appupdate" -o -n "$modupdate" -o -n "$bgupdate" ]; then if false && [ -f "$arkserverroot/version.txt" ]; then arkversion="$(<"$arkserverroot/version.txt")" @@ -1653,10 +1658,10 @@ doUpdate() { if isTheServerRunning; then if [ "$updatetype" == "safe" ]; 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" + logprint "Save file older than 1 minute. Delaying update." sleep 30s done - echo "`timestamp`: Save file newer than 1 minute. Performing an update." >> "$logdir/update.log" + logprint "Save file newer than 1 minute. Performing an update." elif [ "$updatetype" == "warn" ]; then if ! doWarn update; then return 1 @@ -1664,14 +1669,14 @@ doUpdate() { elif [ "$updatetype" == "ifempty" ]; then numplayers=$(( $(numPlayersConnected) + 0 )) if (( numplayers != 0 )); then - echo "${numplayers} players are still connected" + logprint "${numplayers} players are still connected" return 1 fi fi fi if [ -n "$saveworld" ]; then - echo "Saving world" + logprint "Saving world" doSaveWorld fi @@ -1685,7 +1690,7 @@ doUpdate() { if [ -n "$appupdate" ]; then if [ -d "${arkStagingDir}" -a "${arkStagingDir}" != "${arkserverroot}" ]; then - echo "Applying update from staging directory" + logprint "Applying update from staging directory" if [ "$(stat -c "%d" "$arkserverroot")" == "$(stat -c "%d" "$arkStagingDir")" ]; then cp -alu --remove-destination "$arkStagingDir/ShooterGame/." "$arkserverroot/ShooterGame" cp -alu --remove-destination "$arkStagingDir/Engine/." "$arkserverroot/Engine" @@ -1714,21 +1719,22 @@ doUpdate() { done else echo -n "Performing ARK update" + logprint "Performing ARK update" >/dev/null doDownloadSteamCMD cd "$steamcmdroot" runSteamCMDAppUpdate "$arkserverroot" $validate fi # the current version should be the last version. We set our version instver="$(getCurrentVersion)" - echo "`timestamp`: update to $instver complete" >> "$logdir/update.log" + logprint "Update to $instver complete" fi if [ -n "$modupdate" ] && [ -z "$arkflag_automanagedmods" ]; then for modid in $(getModIds); do if isModUpdateNeeded $modid; then - echo "Updating mod $modid" + logprint "Updating mod $modid" doExtractMod $modid - echo "`timestamp`: Mod $modid updated" >> "$logdir/update.log" + logprint "Mod $modid updated" fi done fi @@ -1736,8 +1742,7 @@ doUpdate() { touch "${arkserverroot}/steamapps/appmanifest_${appid}.acf" fi else - echo "Your server is already up to date! The most recent version is ${bnumber}." - echo "`timestamp`: No update needed." >> "$logdir/update.log" + logprint "Your server is already up to date! The most recent version is ${bnumber}." fi; rm -f "${arkserverroot}/${arkupdatelockfile}" From 481b39301720b43a4f18509d71611d2ed7b49706 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Sun, 11 Dec 2016 15:57:25 +1000 Subject: [PATCH 165/169] Output detected Saved Arks directory and world file name --- tools/arkmanager | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 00dd481..ee75785 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -2256,8 +2256,10 @@ doBackup(){ fi fi + echo "${NORMAL} Saved arks directory is ${savedir}" + # ARK server uses Write-Unlink-Rename - echo -ne "${NORMAL} Copying ARK world file " + echo -ne "${NORMAL} Copying ARK world file (${serverMap}) " # Take into account screwed up casing of saved ark files # in some environments From 0a1d8089051c7805cfd52276077c004648cad080 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 12 Dec 2016 01:57:24 +1000 Subject: [PATCH 166/169] Fix typo of getServerPID in doRun --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index ee75785..6400b25 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1045,7 +1045,7 @@ doStart() { fi fi - serverpid="$(getServerPid)" + serverpid="$(getServerPID)" if [ -n "$serverpid" ] && kill -0 "$serverpid"; then logprint "Start aborted due to server already running - pid: $serverpid" else From db592eeb403949005d70c5a4b96185c47324359e Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 13 Dec 2016 15:02:54 +1100 Subject: [PATCH 167/169] Add instance name to arkmanager.log log entries --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 6400b25..35cb6b4 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -265,7 +265,7 @@ timestamp() { # logprint(){ printf "%s\n" "$*" - printf "%s: %s\n" "$(timestamp)" "$*" >>"${logdir}/${arkmanagerLog}" + printf "%s: [%s] %s\n" "$(timestamp)" "${instance}" "$*" >>"${logdir}/${arkmanagerLog}" } # From 37db49f6f559c53f7fb25edba2e83b5e0b883717 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Tue, 13 Dec 2016 15:06:20 +1100 Subject: [PATCH 168/169] Add timestamp and instance name to arkserver.log log entries --- tools/arkmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 35cb6b4..0e92dcd 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1064,7 +1064,7 @@ doStart() { local pid=$! if [[ -n "$arkPriorityBoost" || -n "$arkCpuAffinity" ]]; then - doRun --wait >"$logdir/$arkserverLog" 2>&1 & # output of this command is logged + doRun --wait >(while read -r l; do printf "%s: [%s] %s\n" "$(timestamp)" "${instance}" "${l}" >>"$logdir/$arkserverLog"; done) 2>&1 & # output of this command is logged local pid="$!" # Wait for monitor process to suspend itself From a51dcdc35b599c76a05e337c0acce29d64083359 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 15 Dec 2016 19:11:44 +1100 Subject: [PATCH 169/169] Continue downloading mods if one fails --- tools/arkmanager | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/arkmanager b/tools/arkmanager index 0e92dcd..f18494f 100755 --- a/tools/arkmanager +++ b/tools/arkmanager @@ -1861,11 +1861,18 @@ doDownloadMod(){ # Downloads all installed and requested mods from the Steam workshop # doDownloadAllMods(){ + local fail=0 + local success=0 for modid in $(getModIds); do if isModUpdateAvailable $nodid; then - doDownloadMod $modid || return 1 + if doDownloadMod $modid; then + success=1 + else + fail=1 + fi fi done + [[ $success == 1 || $fail == 0 ]] && return 0 || return 1 } #