#!/bin/bash # kf2-srv is a command line tool for managing a set of Killing Floor 2 servers. # Copyright (C) 2019-2021 GenZmeY # mailto: genzmey@gmail.com # # This file is part of kf2-srv. # # kf2-srv is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . function show_enabled_instances () { local EnabledInstances="" for Instance in $(show_instances) do if systemctl -q is-enabled $(service_name "$Instance") ; then EnabledInstances+=" $Instance" fi done echo "$EnabledInstances" } function show_instances () { find "$InstanceConfigDir" \ -maxdepth 1 \ -mindepth 1 \ -type d \ -printf "%f\n" } function service_name () # $*: Instance[s] { local Services="" for Instance in $* do if multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "UseOrigApp" 2> /dev/null | grep -Piqo '^True$' && test -x "$AppBinOrig"; then Services+=" kf2-srv${KF2POSTFIX}-orig@$Instance.service" else Services+=" kf2-srv${KF2POSTFIX}@$Instance.service" fi done echo "$Services" } function service_names () # $*: Instance[s] { local Services="" for Instance in $* do Services+=" kf2-srv${KF2POSTFIX}-orig@$Instance.service" Services+=" kf2-srv${KF2POSTFIX}@$Instance.service" done echo "$Services" } function instance_exists () # $1: Instance { test -d "$InstanceConfigDir/$1" return $? } function instance_add () # $*: InstanceName[s] { include /etc/steamcmd/steamcmd.conf include /etc/kf2-srv/kf2-srv.conf include "$LibDir/game.lib" if [[ -z "$*" ]]; then echo "Name of instance[s] must be set" exit 1 fi local MaxGamePort='7777' local MaxQueryPort='27015' local MaxWebAdminPort='8080' for Instance in $(show_instances) do local Config="$InstanceConfigDir/$Instance/instance.conf" local GamePort=$(multini --get "$Config" '' 'PortGame') local WebAdminPort=$(multini --get "$Config" '' 'PortWeb') local QueryPort=$(multini --get "$Config" '' 'PortQuery') if [[ "$GamePort" -gt "$MaxGamePort" ]]; then MaxGamePort="$GamePort"; fi if [[ "$QueryPort" -gt "$MaxQueryPort" ]]; then MaxQueryPort="$QueryPort"; fi if [[ "$WebAdminPort" -gt "$MaxWebAdminPort" ]]; then MaxWebAdminPort="$WebAdminPort"; fi done for Instance in $* do if instance_exists "$Instance"; then echo "Instance $Instance already exists - skip" continue fi local InstanceDir="$InstanceConfigDir/$Instance" local DirMode="-d -g $SteamUser -o $IniGroup -m 775" local FileMode=" -g $SteamUser -o $IniGroup -m $IniPermissions" install $DirMode "$InstanceDir" install $DirMode "$InstanceDir/LinuxServer" install $FileMode "$InstanceConfigTemplate" "$InstanceDir/instance.conf" install $FileMode "$DefaultConfigDir/KFAI.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/KFWeb.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/KFWebAdmin.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/KFMultiAdmin.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFEngine.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFGame.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFInput.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer-KFSystemSettings.ini" "$InstanceDir" install $FileMode "$DefaultConfigDir/LinuxServer/LinuxServerEngine.ini" "$InstanceDir/LinuxServer" install $FileMode "$DefaultConfigDir/LinuxServer/LinuxServerGame.ini" "$InstanceDir/LinuxServer" install $FileMode "$DefaultConfigDir/LinuxServer/LinuxServerInput.ini" "$InstanceDir/LinuxServer" install $FileMode "$DefaultConfigDir/LinuxServer/LinuxServerSystemSettings.ini" "$InstanceDir/LinuxServer" ((MaxGamePort++)); ((MaxQueryPort++)); ((MaxWebAdminPort++)) multini -s "$InstanceDir/instance.conf" '' 'PortGame' "$MaxGamePort" multini -s "$InstanceDir/instance.conf" '' 'PortQuery' "$MaxQueryPort" multini -s "$InstanceDir/instance.conf" '' 'PortWeb' "$MaxWebAdminPort" multini -s "$InstanceDir/KFWeb.ini" "IpDrv.WebServer" "bEnabled" "true" multini -s "$InstanceDir/LinuxServer-KFEngine.ini" "LogFiles" "PurgeLogsDays" "0" multini -s "$InstanceDir/LinuxServer-KFEngine.ini" "LogFiles" "LogTimes" "False" multini -s "$InstanceDir/KFWebAdmin.ini" "WebAdmin.WebAdmin" "AuthenticationClass" "WebAdmin.MultiWebAdminAuth" multini -s "$InstanceDir/KFWebAdmin.ini" "WebAdmin.WebAdmin" "bHttpAuth" "True" multini -s "$InstanceDir/KFWebAdmin.ini" "WebAdmin.Chatlog" "Filename" "$Instance-chat" multini -s "$InstanceDir/KFWebAdmin.ini" "WebAdmin.Chatlog" "bIncludeTimeStamp" "False" echo "Instance $Instance created. See /etc/$ScriptName/instances$BetaPostfix/$Instance for edit configuration" done } function instance_chat () # $1: Message, $*: instance... { include "$LibDir/webadmin.lib" local Message=$(echo "$1" | sed 's/ /+/g') shift local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_instances) fi for Instance in $InstanceList do ( if instance_exists "$Instance"; then local Service=$(service_name "$Instance") if systemctl -q is-active $Service ; then admin_curl "$Instance" "ServerAdmin/current/chat+frame+data" \ --request POST \ --data ajax=1 \ --data message="$Message" \ --data teamsay=-1 else echo "Instance $Instance not running - skip" fi else echo "Instance $Instance not exitst" fi ) & done wait } function instance_delete () # $*: [InstanceName[s]] { if [[ -z "$*" ]]; then echo "Are you sure you want to delete all instances? [y/N]" local Answ="N" read Answ if [[ "$Answ" == "y" || "$Answ" == "Y" ]]; then for Instance in $(show_instances) do ( instance_stop "$Instance" instance_delete "$Instance" ) & done fi else for Instance in $* do ( if instance_exists "$Instance"; then local InstanceDir="$InstanceConfigDir/$Instance" instance_stop "$Instance" rm -rf "$InstanceDir" echo "Instance $Instance removed" else echo "Instance $Instance not exists" fi ) & done fi wait } function instance_disable () # $*: [InstanceName[s]] { local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_instances) fi local ToDisableInstanceList="" for Instance in $InstanceList do if instance_exists "$Instance"; then ToDisableInstanceList+=" $Instance" else echo "Instance $Instance not exitst" fi done if [[ -n "$ToDisableInstanceList" ]]; then systemctl disable $(service_names "$ToDisableInstanceList") else echo "Nothing to do" fi } function instance_enable () # $1*: [InstanceName[s]] { local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_instances) fi local ToEnableInstanceList="" for Instance in $InstanceList do if instance_exists "$Instance"; then ToEnableInstanceList+=" $Instance" else echo "Instance $Instance not exist" fi done if [[ -n "$ToEnableInstanceList" ]]; then systemctl enable $(service_name "$ToEnableInstanceList") else echo "Nothing to do" fi } function instance_list () # $*: [InstanceName[s]] { { echo -e "INSTANCE:AUTORUN:STATE:P_GAME:P_QUERY:P_WEB:TYPE:LEN:DIFF:MUTATORS:ARGS:COMMENT" { local InstanceList="$*" if [[ -z "$*" ]] ; then InstanceList=$(show_instances) fi for Instance in $InstanceList do ( instance_status "$Instance" ) & done wait } | sort -t : -k 4 } | column -t -s : } function instance_status () # $1: InstanceName { include /etc/kf2-srv/kf2-srv.conf local Instance="$1" if ! instance_exists "$Instance"; then return 1; fi if systemctl -q is-enabled $(service_name "$Instance"); then local IsEnabled="enabled" else local IsEnabled="disabled" fi if systemctl | grep $(service_name "$Instance") | grep -q 'running' ; then local IsRuning="running" else local IsRuning="stopped" fi local Comment=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Comment") local GamePort=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "PortGame") local WebAdminPort=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "PortWeb") local QueryPort=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "PortQuery") local GameType=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Game") local GameLength=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Length") local GameDifficulty=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Difficulty") local Map=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Map") local Mutators=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Mutators") local Args=$( multini -g "$InstanceConfigDir/$Instance/instance.conf" '' "Args") local DisplayGameType='' local DisplayGameLength='' local DisplayDifficulty='' local DisplayMutators='' for Mutator in ${Mutators//,/ } do local MutName=${MutNames[$Mutator]} if [[ -z "$MutName" ]]; then MutName="$Mutator" fi if [[ -z "$DisplayMutators" ]]; then DisplayMutators="$MutName" else DisplayMutators="$DisplayMutators, $MutName" fi done if [[ -n "$GameType" ]]; then DisplayGameType=${ModeNames[$GameType]} ; fi if [[ -n "$GameLength" ]]; then DisplayGameLength=${WaveNames[$GameLength]} ; fi if [[ -n "$GameDifficulty" ]]; then DisplayDifficulty=${DiffNames[$GameDifficulty]} ; fi if [[ -z "$DisplayMutators" ]] && [[ -z "$Mutators" ]]; then DisplayMutators='-' fi if [[ -z "$DisplayGameType" ]]; then DisplayGameType="$GameType" fi if [[ -z "$Args" ]]; then Args='-' fi if [[ "$GameType" == 'KFGameContent.KFGameInfo_WeeklySurvival' || \ "$GameType" == 'KFGameContent.KFGameInfo_Endless' || \ "$GameType" == 'KFGameContent.KFGameInfo_VersusSurvival' || \ "$GameType" == 'KFGameContent.KFGameInfo_Objective' ]]; then DisplayGameLength='-' fi if [[ "$GameType" == 'KFGameContent.KFGameInfo_WeeklySurvival' || \ "$DisplayGameType" == 'KFGameContent.KFGameInfo_VersusSurvival' ]]; then DisplayDifficulty='-' fi echo -e "$Instance:$IsEnabled:$IsRuning:$GamePort:$QueryPort:$WebAdminPort:$DisplayGameType:$DisplayGameLength:$DisplayDifficulty:$DisplayMutators:$Args:$Comment" } function instance_restart () # $*: [InstanceName[s]] { local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_enabled_instances) fi local ToRestartInstancesList="" for Instance in $InstanceList do if instance_exists "$Instance"; then ToRestartInstancesList+=" $Instance" else echo "Instance $Instance not exitst" fi done if [[ -n "$ToRestartInstancesList" ]]; then systemctl restart $(service_name "$ToRestartInstancesList") else echo "Nothing to do" fi } function instance_start () # $*: [InstanceName[s]] { local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_enabled_instances) fi local InactiveServiceList="" for Instance in $InstanceList do if instance_exists "$Instance"; then local Service=$(service_name "$Instance") if systemctl -q is-active $Service ; then echo "Instance $Instance already running - skip" else InactiveServiceList+=" $Service" fi else echo "Instance $Instance not exitst" fi done if [[ -n "$InactiveServiceList" ]]; then systemctl start $InactiveServiceList else echo "Nothing to do" fi } function instance_stop () # $*: [InstanceName[s]] { local InstanceList="$*" if [[ -z "$InstanceList" ]] ; then InstanceList=$(show_instances) fi local ToStopInstanceList="" for Instance in $InstanceList do if instance_exists "$Instance"; then ToStopInstanceList+=" $Instance" else echo "Instance $Instance not exitst" fi done if [[ -n "$ToStopInstanceList" ]]; then systemctl stop $(service_names "$ToStopInstanceList") else echo "Nothing to do" fi }