Merge pull request #167 from klightspeed/1.4-dev#modupdate

1.4 dev#modupdate
This commit is contained in:
Fez Vrasta 2015-09-16 12:46:57 +02:00
commit ec8eec8cfa

View File

@ -444,66 +444,171 @@ doInstall() {
getCurrentVersion getCurrentVersion
} }
#
# Waits for a configurable number of minutes before updating the server
#
doUpdateWarn(){
cd "$arkserverroot"
local pid=`getServerPID`
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 1 )
for warninterval in "${warnintervals[@]}"; do
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
return 1
fi
if (( arkwarnminutes > warninterval )); then
if [ -n "$msgWarnUpdateMinutes" ]; then
warnmsg="$(printf "$msgWarnUpdateMinutes" "$warnminutes")"
else
warnmsg="$(printf "This ARK server will shutdown for an update in %d minutes" "$warnminutes")"
fi
doBroadcastWithEcho "$warnmsg"
sleep $(( warnminutes - warninterval ))m
warnminutes=$warninterval
fi
done
local warnseconds=90
warnintervals=( 60 45 30 20 15 10 5 0 )
for warninterval in "${warnintervals[@]}"; do
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
return 1
fi
if [ -n "$msgWarnUpdateMinutes" ]; then
warnmsg="$(printf "$msgWarnUpdateMinutes" "$warnminutes")"
else
warnmsg="$(printf "This ARK server will shutdown for an update in %d seconds" "$warnseconds")"
fi
doBroadcastWithEcho "$warnmsg"
sleep $(( warnseconds - warninterval ))s
done
fi
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
return 1
fi
return 0
}
# #
# Stop the server, update it and then start it back. # Stop the server, update it and then start it back.
# #
doUpdate() { doUpdate() {
local appupdate=
local updatetype=normal
local validate=
local modupdate=
for arg in "$@"; do
if [ "$arg" == "--force" ]; then
appupdate=1
elif [ "$arg" == "--safe" ]; then
updatetype=safe
elif [ "$arg" == "--warn" ]; then
updatetype=warn
elif [ "$arg" == "--validate" ]; then
validate=validate
appupdate=1
elif [ "$arg" == "--update-mods" ]; then
modupdate=1
fi
done
if [ -n "$modupdate" ]; then
if ! doDownloadAllMods; then
modupdate=
fi
if ! isAnyModUpdateNeeded; then
modupdate=
fi
fi
cd "$arkserverroot" cd "$arkserverroot"
if isUpdateNeeded; then if isUpdateNeeded; then
forceUpdate appupdate=1
fi
if [ -n "$appupdate" -o -n "$modupdate" ]; then
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"
sleep 30s
done
echo "`timestamp`: Save file newer than 1 minute. Performing an update." >> "$logdir/update.log"
elif [ "$updatetype" == "warn" ]; then
if ! doUpdateWarn; then
return 1
fi
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
doStop
if [ -n "$appupdate" ]; then
cd "$steamcmdroot"
./$steamcmdexec +login anonymous +force_install_dir "$arkserverroot" +app_update $appid $validate +quit
# the current version should be the last version. We set our version
getCurrentVersion
echo "`timestamp`: update to $instver complete" >> "$logdir/update.log"
fi
if [ -n "$modupdate" ]; then
for modid in $(getModIds); do
if isModUpdateNeeded $modid; then
doExtractMod $modid
echo "`timestamp`: Mod $modid updated" >> "$logdir/update.log"
fi
done
fi
# we restart the server only if it was started before the update
if [ $serverWasAlive -eq 1 ]; then
doStart
fi
else else
echo "Your server is already up to date! The most recent version is ${bnumber}." echo "Your server is already up to date! The most recent version is ${bnumber}."
echo "`timestamp`: No update needed." >> "$logdir/update.log" echo "`timestamp`: No update needed." >> "$logdir/update.log"
fi; fi;
} }
forceUpdate(){ #
# check if the server was alive before the update so we can launch it back after the update # Get the Mod IDs of the installed mods and the requested mods
serverWasAlive=0 #
if isTheServerRunning ;then getModIds(){
serverWasAlive=1 (
fi echo "${serverMapModId}"
doStop echo "${ark_TotalConversionMod}"
cd "$steamcmdroot" echo "${ark_GameModIds}" | tr ',' '\n'
./$steamcmdexec +login anonymous +force_install_dir "$arkserverroot" +app_update $appid +quit find "${arkserverroot}/ShooterGame/Content/Mods" -maxdepth 1 -type d -printf "%P\n"
# the current version should be the last version. We set our version ) | sort | uniq | grep '^[1-9][0-9]*$'
getCurrentVersion
echo "`timestamp`: update to $instver complete" >> "$logdir/update.log"
# we restart the server only if it was started before the update
if [ $serverWasAlive -eq 1 ]; then
doStart
fi
} }
# #
# Waits for server to perform save before update (until save file is newer than 1 minute) # Downloads a mod from the Steam workshop
# #
doSafeUpdate(){ doDownloadMod(){
cd "$arkserverroot"
if isUpdateNeeded; then
while [ ! `find $arkserverroot/ShooterGame/Saved/SavedArks -mmin -1 -name ${serverMap##*/}.ark` ]; do
echo "`timestamp`: Save file older than 1 minute. Delaying update." >> "$logdir/update.log"
sleep 30s
done
echo "`timestamp`: Save file newer than 1 minute. Performing an update." >> "$logdir/update.log"
forceUpdate
else
echo "Your server is already up to date! The most recent version is ${bnumber}."
echo "`timestamp`: No update needed." >> "$logdir/update.log"
fi
}
#
# Downloads mod and installs it into mods directory
#
doInstallMod(){
local modid=$1 local modid=$1
local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid" local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid"
local moddldir="$steamcmdroot/steamapps/workshop/downloads/$mod_appid/$modid" local moddldir="$steamcmdroot/steamapps/workshop/downloads/$mod_appid/$modid"
local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid"
local dlsize=0 local dlsize=0
cd "$steamcmdroot" cd "$steamcmdroot"
@ -517,50 +622,122 @@ doInstallMod(){
if [ -f "$modsrcdir/mod.info" ]; then if [ -f "$modsrcdir/mod.info" ]; then
echo "Mod $modid downloaded" echo "Mod $modid downloaded"
return 0
else
echo "Mod $modid was not successfully downloaded"
return 1
fi
}
#
# Downloads all installed and requested mods from the Steam workshop
#
doDownloadAllMods(){
for modid in $(getModIds); do
doDownloadMod $modid || return 1
done
}
#
# Checks if the files a mod owns need to be updated
#
isModUpdateNeeded(){
local modid=$1
local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid"
local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid"
if [ -f "$modsrcdir/mod.info" ]; then
if [ -f "$modsrcdir/LinuxNoEditor/mod.info" ]; then
modsrcdir="$modsrcdir/LinuxNoEditor"
fi
find "$modsrcdir" -type f ! -name "*.z.uncompressed_size" -printf "%P\n" | while read f; do
if [ ! -f "$moddestdir/${f%.z}" -o "$modsrcdir/$f" -nt "$moddestdir/${f%.z}" ]; then
return 0
fi
done
fi
return 1
}
#
# Checks if any installed or requested mods need to be updated
#
isAnyModUpdateNeeded(){
for modid in $(getModIds); do
if isModUpdateNeeded $modid; then
return 0
fi
done
return 1
}
#
# Extracts a mod into the ARK Mods directory
#
doExtractMod(){
local modid=$1
local modsrcdir="$steamcmdroot/steamapps/workshop/content/$mod_appid/$modid"
local moddestdir="$arkserverroot/ShooterGame/Content/Mods/$modid"
if [ -f "$modsrcdir/mod.info" ]; then
echo "Copying files to $moddestdir" echo "Copying files to $moddestdir"
if [ -f "$modsrcdir/LinuxNoEditor/mod.info" ]; then if [ -f "$modsrcdir/LinuxNoEditor/mod.info" ]; then
modsrcdir="$modsrcdir/LinuxNoEditor" modsrcdir="$modsrcdir/LinuxNoEditor"
fi fi
find "$modsrcdir" -type d -printf "$moddestdir/%P\0" | xargs -0 -r mkdir -p find "$modsrcdir" -type d -printf "$moddestdir/%P\0" | xargs -0 -r mkdir -p
find "$modsrcdir" -type f ! \( -name '*.z' -or -name '*.z.uncompressed_size' \) -printf "%P\0" | xargs -0 -r tar -c -C "$modsrcdir" | tar -x -C "$moddestdir"
find "$modsrcdir" -type f ! \( -name '*.z' -or -name '*.z.uncompressed_size' \) -printf "%P\n" | while read f; do
if [ ! -f "$moddestdir/$f" -o "$modsrcdir/$f" -nt "$moddestdir/$f" ]; then
printf "%10d %s " "`stat -c '%s' "$modsrcdir/$f"`" "$f"
cp "$modsrcdir/$f" "$moddestdir/$f"
echo -ne "\r\\033[K"
fi
done
find "$modsrcdir" -type f -name '*.z' -printf "%P\n" | while read f; do find "$modsrcdir" -type f -name '*.z' -printf "%P\n" | while read f; do
printf "%10d %s " "`stat -c '%s' "$modsrcdir/$f"`" "${f%.z}" if [ ! -f "$moddestdir/${f%.z}" -o "$modsrcdir/$f" -nt "$moddestdir/${f%.z}" ]; then
perl -M'Compress::Raw::Zlib' -e ' printf "%10d %s " "`stat -c '%s' "$modsrcdir/$f"`" "${f%.z}"
my $sig; perl -M'Compress::Raw::Zlib' -e '
read(STDIN, $sig, 8) or die "Unable to read compressed file"; my $sig;
if ($sig != "\xC1\x83\x2A\x9E\x00\x00\x00\x00"){ read(STDIN, $sig, 8) or die "Unable to read compressed file";
die "Bad file magic"; if ($sig != "\xC1\x83\x2A\x9E\x00\x00\x00\x00"){
} die "Bad file magic";
my $data;
read(STDIN, $data, 24) or die "Unable to read compressed file";
my ($chunksizelo, $chunksizehi,
$comprtotlo, $comprtothi,
$uncomtotlo, $uncomtothi) = unpack("(LLLLLL)<", $data);
my @chunks = ();
my $comprused = 0;
while ($comprused < $comprtotlo) {
read(STDIN, $data, 16) or die "Unable to read compressed file";
my ($comprsizelo, $comprsizehi,
$uncomsizelo, $uncomsizehi) = unpack("(LLLL)<", $data);
push @chunks, $comprsizelo;
$comprused += $comprsizelo;
}
foreach my $comprsize (@chunks) {
read(STDIN, $data, $comprsize) or die "File read failed";
my ($inflate, $status) = new Compress::Raw::Zlib::Inflate();
my $output;
$status = $inflate->inflate($data, $output, 1);
if ($status != Z_STREAM_END) {
die "Bad compressed stream; status: " . ($status);
} }
if (length($data) != 0) { my $data;
die "Unconsumed data in input" read(STDIN, $data, 24) or die "Unable to read compressed file";
my ($chunksizelo, $chunksizehi,
$comprtotlo, $comprtothi,
$uncomtotlo, $uncomtothi) = unpack("(LLLLLL)<", $data);
my @chunks = ();
my $comprused = 0;
while ($comprused < $comprtotlo) {
read(STDIN, $data, 16) or die "Unable to read compressed file";
my ($comprsizelo, $comprsizehi,
$uncomsizelo, $uncomsizehi) = unpack("(LLLL)<", $data);
push @chunks, $comprsizelo;
$comprused += $comprsizelo;
} }
print $output; foreach my $comprsize (@chunks) {
} read(STDIN, $data, $comprsize) or die "File read failed";
' <"$modsrcdir/$f" >"$moddestdir/${f%.z}" my ($inflate, $status) = new Compress::Raw::Zlib::Inflate();
echo -ne "\r\\033[K" my $output;
$status = $inflate->inflate($data, $output, 1);
if ($status != Z_STREAM_END) {
die "Bad compressed stream; status: " . ($status);
}
if (length($data) != 0) {
die "Unconsumed data in input"
}
print $output;
}
' <"$modsrcdir/$f" >"$moddestdir/${f%.z}"
touch -c -r "$modsrcdir/$f" "$moddestdir/${f%.z}"
echo -ne "\r\\033[K"
fi
done done
perl -e ' perl -e '
@ -581,68 +758,18 @@ doInstallMod(){
else 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 fi
echo "Mod $modid installed"
else
echo "Mod $modid was not successfully downloaded"
fi fi
} }
# #
# Waits for a configurable number of minutes before updating the server # Downloads mod and installs it into mods directory
# #
doWarnUpdate(){ doInstallMod(){
cd "$arkserverroot" local modid=$1
if isUpdateNeeded; then if doDownloadMod $modid; then
local pid=`getServerPID` doExtractMod $modid
if [ -n "$pid" ]; then echo "Mod $modid installed"
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 1 )
for warninterval in "${warnintervals[@]}"; do
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
return 1
fi
if (( arkwarnminutes > warninterval )); then
if [ -n "$msgWarnUpdateMinutes" ]; then
warnmsg="$(printf "$msgWarnUpdateMinutes" "$warnminutes")"
else
warnmsg="$(printf "This ARK server will shutdown for an update in %d minutes" "$warnminutes")"
fi
doBroadcastWithEcho "$warnmsg"
sleep $(( warnminutes - warninterval ))m
warnminutes=$warninterval
fi
done
local warnseconds=90
warnintervals=( 60 45 30 20 15 10 5 0 )
for warninterval in "${warnintervals[@]}"; do
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
return 1
fi
if [ -n "$msgWarnUpdateMinutes" ]; then
warnmsg="$(printf "$msgWarnUpdateMinutes" "$warnminutes")"
else
warnmsg="$(printf "This ARK server will shutdown for an update in %d seconds" "$warnseconds")"
fi
doBroadcastWithEcho "$warnmsg"
sleep $(( warnseconds - warninterval ))s
done
fi
if [ "`getServerPID`" != "$pid" ]; then
echo "Server has stopped. Aborting update"
fi
doUpdate
fi fi
} }
@ -869,18 +996,14 @@ while true; do
doInstall doInstall
;; ;;
update) update)
if [ "$2" == "--force" ]; then args=()
forceUpdate
while [[ "$2" =~ ^-- ]]; do
args=( "${args[@]}" "$2" )
shift shift
elif [ "$2" == "--safe" ]; then done
doSafeUpdate
shift doUpdate "${args[@]}"
elif [ "$2" == "--warn" ]; then
doWarnUpdate
shift
else
doUpdate
fi
;; ;;
checkupdate) checkupdate)
checkForUpdate checkForUpdate
@ -915,26 +1038,29 @@ while true; do
;; ;;
-h|--help) -h|--help)
echo -e "Usage: arkmanager [OPTION]\n" echo -e "Usage: arkmanager [OPTION]\n"
echo "Option Description" echo "Option Description"
echo "backup Saves a backup of your server inside the backup directory" echo "backup Saves a backup of your server inside the backup directory"
echo "broadcast <msg> Sends a message to all users connected to server" echo "broadcast <msg> Sends a message to all users connected to server"
echo "saveworld Saves the game world to disk" echo "saveworld Saves the game world to disk"
echo "rconcmd <cmd> Execute RCON command on server" echo "rconcmd <cmd> Execute RCON command on server"
echo "checkupdate Check for a new ARK server version" echo "checkupdate Check for a new ARK server version"
echo "install Install the ARK server files from steamcmd" echo "install Install the ARK server files from steamcmd"
echo "restart Stops the server and then starts it" echo "installmod <modid> Installs a mod from the Steam workshop"
echo "restart --all Restarts all servers specified in configfile_xxxxx" echo "restart Stops the server and then starts it"
echo "start Starts the server" echo "restart --all Restarts all servers specified in configfile_xxxxx"
echo "start --all Starts all servers specified in configfile_xxxxx" echo "start Starts the server"
echo "stop Stops the server" echo "start --all Starts all servers specified in configfile_xxxxx"
echo "stop --all Stops all servers specified in configfile_xxxxx" echo "stop Stops the server"
echo "status Returns the status of the current ARK server instance" echo "stop --all Stops all servers specified in configfile_xxxxx"
echo "update Check for a new ARK server version, if needed, stops the server, updates it, and starts it again" echo "status Returns the status of the current ARK server instance"
echo "update --force Apply update without check the current version" echo "update Check for a new ARK server version, if needed, stops the server, updates it, and starts it again"
echo "update --safe Wait for server to perform world save and update." echo "update --force Apply update without checking the current version"
echo "update --warn Warn players before updating server" echo "update --safe Wait for server to perform world save and update."
echo "upgrade Check for a new ARK Server Tools version and upgrades it if needed" echo "update --warn Warn players before updating server"
echo "useconfig <name> Use the configuration overrides in the specified config name or file" echo "update --validate Validates all ARK server files"
echo "update --update-mods Updates installed and requested mods"
echo "upgrade Check for a new ARK Server Tools version and upgrades it if needed"
echo "useconfig <name> Use the configuration overrides in the specified config name or file"
exit 1 exit 1
;; ;;
*) *)