Kaynağa Gözat

All servers fully migrated to functions code

All servers have now been migrated to the new functions code. All
functions are now separated in there own file allowing to make quicker
changes to all servers code and simpler management of the code. For the
developer the code is now very scalable.
Daniel Gibbs 11 yıl önce
ebeveyn
işleme
8f549d689c

+ 96 - 568
Arma3/arma3server

@@ -4,7 +4,7 @@
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Contributor: Scarsz
 # Contributor: Scarsz
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -72,7 +72,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -84,15 +84,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -101,11 +102,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -120,10 +117,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -134,398 +129,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -535,96 +205,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -632,161 +243,71 @@ echo ""
 #
 #
 
 
 fn_glibcfix(){
 fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "contributions by Scarsz"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
-}
-
-fn_arma3config(){
-echo "Downloading CONFIG_Vanilla.cfg"
-echo "================================="
-sleep 1
-cd "${systemdir}"
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/Arma3/CONFIG_Vanilla.cfg
-echo "Creating ${servicename}.cfg config file."
-sleep 1
-cp -v CONFIG_Vanilla.cfg ${servercfgfullpath}
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-fn_arma3config
-sleep 1
-echo ""
+fn_serverconfig
 fn_header
 fn_header
-sleep 1
 fn_details
 fn_details
-sleep 1
 echo "================================="
 echo "================================="
 echo "Install Complete!"
 echo "Install Complete!"
 echo ""
 echo ""
@@ -795,6 +316,11 @@ echo "${selfname} start"
 echo ""
 echo ""
 }
 }
 
 
+fn_autoinstall(){
+autoinstall=1
+fn_install
+}
+
 case "$1" in
 case "$1" in
 	start)
 	start)
 		fn_startserver;;
 		fn_startserver;;
@@ -828,8 +354,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 103 - 589
BladeSymphony/bsserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 121114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,181 +247,82 @@ echo ""
 #
 #
 
 
 fn_glibcfix(){
 fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -846,8 +358,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 607
CounterStrike/csserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,196 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	touch "${systemdir}/listip.cfg"
-	touch "${systemdir}/banned.cfg"
-	{
-		echo -e "// Use this file to configure your DEDICATED server."
-		echo -e "// This config file is executed on server start."
-		echo -e ""
-		echo -e "// disable autoaim"
-		echo -e "sv_aim 0"
-		echo -e ""
-		echo -e "// disable clients' ability to pause the server"
-		echo -e "pausable 0"
-		echo -e ""
-		echo -e "// default server name. Change to \"Bob's Server\", etc."
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// maximum client movement speed "
-		echo -e "sv_maxspeed 320"
-		echo -e ""
-		echo -e "// 20 minute timelimit"
-		echo -e "mp_timelimit 20"
-		echo -e ""
-		echo -e "// cheats off"
-		echo -e "sv_cheats 0"
-		echo -e ""
-		echo -e "// load ban files"
-		echo -e "exec listip.cfg"
-		echo -e "exec banned.cfg"
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -860,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 607
CounterStrikeConditionZero/csczserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,196 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	touch "${systemdir}/listip.cfg"
-	touch "${systemdir}/banned.cfg"
-	{
-		echo -e "// Use this file to configure your DEDICATED server."
-		echo -e "// This config file is executed on server start."
-		echo -e ""
-		echo -e "// disable autoaim"
-		echo -e "sv_aim 0"
-		echo -e ""
-		echo -e "// disable clients' ability to pause the server"
-		echo -e "pausable 0"
-		echo -e ""
-		echo -e "// default server name. Change to \"Bob's Server\", etc."
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// maximum client movement speed "
-		echo -e "sv_maxspeed 320"
-		echo -e ""
-		echo -e "// 20 minute timelimit"
-		echo -e "mp_timelimit 20"
-		echo -e ""
-		echo -e "// cheats off"
-		echo -e "sv_cheats 0"
-		echo -e ""
-		echo -e "// load ban files"
-		echo -e "exec listip.cfg"
-		echo -e "exec banned.cfg"
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -860,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 97 - 647
CounterStrikeGlobalOffensive/csgoserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -93,7 +93,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -105,15 +105,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -122,11 +123,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -141,10 +138,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -155,398 +150,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -556,336 +226,109 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_csgoappidfix
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
-}
-
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
-fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
-}
-
-# Game Specific Functions
-
-fn_csgoappidfix(){
-if [ ! -f "${filesdir}/steam_appid.txt" ]; then
-	fn_printdots "Applying 730 steam_appid.txt Fix."
-	sleep 1
-	fn_printinfo "Applying 730 steam_appid.txt Fix."
-	sleep 1
-	echo -en "\n"
-	echo -n "730" >> ${filesdir}/steam_appid.txt
-fi
-}
-
-# Fixes the following error
-# Error parsing BotProfile.db - unknown attribute 'Rank"
-fn_botprofilefix(){
-if ! grep -q "//Rank" "${systemdir}/botprofile.db" ; then
-	echo "botprofile.db fix removes the following error from appearing on the console:"
-	echo "	Error parsing BotProfile.db - unknown attribute 'Rank"
-	sleep 1
-	fn_printdots "Applying botprofile.db fix."
-	sleep 1
-	fn_printinfo "Applying botprofile.db fix."
-	sleep 1
-	sed -i 's/\tRank/\t\/\/Rank/g' "${systemdir}/botprofile.db"
-	echo -en "\n"
-	echo ""
-fi
-}
-
-# Fixes errors simular to the following
-# Unknown command "cl_bobamt_vert"
-fn_valvetcfix(){
-if ! grep -q "//exec default" "${servercfgdir}/valve.rc" || ! grep -q "//exec joystick" "${servercfgdir}/valve.rc"; then
-	echo "valve.rc fix removes the following error from appearing on the console:"
-	echo "	Unknown command \"cl_bobamt_vert\""
-	sleep 1
-	fn_printdots "Applying valve.rc fix."
-	sleep 1
-	fn_printinfo "Applying valve.rc fix."
-	sleep 1
-	sed -i 's/exec default.cfg/\/\/exec default.cfg/g' "${servercfgdir}/valve.rc"
-	sed -i 's/exec joystick.cfg/\/\/exec joystick.cfg/g' "${servercfgdir}/valve.rc"
-	echo -en "\n"
-	echo ""
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-# Fixes errors simular to the following
-# http://forums.steampowered.com/forums/showthread.php?t=3170366
-fn_workshopmapfix(){
-if [ -f "${systemdir}/subscribed_collection_ids.txt" ]||[ -f "${systemdir}/subscribed_file_ids.txt" ]||[ -f "${systemdir}/ugc_collection_cache.txt" ]; then
-	echo "workshopmapfix fixes the following error:"
-	echo "	http://forums.steampowered.com/forums/showthread.php?t=3170366"
-	sleep 1
-	fn_printdots "Applying workshopmap fix."
-	sleep 1
-	fn_printinfo "Applying workshopmap fix."
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
 	sleep 1
 	sleep 1
-	rm -f "${systemdir}/subscribed_collection_ids.txt"
-	rm -f "${systemdir}/subscribed_file_ids.txt"
-	rm -f "${systemdir}/ugc_collection_cache.txt"
-	echo -en "\n"
 	echo ""
 	echo ""
 fi
 fi
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
+fn_csgofix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
-echo "================================="
-sleep 1
-read -p "Enter server name: " servername
-read -p "Enter rcon password: " rconpass
-sleep 1
-echo "Creating server.cfg."
-touch "${defaultcfg}"
-echo "exec ${servicename}.cfg" > "${defaultcfg}"
-sleep 1
-echo "Creating ${servicename}.cfg config file."
-touch "${servercfgfullpath}"
-{
-	echo -e "// Server Name"
-	echo -e "hostname \"${servername}\""
-	echo -e ""
-	echo -e "// RCON Password"
-	echo -e "rcon_password \"${rconpass}\""
-	echo -e ""
-	echo -e "// Server Password"
-	echo -e "sv_password \"\""
-	echo -e ""
-	echo -e "// Server Logging"
-	echo -e "log on"
-	echo -e "sv_logbans 1"
-	echo -e "sv_logecho 1"
-	echo -e "sv_logfile 1"
-	echo -e "sv_log_onefile 0"
-}|tee "${servercfgfullpath}" > /dev/null 2>&1
-sleep 1
-echo ""
-echo "Applying ${gamename} Fixes"
-echo "================================="
-fn_botprofilefix
-fn_valvetcfix
-fn_workshopmapfix
+fn_serverconfig
+fn_csgofix
 fn_header
 fn_header
-sleep 1
 fn_details
 fn_details
-sleep 1
 echo "================================="
 echo "================================="
 echo "Install Complete!"
 echo "Install Complete!"
 echo ""
 echo ""
@@ -894,6 +337,11 @@ echo "${selfname} start"
 echo ""
 echo ""
 }
 }
 
 
+fn_autoinstall(){
+autoinstall=1
+fn_install
+}
+
 case "$1" in
 case "$1" in
 	start)
 	start)
 		fn_startserver;;
 		fn_startserver;;
@@ -927,8 +375,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 583
CounterStrikeSource/cssserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,172 +247,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -837,8 +352,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 101 - 611
DayOfDefeat/dodserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -31,7 +31,7 @@ parms="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientpor
 #### Advanced Variables ####
 #### Advanced Variables ####
 
 
 # Steam
 # Steam
-appid="90 -beta beta +app_set_config 90 mod dod"
+appid="90 +app_set_config 90 mod dod"
 
 
 # Server Details
 # Server Details
 servicename="dod-server"
 servicename="dod-server"
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,199 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
-fn_steaminstall
-fn_steaminstall
-fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	touch "${systemdir}/listip.cfg"
-	touch "${systemdir}/banned.cfg"
-	{
-		echo -e "// Use this file to configure your DEDICATED server."
-		echo -e "// This config file is executed on server start."
-		echo -e ""
-		echo -e "// disable autoaim"
-		echo -e "sv_aim 0"
-		echo -e ""
-		echo -e "// disable clients' ability to pause the server"
-		echo -e "pausable 0"
-		echo -e ""
-		echo -e "// default server name. Change to \"Bob's Server\", etc."
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// maximum client movement speed "
-		echo -e "sv_maxspeed 320"
-		echo -e ""
-		echo -e "// 20 minute timelimit"
-		echo -e "mp_timelimit 20"
-		echo -e ""
-		echo -e "// cheats off"
-		echo -e "sv_cheats 0"
-		echo -e ""
-		echo -e "// load ban files"
-		echo -e "exec listip.cfg"
-		echo -e "exec banned.cfg"
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -863,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 591
DayOfDefeatSource/dodsserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,277 +209,114 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
-fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
-}
-
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -845,8 +352,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 103 - 623
FistfulOfFrags/fofserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,215 +247,82 @@ echo ""
 #
 #
 
 
 fn_glibcfix(){
 fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-		echo -e "//Fistful of Frags"
-		echo -e ""
-		echo -e "//// Game Modes"
-		echo -e "// 1 = Shootout"
-		echo -e "// 2 = Teamplay/Objectives"
-		echo -e ""
-		echo -e "fof_sv_currentmode 1 "
-		echo -e ""
-		echo -e ""
-		echo -e "//// Teamplay"
-		echo -e "// 0 = Free-for-all"
-		echo -e "// 1 = Team Deathmatch"
-		echo -e ""
-		echo -e "mp_teamplay 0"
-		echo -e ""
-		echo -e ""
-		echo -e "//// Friendly Fire"
-		echo -e "// 0 = Friendly fire disabled"
-		echo -e "// 1 = Friendly fire enabled"
-		echo -e ""
-		echo -e "mp_friendlyfire 0"
-		echo -e ""
-		echo -e ""
-		echo -e "//// Team numbers"
-		echo -e "// 2 = Vigilantes & Desperados"
-		echo -e "// 3 = Vigilantes, Desperados & Bandidos"
-		echo -e "// 4 = Vigilantes, Desperados, Bandidos & Rangers"
-		echo -e ""
-		echo -e "fof_sv_maxteams 4"
-		echo -e ""
-		echo -e "//// Scrable Teams"
-		echo -e "// Teams get scrambled when 75% of kills come from same team"
-		echo -e "fof_sv_scrambleteams 1"
-		echo -e "fof_sv_scrambleteams_maxkillratio 0.75"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -880,8 +358,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 103 - 661
GarrysMod/gmodserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -81,7 +81,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -93,15 +93,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -110,11 +111,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -129,10 +126,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -143,398 +138,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -544,96 +214,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -641,253 +252,82 @@ echo ""
 #
 #
 
 
 fn_glibcfix(){
 fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-		echo -e "lua_log_sv 0"
-		echo -e "sv_rcon_banpenalty 0"
-		echo -e "sv_rcon_maxfailures 20"
-		echo -e "sv_rcon_minfailures 20"
-		echo -e "sv_rcon_minfailuretime 20"
-		echo -e ""
-		echo -e "// Network Settings"
-		echo -e "sv_downloadurl \"\""
-		echo -e "sv_loadingurl \"\""
-		echo -e "net_maxfilesize 64"
-		echo -e "sv_maxrate 40000"
-		echo -e "sv_minrate 40000"
-		echo -e "sv_maxupdaterate 66"
-		echo -e "sv_minupdaterate 10"
-		echo -e "sv_maxcmdrate 60"
-		echo -e "sv_mincmdrate 10"
-		echo -e ""
-		echo -e "// Server Settings"
-		echo -e "sv_airaccelerate 100"
-		echo -e "sv_gravity 600"
-		echo -e "sv_allow_wait_command 0"
-		echo -e "sv_allow_voice_from_file 0"
-		echo -e "sv_turbophysics 0"
-		echo -e "sv_max_usercmd_future_ticks 12"
-		echo -e "gmod_physiterations 2"
-		echo -e "sv_client_min_interp_ratio 1"
-		echo -e "sv_client_max_interp_ratio 2"
-		echo -e "think_limit 20"
-		echo -e "sv_region 0"
-		echo -e "sv_noclipspeed 5"
-		echo -e "sv_noclipaccelerate 5"
-		echo -e "sv_lan 0"
-		echo -e "sv_alltalk 1"
-		echo -e "sv_contact youremail@changeme.com"
-		echo -e "sv_cheats 0"
-		echo -e "sv_allowcslua 0"
-		echo -e "sv_pausable 0"
-		echo -e "sv_filterban 1"
-		echo -e "sv_forcepreload 1"
-		echo -e "sv_footsteps 1"
-		echo -e "sv_voiceenable 1"
-		echo -e "sv_voicecodec vaudio_speex"
-		echo -e "sv_timeout 120"
-		echo -e "sv_deltaprint 0"
-		echo -e "sv_allowupload 0"
-		echo -e "sv_allowdownload 0"
-		echo -e ""
-		echo -e "// Sandbox Settings"
-		echo -e "sbox_noclip 0"
-		echo -e "sbox_godmode 0"
-		echo -e "sbox_weapons 0"
-		echo -e "sbox_plpldamage 0"
-		echo -e "sbox_maxprops 100"
-		echo -e "sbox_maxragdolls 50"
-		echo -e "sbox_maxnpcs 10"
-		echo -e "sbox_maxballoons 10"
-		echo -e "sbox_maxeffects 0"
-		echo -e "sbox_maxdynamite 0"
-		echo -e "sbox_maxlamps 5"
-		echo -e "sbox_maxthrusters 20"
-		echo -e "sbox_maxwheels 20"
-		echo -e "sbox_maxhoverballs 20"
-		echo -e "sbox_maxvehicles 1"
-		echo -e "sbox_maxbuttons 20"
-		echo -e "sbox_maxemitters 0"
-		echo -e "sbox_maxspawners 0"
-		echo -e "sbox_maxturrets 0"
-		echo -e ""
-		echo -e "// Misc Config"
-		echo -e "exec banned_user.cfg"
-		echo -e "exec banned_ip.cfg"
-		echo -e "heartbeat"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -923,8 +363,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 583
HalfLife2Deathmatch/hl2dmserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,172 +247,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -837,8 +352,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 610
HalfLifeDeathmatchClassic/hldmcserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,199 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
-fn_steaminstall
-fn_steaminstall
-fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	touch "${systemdir}/listip.cfg"
-	touch "${systemdir}/banned.cfg"
-	{
-		echo -e "// Use this file to configure your DEDICATED server."
-		echo -e "// This config file is executed on server start."
-		echo -e ""
-		echo -e "// disable autoaim"
-		echo -e "sv_aim 0"
-		echo -e ""
-		echo -e "// disable clients' ability to pause the server"
-		echo -e "pausable 0"
-		echo -e ""
-		echo -e "// default server name. Change to \"Bob's Server\", etc."
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// maximum client movement speed "
-		echo -e "sv_maxspeed 320"
-		echo -e ""
-		echo -e "// 20 minute timelimit"
-		echo -e "mp_timelimit 20"
-		echo -e ""
-		echo -e "// cheats off"
-		echo -e "sv_cheats 0"
-		echo -e ""
-		echo -e "// load ban files"
-		echo -e "exec listip.cfg"
-		echo -e "exec banned.cfg"
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -863,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 106 - 592
Insurgency/insserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,278 +209,120 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
-fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
-}
-
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_glibcfix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -846,8 +358,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 96 - 561
JustCause2/jc2server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -70,7 +70,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -82,15 +82,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -99,11 +100,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -118,10 +115,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -132,398 +127,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -533,245 +203,103 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
-fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
-}
-
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+fn_glibcfix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_jc2config(){
-echo "Copying default_config.lua"
-echo "================================="
-sleep 1
-cd "${filesdir}"
-cp -v default_config.lua config.lua
-sleep 1
-echo ""	
+fn_loginstall(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
+fn_glibcfix
 fn_loginstall
 fn_loginstall
-fn_jc2config
 fn_getquery
 fn_getquery
-fn_glibcfix
-sleep 1
-echo ""
+fn_serverconfig
 fn_header
 fn_header
-sleep 1
 fn_details
 fn_details
-sleep 1
 echo "================================="
 echo "================================="
 echo "Install Complete!"
 echo "Install Complete!"
 echo ""
 echo ""
@@ -780,6 +308,11 @@ echo "${selfname} start"
 echo ""
 echo ""
 }
 }
 
 
+fn_autoinstall(){
+autoinstall=1
+fn_install
+}
+
 case "$1" in
 case "$1" in
 	start)
 	start)
 		fn_startserver;;
 		fn_startserver;;
@@ -813,8 +346,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 110 - 612
KillingFloor/kfserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -70,7 +70,7 @@ parms="server ${defaultmap}?game=KFmod.KFGameType?VACSecured=true -nohomedir ini
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -82,15 +82,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -99,11 +100,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -118,10 +115,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -132,398 +127,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -533,299 +203,125 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
-fn_kfcompressmaps(){
-fn_rootcheck
-clear
-echo "${gamename} Map Compressor"
-echo "============================"
-echo "Will compress all maps in:"
-echo ""
-pwd
-echo ""
-echo "Compressed maps saved to:"
-echo ""
-echo "${compressedmapsdir}"
-echo ""
-while true; do
-	read -p "Start compression [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-mkdir -pv "${compressedmapsdir}" > /dev/null 2>&1
-rm -rfv "${filesdir}/Maps/*.uz2"
-cd "${systemdir}"
-for map in `ls "${filesdir}/Maps"`; do
-	./ucc-bin compress ../Maps/${map} --nohomedir
-done
-mv -fv "${filesdir}/Maps/*.uz2" "${compressedmapsdir}"
+fn_unreal2compressmaps(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
+fn_kffix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_kffix
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	echo "Copying "${defaultcfg}" to ${systemdir}/${ini}"
-	cp "${defaultcfg}" "${systemdir}/${ini}"
-	sleep 1
-	echo "Applying WebAdmin ROOst.css fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=585435&postcount=13"
-	sed -i 's/none}/none;/g' ${filesdir}/Web/ServerAdmin/ROOst.css
-	sed -i 's/underline}/underline;/g' ${filesdir}/Web/ServerAdmin/ROOst.css
-	sleep 1
-	echo "Applying WebAdmin CharSet fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=442340&postcount=1"
-	sed -i 's/CharSet="iso-8859-1"/CharSet="utf-8"/g' ${systemdir}/UWeb.int
-	sleep 1
-	echo "Setting WebAdmin username and password"
-	sed -i 's/AdminName=/AdminName=admin/g' ${systemdir}/${ini}
-	sed -i 's/AdminPassword=/AdminPassword=admin/g' ${systemdir}/${ini}
-	sleep 1
-	echo "Enabling WebAdmin"
-	sed -i 's/bEnabled=False/bEnabled=True/g' ${systemdir}/${ini}
-	sleep 1
-	echo "Forcing server to start to get ports/server name to display correctly"
-	sleep 1
-	cd "${rootdir}"
-	${selfname} start
-	sleep 5
-	${selfname} restart
-	sleep 5
-	${selfname} stop
-	sleep 5
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -861,10 +357,12 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	map-compressor)
 	map-compressor)
-		fn_kfcompressmaps;;
+		fn_unreal2compressmaps;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install|map-compressor}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 101 - 595
Left4Dead/l4dserver

@@ -2,8 +2,9 @@
 # Left 4 Dead
 # Left 4 Dead
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
+# Contributor: Summit Singh Thakur
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,281 +209,114 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
-fn_l4ddeps(){
-echo "Copying libstdc++.so.6"
-echo "================================="
-sleep 1
-cd "${filesdir}"
-cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}"
-sleep 1
-echo ""
-}
-
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "contributions by Summit Singh Thakur"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_l4ddeps
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -848,8 +352,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 583
Left4Dead2/l4d2server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,172 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -836,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 101 - 562
NaturalSelection2/ns2server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,247 +208,114 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
-fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
-}
-
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_glibcfix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+fn_header
+fn_details
+echo "================================="
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -814,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 103 - 589
NoMoreRoomInHell/nmrihserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,181 +247,82 @@ echo ""
 #
 #
 
 
 fn_glibcfix(){
 fn_glibcfix(){
-if [ ! -f ${rootdir}/functions/fn_glibcfix ]; then
-	functionfile="fn_glibcfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_glibcfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
+fn_glibcfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-fn_glibcfix
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// Server Name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// RCON Password"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -846,8 +358,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 110 - 612
RedOrchestra/roserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -66,7 +66,7 @@ parms="server ${defaultmap}?game=ROGame.ROTeamGame?VACSecured=true -nohomedir in
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -78,15 +78,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -95,11 +96,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -114,10 +111,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -128,398 +123,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -529,299 +199,125 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
-fn_kfcompressmaps(){
-fn_rootcheck
-clear
-echo "${gamename} Map Compressor"
-echo "============================"
-echo "Will compress all maps in:"
-echo ""
-pwd
-echo ""
-echo "Compressed maps saved to:"
-echo ""
-echo "${compressedmapsdir}"
-echo ""
-while true; do
-	read -p "Start compression [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-mkdir -pv "${compressedmapsdir}" > /dev/null 2>&1
-rm -rfv "${filesdir}/Maps/*.uz2"
-cd "${systemdir}"
-for map in `ls "${filesdir}/Maps"`; do
-	./ucc-bin compress ../Maps/${map} --nohomedir
-done
-mv -fv "${filesdir}/Maps/*.uz2" "${compressedmapsdir}"
+fn_unreal2compressmaps(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
+fn_rofix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_rofix
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	echo "Copying "${defaultcfg}" to ${systemdir}/${ini}"
-	cp "${defaultcfg}" "${systemdir}/${ini}"
-	sleep 1
-	echo "Applying WebAdmin ROOst.css fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=585435&postcount=13"
-	sed -i 's/none}/none;/g' ${filesdir}/Web/ServerAdmin/ROOst.css
-	sed -i 's/underline}/underline;/g' ${filesdir}/Web/ServerAdmin/ROOst.css
-	sleep 1
-	echo "Applying WebAdmin CharSet fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=442340&postcount=1"
-	sed -i 's/CharSet="iso-8859-1"/CharSet="utf-8"/g' ${systemdir}/uweb.int
-	sleep 1
-	echo "Setting WebAdmin username and password"
-	sed -i 's/AdminName=/AdminName=admin/g' ${systemdir}/${ini}
-	sed -i 's/AdminPassword=/AdminPassword=ropass/g' ${systemdir}/${ini}
-	sleep 1
-	echo "Enabling WebAdmin"
-	sed -i 's/bEnabled=False/bEnabled=True/g' ${systemdir}/${ini}
-	sleep 1
-	echo "Forcing server to start to get ports/server name to display correctly"
-	sleep 1
-	cd "${rootdir}"
-	${selfname} start
-	sleep 5
-	${selfname} restart
-	sleep 5
-	${selfname} stop
-	sleep 5
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -857,10 +353,12 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	map-compressor)
 	map-compressor)
-		fn_kfcompressmaps;;
+		fn_unreal2compressmaps;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install|map-compressor}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 583
TeamFortress2/tf2server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -88,15 +88,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -105,11 +106,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -124,10 +121,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -138,398 +133,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -539,96 +209,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -636,172 +247,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	{
-		echo -e "// server name"
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -837,8 +352,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 100 - 610
TeamFortressClassic/tfcserver

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -87,15 +87,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -104,11 +105,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -123,10 +120,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -137,398 +132,73 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_updateserver(){
 fn_updateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printdots "Updating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Updating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Updating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_validateserver(){
 fn_validateserver(){
-fn_rootcheck
-fn_syscheck
-fn_printwarn "Validating may overwrite some customised files."
-sleep 1
-echo -en "\n"
-echo -en "https://developer.valvesoftware.com/wiki/SteamCMD#Validate"
-sleep 5
-echo -en "\n"
-fn_printdots "Validating ${servicename}: ${servername}"
-sleep 1
-fn_printok "Validating ${servicename}: ${servername}"
-sleep 1
-fn_scriptlog "Validating ${servername}"
-cd "${rootdir}"
-cd "steamcmd"
-./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -538,96 +208,37 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 #
 #
@@ -635,199 +246,76 @@ echo ""
 #
 #
 
 
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamdl(){
 fn_steamdl(){
-echo "Installing SteamCMD"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "steamcmd"
-sleep 1
-cd "steamcmd"
-if [ ! -f steamcmd.sh ]; then
-	wget -nv -N http://media.steampowered.com/client/steamcmd_linux.tar.gz
-	tar --verbose -zxf steamcmd_linux.tar.gz
-	rm -v steamcmd_linux.tar.gz
-	chmod +x steamcmd.sh
-	sleep 1
-else
-	echo ""
-	echo "Steam already installed!"
-fi
-sleep 1
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steaminstall(){
 fn_steaminstall(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${rootdir}/steamcmd"
-STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit
-echo ""
-echo "================================="
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_steamfix(){
 fn_steamfix(){
-if [ ! -f ${rootdir}/functions/fn_steamfix ]; then
-	functionfile="fn_steamfix"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_steamfix
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_steamdl
 fn_steamdl
 fn_steaminstall
 fn_steaminstall
-fn_steaminstall
-fn_steaminstall
-fn_steaminstall
 fn_steamfix
 fn_steamfix
 fn_loginstall
 fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	read -p "Enter server name: " servername
-	read -p "Enter rcon password: " rconpass
-	sleep 1
-	echo "Creating server.cfg."
-	touch "${defaultcfg}"
-	echo "exec ${servicename}.cfg" > "${defaultcfg}"
-	sleep 1
-	echo "Creating ${servicename}.cfg config file."
-	touch "${servercfgfullpath}"
-	touch "${systemdir}/listip.cfg"
-	touch "${systemdir}/banned.cfg"
-	{
-		echo -e "// Use this file to configure your DEDICATED server."
-		echo -e "// This config file is executed on server start."
-		echo -e ""
-		echo -e "// disable autoaim"
-		echo -e "sv_aim 0"
-		echo -e ""
-		echo -e "// disable clients' ability to pause the server"
-		echo -e "pausable 0"
-		echo -e ""
-		echo -e "// default server name. Change to \"Bob's Server\", etc."
-		echo -e "hostname \"${servername}\""
-		echo -e ""
-		echo -e "// maximum client movement speed "
-		echo -e "sv_maxspeed 320"
-		echo -e ""
-		echo -e "// 20 minute timelimit"
-		echo -e "mp_timelimit 20"
-		echo -e ""
-		echo -e "// cheats off"
-		echo -e "sv_cheats 0"
-		echo -e ""
-		echo -e "// load ban files"
-		echo -e "exec listip.cfg"
-		echo -e "exec banned.cfg"
-		echo -e ""
-		echo -e "// rcon passsword"
-		echo -e "rcon_password \"${rconpass}\""
-		echo -e ""
-		echo -e "// Server Password"
-		echo -e "sv_password \"\""
-		echo -e ""
-		echo -e "// Server Logging"
-		echo -e "log on"
-		echo -e "sv_logbans 1"
-		echo -e "sv_logecho 1"
-		echo -e "sv_logfile 1"
-		echo -e "sv_log_onefile 0"
-	}|tee "${servercfgfullpath}" > /dev/null 2>&1
-	sleep 1
-	echo ""
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
+}
+
+fn_autoinstall(){
+autoinstall=1
+fn_install
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -863,8 +351,10 @@ case "$1" in
 		fn_debugserver;;
 		fn_debugserver;;
 	install)
 	install)
 		fn_install;;
 		fn_install;;
+	auto-install)
+		fn_autoinstall;;
 	*)
 	*)
-	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}"
+	echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install|auto-install}"
 	exit 1;;
 	exit 1;;
 esac
 esac
 exit
 exit

+ 99 - 649
UnrealTournament2004/ut2k4server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -59,7 +59,7 @@ parms="server ${defaultmap}?game=XGame.xDeathMatch -nohomedir ini=${ini} log=${g
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -71,15 +71,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -88,11 +89,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -107,10 +104,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -121,366 +116,63 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -490,362 +182,120 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
-fn_ut2k4compressmaps(){
-fn_rootcheck
-clear
-echo "${gamename} Map Compressor"
-echo "============================"
-echo "Will compress all maps in:"
-echo ""
-pwd
-echo ""
-echo "Compressed maps saved to:"
-echo ""
-echo "${compressedmapsdir}"
-echo ""
-while true; do
-	read -p "Start compression [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-mkdir -pv "${compressedmapsdir}" > /dev/null 2>&1
-rm -rfv "${filesdir}/Maps/*.uz2"
-cd "${systemdir}"
-for map in `ls "${filesdir}/Maps"`; do
-	if [ `getconf LONG_BIT` = "64" ]; then
-		./ucc-bin-linux-amd64 compress ../Maps/${map} --nohomedir
-	else
-		./ucc-bin compress ../Maps/${map} --nohomedir
-	fi
-done
-mv -fv "${filesdir}/Maps/*.uz2" "${compressedmapsdir}"
+fn_unreal2compressmaps(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
+fn_ut2k4fix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_ut2k4filesdl(){
 fn_ut2k4filesdl(){
-echo "Downloading Server Files"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "${filesdir}"
-cd "${filesdir}"
-if [ ! -f dedicatedserver3339-bonuspack.zip ]; then
-	wget -nv -N http://downloads.unrealadmin.org/UT2004/Server/dedicatedserver3339-bonuspack.zip
-else
-	echo "dedicatedserver3339-bonuspack.zip already downloaded!"
-fi
-echo "Running MD5 checksum to verify the file"
-sleep 1
-echo "MD5 checksum: d3f28c5245c4c02802d48e4f0ffd3e34"
-md5check=$(md5sum dedicatedserver3339-bonuspack.zip|awk '{print $1;}')
-echo "File returned: ${md5check}"
-if [ "${md5check}" != "d3f28c5245c4c02802d48e4f0ffd3e34" ]; then
-	echo "MD5 checksum: FAILED!"
-	read -p "Retry download? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv dedicatedserver3339-bonuspack.zip; fn_ut2k4filesdl;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-else
-	echo "MD5 checksum: PASSED"
-fi
-if [ ! -f ut2004-lnxpatch3369-2.tar.bz2 ]; then
-	wget -nv -N http://downloads.unrealadmin.org/UT2004/Patches/Linux/ut2004-lnxpatch3369-2.tar.bz2
-else
-	echo "ut2004-lnxpatch3369-2.tar.bz2 already downloaded!"
-fi
-echo "Running MD5 checksum to verify the file"
-sleep 1
-echo "MD5 checksum: 0fa447e05fe5a38e0e32adf171be405e"
-md5check=$(md5sum ut2004-lnxpatch3369-2.tar.bz2|awk '{print $1;}')
-echo "File returned: ${md5check}"
-if [ "${md5check}" != "0fa447e05fe5a38e0e32adf171be405e" ]; then
-	echo "MD5 checksum: FAILED!"
-	read -p "Retry download? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv ut2004-lnxpatch3369-2.tar.bz2; fn_ut2k4filesdl;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-else
-	echo "MD5 checksum: PASSED"
-fi
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_ut2k4key(){
 fn_ut2k4key(){
-echo "Enter ${gamename} CD Key"
-echo "================================="
-sleep 1
-echo "To get your server listed on the Master Server list"
-echo "you must get a free CD key. Get a key here:"
-echo "http://www.unrealtournament.com/ut2004server/cdkey.php"
-echo ""
-echo "Once you have the key enter it below"
-echo -n "KEY: "
-read CODE
-echo ""\""CDKey"\""="\""${CODE}"\""" > "${systemdir}/cdkey"
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_ut2k4install(){
 fn_ut2k4install(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${filesdir}"
-echo "Extracting dedicatedserver3339-bonuspack.zip"
-sleep 1
-unzip dedicatedserver3339-bonuspack.zip
-echo "Extracting ut2004-lnxpatch3369-2.tar.bz2"
-sleep 1
-tar -xvjf ut2004-lnxpatch3369-2.tar.bz2 UT2004-Patch/ --strip-components=1
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-while true; do
-	read -p "Remove ut2004-lnxpatch3369-2.tar.bz2? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv ut2004-lnxpatch3369-2.tar.bz2; break;;
-	[Nn]* ) break;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-while true; do
-	read -p "Remove dedicatedserver3339-bonuspack.zip? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv dedicatedserver3339-bonuspack.zip; break;;
-	[Nn]* ) break;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_ut2k4filesdl
 fn_ut2k4filesdl
 fn_ut2k4install
 fn_ut2k4install
 fn_ut2k4key
 fn_ut2k4key
-fn_utloginstall
+fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_ut2k4fix
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	echo "Copying "${defaultcfg}" to ${systemdir}/${ini}"
-	cp "${defaultcfg}" "${systemdir}/${ini}"
-	sleep 1
-	echo "Applying WebAdmin ut2003.css fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=585435&postcount=13"
-	sed -i 's/none}/none;/g' "${filesdir}/Web/ServerAdmin/ut2003.css"
-	sed -i 's/underline}/underline;/g' "${filesdir}/Web/ServerAdmin/ut2003.css"
-	sleep 1
-	echo "Applying WebAdmin CharSet fix!"
-	echo "http://forums.tripwireinteractive.com/showpost.php?p=442340&postcount=1"
-	sed -i 's/CharSet="iso-8859-1"/CharSet="utf-8"/g' "${systemdir}/UWeb.int"
-	sleep 1
-	echo "Setting WebAdmin username and password"
-	sed -i 's/AdminName=/AdminName=admin/g' "${systemdir}/${ini}"
-	sed -i 's/AdminPassword=/AdminPassword=admin/g' "${systemdir}/${ini}"
-	sleep 1
-	echo "Enabling WebAdmin"
-	sed -i 's/bEnabled=False/bEnabled=True/g' "${systemdir}/${ini}"
-	sleep 1
-	echo "Setting WebAdmin port to 8077"
-	sed -i 's/ListenPort=80/ListenPort=8077/g' "${systemdir}/${ini}"
-	sleep 1
-	echo "Forcing server to start to get ports/server name to display correctly"
-	sleep 1
-	cd "${rootdir}"
-	${selfname} start
-	sleep 5
-	${selfname} restart
-	sleep 5
-	${selfname} stop
-	sleep 5
-	fn_header
-	sleep 1
-	fn_details
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -870,7 +320,7 @@ case "$1" in
 	install)
 	install)
 		fn_install;;
 		fn_install;;
 	map-compressor)
 	map-compressor)
-		fn_ut2k4compressmaps;;
+		fn_unreal2compressmaps;;
 	*)
 	*)
 	echo "Usage: $0 {start|stop|restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
 	echo "Usage: $0 {start|stop|restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
 	exit 1;;
 	exit 1;;

+ 96 - 627
UnrealTournament99/ut99server

@@ -3,7 +3,7 @@
 # Server Management Script
 # Server Management Script
 # Author: Daniel Gibbs
 # Author: Daniel Gibbs
 # Website: http://danielgibbs.co.uk
 # Website: http://danielgibbs.co.uk
-# Version: 231114
+# Version: 011214
 
 
 #### Variables ####
 #### Variables ####
 
 
@@ -56,7 +56,7 @@ parms="server ${defaultmap}.unr ini=${systemdir}/${ini}"
 # what you are doing
 # what you are doing
 
 
 fn_scriptlog(){
 fn_scriptlog(){
-	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog}
+	echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> "${scriptlog}"
 }
 }
 
 
 # [ FAIL ]
 # [ FAIL ]
@@ -68,15 +68,16 @@ fn_printfailnl(){
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@"
 }
 }
 
 
+# [  OK  ]
 fn_printok(){
 fn_printok(){
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
-# [  OK  ]
 fn_printoknl(){
 fn_printoknl(){
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;32m  OK  \e[0;39m] $@"
 }
 }
 
 
+# [ INFO ]
 fn_printinfo(){
 fn_printinfo(){
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
@@ -85,11 +86,7 @@ fn_printinfonl(){
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
     echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
 }
 }
 
 
-# [ INFO ]
-fn_printokinfonl(){
-    echo -e "\r\033[K[\e[0;36m INFO \e[0;39m] $@"
-}
-
+# [ WARN ]
 fn_printwarn(){
 fn_printwarn(){
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 	echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@"
 }
 }
@@ -104,10 +101,8 @@ fn_printdots(){
 }
 }
 
 
 fn_rootcheck(){
 fn_rootcheck(){
-if [ `whoami` = "root" ]; then
-	fn_printfailnl "Script will not run as root!"
-	exit
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_syscheck(){
 fn_syscheck(){
@@ -118,366 +113,63 @@ fi
 }
 }
 
 
 fn_autoip(){
 fn_autoip(){
-# Identifies the server interface IP
-# If multiple interfaces this will need to be set manually
-getip=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0)
-getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0|wc -l)
-if [ "${ip}" == "0.0.0.0" ]||[ "${ip}" == "" ]; then
-	if [ "${getipwc}" -ge "2" ]; then
-		fn_printwarn "Multiple active network interfaces.\n\n"
-		echo -en "Manually specify the IP you want to use within the ${selfname} script.\n"
-		echo -en "Set ip=\"0.0.0.0\" to one of the following:\n"
-		echo -en "${getip}\n"
-		exit
-	else
-		ip=${getip}
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_logmanager(){
 fn_logmanager(){
-if [ ! -e "${consolelog}" ]; then
-	touch "${consolelog}"
-fi
-# log manager will active if finds logs older than ${logdays}
-if [ `find "${scriptlogdir}"/* -mtime +${logdays}|wc -l` -ne "0" ]; then
-	fn_printdots "Starting log cleaner"
-	sleep 1
-	fn_printok "Starting log cleaner"
-	fn_scriptlog "Starting log cleaner"
-	sleep 1
-	echo -en "\n"
-	fn_printinfo "Removing logs older than ${logdays} days"
-	fn_scriptlog "Removing logs older than ${logdays} days"
-	sleep 1
-	echo -en "\n"
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}"
-	if [ "${engine}" == "unreal2" ]; then
-		gamecount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	fi
-	scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l)
-	consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l)
-	count=$((${scriptcount} + ${consolecount}))
-	if [ "${engine}" == "unreal2" ]; then
-		count=$((${scriptcount} + ${consolecount} + ${gamecount}))
-	else
-		count=$((${scriptcount} + ${consolecount}))
-	fi
-	if [ "${engine}" == "unreal2" ]; then
-		find "${gamelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fi
-	find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \;
-	find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \;
-	fn_printok "Log cleaner removed ${count} log files"
-	fn_scriptlog "Log cleaner removed ${count} log files"
-	sleep 1
-	echo -en "\n"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_debugserver(){
 fn_debugserver(){
-if [ ! -f ${rootdir}/functions/fn_debugserver ]; then
-	functionfile="fn_debugserver"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_debugserver
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_console(){
 fn_console(){
-fn_rootcheck
-fn_syscheck
-echo ""
-echo "${gamename} Console"
-echo "============================"
-echo ""
-echo "Press \"CTRL+b d\" to exit console"
-echo -e "\e[0;31mWARNING!\e[0;39m Do NOT press CTRL+c to exit"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-fn_printdots "Starting ${servicename} console"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printoknl "Starting ${servicename} console"
-	fn_scriptlog "Console accessed"
-	sleep 1
-	tmux attach-session -t ${servicename}
-else
-	fn_printfailnl "Starting ${servicename} console: ${servername} not running"
-	sleep 1
-	while true; do
-		read -p "Do you want to start the server? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_startserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_backupserver(){
 fn_backupserver(){
-fn_rootcheck
-fn_syscheck
-backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')"
-echo ""
-echo "${gamename} Backup"
-echo "============================"
-echo ""
-echo "The following backup will be created."
-echo ""
-echo "${backupdir}/${backupname}.tar.gz"
-echo ""
-while true; do
-	read -p "Continue? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 1 ]; then
-	echo -e "\e[0;31mWARNING!\e[0;39m ${servicename} is currently running"
-	while true; do
-		read -p "Would you like to stop ${servicename} while running the backup? [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_stopserver; break;;
-		[Nn]* ) break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-fi
-fn_printdots "Starting backup ${servicename}: ${servername}"
-sleep 1
-fn_printok "Starting backup ${servicename}: ${servername}"
-fn_scriptlog "Backup started"
-sleep 1
-echo -en "\n"
-cd "${rootdir}"
-mkdir -pv "${backupdir}" > /dev/null 2>&1
-tar -cvzf "${backupdir}/${backupname}.tar.gz" --exclude "${backupdir}" *
-echo -en "\r\033[K${servicename} Backup complete"
-fn_scriptlog "Backup complete"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_distro(){
 fn_distro(){
-arch=$(uname -m)
-kernel=$(uname -r)
-if [ -f /etc/lsb-release ]; then
-	os=$(lsb_release -s -d)
-elif [ -f /etc/debian_version ]; then
-	os="Debian $(cat /etc/debian_version)"
-elif [ -f /etc/redhat-release ]; then
-	os=$(cat /etc/redhat-release)
-else
-	os="$(uname -s) $(uname -r)"
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_uptime(){
 fn_uptime(){
-uptime=$(</proc/uptime)
-uptime=${uptime%%.*}
-minutes=$(( uptime/60%60 ))
-hours=$(( uptime/60/60%24 ))
-days=$(( uptime/60/60/24 ))
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_load(){
 fn_load(){
-load=$(uptime|awk -F 'load average' '{ print $2 }')
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailnotification(){
 fn_emailnotification(){
-fn_distro
-fn_uptime
-fn_load
-{
-	echo -e "========================================\n${servicename} details\n========================================\n"
-	echo -e "Service: ${servicename}"
-	echo -e "Server: ${servername}"
-	echo -e "Game: ${gamename}"
-	echo -e "Failure reason: ${failurereason}"
-	echo -e "Action Taken: ${actiontaken}\n"
-	echo -e "========================================\nServer details\n========================================\n"
-	echo -e "Date: $(date)"
-	echo -e "Distro: ${os}"
-	echo -e "Arch: ${arch}"
-	echo -e "Kernel: ${kernel}"
-	echo -e "Hostname: $HOSTNAME"
-	echo -e "Uptime: ${days}d, ${hours}h, ${minutes}m"
-	echo -e "Avg Load${load}\n"
-	echo -e "========================================\nLogs\n========================================\n"
-	echo -e "Script log\n===================\n"
-}|tee "${scriptlogdir}/${servicename}-email.log" > /dev/null 2>&1
-tail -25 "${scriptlog}" >> "${emaillog}"
-if [ ! -z "${consolelog}" ]; then
-	echo -e "\n\nConsole log\n====================\n" >> "${emaillog}"
-	tail -25 "${consolelog}" >> "${emaillog}"
-fi
-if [ ! -z "${gamelogdir}" ]; then
-	echo -e "\n\nServer log\n====================\n" >> "${emaillog}"
-	tail "${gamelogdir}"/*|grep -v "==>"|sed '/^$/d'|tail -25 >> "${emaillog}"
-fi
-mail -s "${subject}" ${email} < "${emaillog}"
-fn_printinfo "Sent email notification to ${email}"
-fn_scriptlog "Sent email notification to ${email}"
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_emailtest(){
 fn_emailtest(){
-fn_rootcheck
-fn_syscheck
-fn_scriptlog "Emailing test notification"
-if [ "${emailnotification}" = "on" ]; then
-	subject="${servicename} Email Test Notification - Testing ${servername}"
-	failurereason="Testing ${servicename} email notification"
-	actiontaken="Sent test email...hello is this thing on?"
-	fn_emailnotification
-else
-	fn_printfailnl "Email notification not enabled"
-	fn_scriptlog "Email notification not enabled"
-fi
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_serverquery(){
 fn_serverquery(){
-# uses gsquery.py to directly query the server
-# detects if the server locks up
-if [ -f gsquery.py ]; then
-	if [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
-		gameport=$(grep Port= ${systemdir}/${ini}|grep -v Master|grep -v LAN|grep -v Proxy|grep -v Listen|sed 's/\Port=//g')
-		port=$((${gameport} + 1))
-	elif [ "${engine}" == "spark" ]; then
-		port=$((${port} + 1))
-	elif [ "${engine}" == "realvirtuality" ]; then
-		port=${queryport}
-	fi
-	fn_printinfo "Monitoring ${servicename}: Detected gsquery.py"
-	fn_scriptlog "Detected gsquery.py"
-	sleep 1
-	fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING"
-	fn_scriptlog "Querying port: ${ip}:${port}: QUERYING"
-	sleep 1
-	serverquery=$(./gsquery.py -a ${ip} -p ${port} -e ${engine} 2>&1)
-	exitcode=$?
-	if [ "${exitcode}" == "1" ]||[ "${exitcode}" == "2" ]||[ "${exitcode}" == "3" ]||[ "${exitcode}" == "4" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ${serverquery}"
-		sleep 1
-		echo -en "\n"
-		fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}"
-		if [[ -z "${secondquery}" ]]; then
-			fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query"
-			fn_scriptlog "Waiting 30 seconds to re-query"
-			sleep 30
-			secondquery=1
-			fn_serverquery
-		fi
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="Failed to query ${servicename}: ${serverquery}"
-			actiontaken="restarted ${servicename}"
-			fn_emailnotification
-		fi
-		fn_restartserver
-		exit
-	elif [ "${exitcode}" == "0" ]; then
-		fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK"
-		fn_scriptlog "Querying port: ${ip}:${port}: OK"
-		sleep 1
-		echo -en "\n"
-		exit
-	elif [ "${exitcode}" == "126" ]; then
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: ERROR: ./gsquery.py: Permission denied"
-		fn_scriptlog "Querying port: ${ip}:${port}: ./gsquery.py: Permission denied"
-		sleep 1
-		echo -en "\n"
-		echo "Attempting to resolve automatically"
-		chmod +x -v gsquery.py
-		exitcode=$?
-		if [ "${exitcode}" == "0" ]; then
-			fn_serverquery
-		else
-			echo -en "\nUnable to resolve automatically. Please manually fix permissions\n"
-			owner=$(ls -al gsquery.py|awk '{ print $3 }')
-			echo "As user ${owner} or root run the following command"
-			whoami=$(whoami)
-			echo -en "\nchown ${whoami}:${whoami} gsquery.py\n\n"
-		exit
-		fi
-	else
-		fn_printfail "Monitoring ${servicename}: Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR"
-		sleep 1
-		echo -en "\n"
-		./gsquery.py -a ${ip} -p ${port} -e ${engine}
-		exit
-	fi
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_monitorserver(){
 fn_monitorserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_printdots "Monitoring ${servicename}: ${servername}"
-fn_scriptlog "Monitoring ${servername}"
-sleep 1
-if [ ! -f ${lockselfname} ]; then
-	fn_printinfo "Monitoring ${servicename}: Monitor disabled: No lock file found"
-	fn_scriptlog "Monitor disabled: No lock file found"
-	sleep 1
-	echo -en "\n"
-	echo "To enable monitor run ${selfname} start"
-	exit
-fi
-updatecheck=$(ps -ef|grep "${selfname} update"|grep -v grep|wc -l)
-if [ "${updatecheck}" = "0" ]; then
-	fn_printdots "Monitoring ${servicename}: Checking session: CHECKING"
-	fn_scriptlog "Checking session: CHECKING"
-	sleep 1
-	tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-	if [ ${tmuxwc} -eq 1 ]; then
-		fn_printok "Monitoring ${servicename}: Checking session: OK"
-		fn_scriptlog "Checking session: OK"
-		sleep 1
-		echo -en "\n"
-		fn_serverquery
-		exit
-	else
-		fn_printfail "Monitoring ${servicename}: Checking session: FAIL"
-		fn_scriptlog "Checking session: FAIL"
-		sleep 1
-		echo -en "\n"
-		if [ "${emailnotification}" = "on" ]; then
-			subject="${servicename} Monitor - Starting ${servername}"
-			failurereason="${servicename} process not running"
-			actiontaken="${servicename} has been restarted"
-			fn_emailnotification
-		fi
-		fn_scriptlog "Monitor is starting ${servername}"
-		fn_startserver
-	fi
-else
-	fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates"
-	fn_scriptlog "Detected SteamCMD is checking for updates"
-	sleep 1
-	fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start"
-	fn_scriptlog "When updates complete ${servicename} will start"
-	sleep 1
-fi
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_restartserver(){
 fn_restartserver(){
@@ -487,338 +179,115 @@ fn_startserver
 }
 }
 
 
 fn_stopserver(){
 fn_stopserver(){
-fn_rootcheck
-fn_syscheck
-pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-fn_printdots "Stopping ${servicename}: ${servername}"
-fn_scriptlog "Stopping ${servername}"
-sleep 1
-if [ "${pid}" == "0" ]; then
-	fn_printfail "Stopping ${servicename}: ${servername} is already stopped"
-	fn_scriptlog "${servername} is already stopped"
-else
-	tmux kill-session -t ${servicename}
-	fn_printok "Stopping ${servicename}: ${servername}"
-	fn_scriptlog "Stopped ${servername}"
-fi
-# Remove lock file
-rm -f ${lockselfname}
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_startserver(){
 fn_startserver(){
-fn_rootcheck
-fn_syscheck
-fn_autoip
-fn_parms
-fn_logmanager
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_scriptlog "Rotating log files"
-	if [ "${engine}" == "unreal2" ]; then
-		mv "${gamelog}" "${gamelogdate}"
-	fi
-	mv "${scriptlog}" "${scriptlogdate}"
-	mv "${consolelog}" "${consolelogdate}"
-fi
-fn_printdots "Starting ${servicename}: ${servername}"
-fn_scriptlog "Starting ${servername}"
-sleep 1
-if [ ${tmuxwc} -eq 1 ]; then
-	fn_printinfo "Starting ${servicename}: ${servername} is already running"
-	fn_scriptlog "${servername} is already running"
-	sleep 1
-	echo -en "\n"
-	exit
-fi
-# Create lock file
-date > "${rootdir}/${lockselfname}"
-cd "${executabledir}"
-tmux new-session -d -s ${servicename} "${executable} ${parms}" 2> ${scriptlogdir}/.${servicename}-tmux-error.tmp
-tmux pipe-pane -o -t ${servicename} "exec cat >> '${consolelog}'"
-sleep 1
-tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l)
-if [ ${tmuxwc} -eq 0 ]; then
-	fn_printfailnl "Starting ${servicename}: Failed to start ${servername}"
-	echo -en "	Check log files: ${rootdir}/log"
-	fn_scriptlog "failed to start ${servername}"
-	if [ -a ${scriptlogdir}/.${servicename}-tmux-error.tmp ]; then
-		fn_scriptlog "tmux returned the following error"
-		cat ${scriptlogdir}/.${servicename}-tmux-error.tmp >> ${scriptlog}
-	fi
-else
-	fn_printok "Starting ${servicename}: ${servername}"
-	fn_scriptlog "Started ${servername}"
-fi
-rm ${scriptlogdir}/.${servicename}-tmux-error.tmp
-sleep 1
-echo -en "\n"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_details(){
 fn_details(){
-if [ ! -f ${rootdir}/functions/fn_details ]; then
-	functionfile="fn_details"
-	fn_fninstall
-fi
-source ${rootdir}/functions/fn_details
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
-fn_fninstall(){
-cd ${rootdir}	
-if [ ! -d "functions" ]; then
-	mkdir functions
+fn_runfunction(){
+# Download function if missing
+if [ ! -f "${rootdir}/functions/${functionfile}" ]; then
+	cd "${rootdir}"
+	if [ ! -d "functions" ]; then
+		mkdir functions
+	fi
+	echo "loading ${functionfile}..."
+	cd functions
+	wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
+	chmod +x "${functionfile}"
+	cd "${rootdir}"
+	sleep 1
+	echo ""
 fi
 fi
-echo ""
-echo "loading ${functionfile}..."
-cd functions
-wget --no-check-certificate -nv -N https://raw.githubusercontent.com/dgibbs64/linuxgameservers/master/functions/${functionfile}
-chmod +x ${functionfile}
-cd ${rootdir}
-sleep 1
-echo ""
+# Run function
+source "${rootdir}/functions/${functionfile}"
 }
 }
 
 
 fn_ut99compressmaps(){
 fn_ut99compressmaps(){
-fn_rootcheck
-clear
-echo "${gamename} Map Compressor"
-echo "============================"
-echo "Will compress all maps in:"
-echo ""
-pwd
-echo ""
-echo "Compressed maps saved to:"
-echo ""
-echo "${compressedmapsdir}"
-echo ""
-while true; do
-	read -p "Start compression [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-mkdir -pv "${compressedmapsdir}" > /dev/null 2>&1
-rm -rfv "${filesdir}/Maps/*.unr.uz"
-cd "${systemdir}"
-for map in `ls "${filesdir}/Maps"`; do
-	./ucc-bin compress ../Maps/${map} --nohomedir
-done
-mv -fv "${filesdir}/Maps/*.unr.uz" "${compressedmapsdir}"
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 #
 #
 ## Installer
 ## Installer
 #
 #
 
 
+fn_ut99fix(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
 fn_header(){
 fn_header(){
-clear
-echo "================================="
-echo "${gamename}"
-echo "Linux Game Server Manager"
-echo "by Daniel Gibbs"
-echo "http://danielgibbs.co.uk"
-echo "================================="
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_ut99filesdl(){
 fn_ut99filesdl(){
-echo "Downloading Server Files"
-echo "================================="
-cd "${rootdir}"
-mkdir -pv "${filesdir}"
-cd "${filesdir}"
-if [ ! -f ut-server-436.tar.gz ]; then
-	wget -nv -N http://danielgibbs.co.uk/wp-content/uploads/ut-server-436.tar.gz
-else
-	echo "ut-server-436.tar.gz already downloaded!"
-fi
-echo "Running MD5 checksum to verify the file"
-sleep 1
-echo "MD5 checksum: 10cd7353aa9d758a075c600a6dd193fd"
-md5check=$(md5sum ut-server-436.tar.gz|awk '{print $1;}')
-echo "File returned: ${md5check}"
-if [ "${md5check}" != "10cd7353aa9d758a075c600a6dd193fd" ]; then
-	echo "MD5 checksum: FAILED!"
-	read -p "Retry download? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv ut-server-436.tar.gz; fn_filesdl;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-else
-	echo "MD5 checksum: PASSED"
-fi
-if [ ! -f UTPGPatch451.tar.bz2 ]; then
-	wget -nv -N http://danielgibbs.co.uk/wp-content/uploads/UTPGPatch451.tar.bz2
-else
-	echo "UTPGPatch451.tar.bz2 already downloaded!"
-fi
-echo "Running MD5 checksum to verify the file"
-sleep 1
-echo "MD5 checksum: 77a735a78b1eb819042338859900b83b"
-md5check=$(md5sum UTPGPatch451.tar.bz2|awk '{print $1;}')
-echo "File returned: ${md5check}"
-if [ "${md5check}" != "77a735a78b1eb819042338859900b83b" ]; then
-	echo "MD5 checksum: FAILED!"
-	read -p "Retry download? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv UTPGPatch451.tar.bz2; fn_filesdl;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-else
-	echo "MD5 checksum: PASSED"
-fi
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 
 
 fn_ut99install(){
 fn_ut99install(){
-echo "Installing ${gamename} Server"
-echo "================================="
-sleep 1
-mkdir -pv "${filesdir}"
-cd "${filesdir}"
-echo "Extracting ut-server-436.tar.gz"
-sleep 1
-tar -zxvf ut-server-436.tar.gz ut-server/ --strip-components=1
-echo "Extracting UTPGPatch451.tar.bz2"
-sleep 1
-tar -jxvf UTPGPatch451.tar.bz2
-while true; do
-	read -p "Was the install successful? [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) fn_retryinstall;;
-	* ) echo "Please answer yes or no.";;
-esac
-done
-while true; do
-	read -p "Remove ut-server-436.tar.gz? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv ut-server-436.tar.gz; break;;
-	[Nn]* ) break;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-while true; do
-	read -p "Remove UTPGPatch451.tar.bz2? [y/N]" yn
-	case $yn in
-	[Yy]* ) rm -fv UTPGPatch451.tar.bz2; break;;
-	[Nn]* ) break;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_loginstall(){
 fn_loginstall(){
-if [ ! -f ${rootdir}/functions/fn_loginstall ]; then
-	functionfile="fn_loginstall"
-	fn_fninstall
-fi	
-source ${rootdir}/functions/fn_loginstall
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_getquery(){
 fn_getquery(){
-	echo "GameServerQuery"
-	echo "============================"
-	while true; do
-		read -p "Do you want to install GameServerQuery? [y/N]" yn
-		case $yn in
-		[Yy]* ) cd "${rootdir}"; wget -nv -N "http://danielgibbs.co.uk/dl/gsquery.py"; chmod +x gsquery.py; break;;
-		[Nn]* ) echo -e "Not installing GameServerQuery.";break;;
-		* ) echo "Please answer yes or no.";;
-	esac
-	done
-	echo ""
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_retryinstall(){
 fn_retryinstall(){
-while true; do
-	read -p "Retry install? [y/N]" yn
-	case $yn in
-	[Yy]* ) fn_install; exit;;
-	[Nn]* ) echo Exiting; exit;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverdirectory(){
+functionfile="${FUNCNAME}"
+fn_runfunction
+}
+
+fn_serverconfig(){
+functionfile="${FUNCNAME}"
+fn_runfunction
 }
 }
 
 
 fn_install(){
 fn_install(){
 fn_rootcheck
 fn_rootcheck
 fn_header
 fn_header
-if [ -d "${filesdir}" ]; then
-	echo "${gamename} Server is already installed here:"
-	pwd
-	echo ""
-	while true; do
-		read -p "Continue [y/N]" yn
-		case $yn in
-		[Yy]* ) fn_header; break;;
-		[Nn]* ) echo Exiting; return 1;;
-		* ) echo "Please answer yes or no.";;
-		esac
-	done
+if [ -z "${autoinstall}" ]; then
+	fn_serverdirectory
+	fn_header
 fi
 fi
-echo "Install Directory:"
-pwd
-echo ""
-while true; do
-	read -p "Continue [y/N]" yn
-	case $yn in
-	[Yy]* ) break;;
-	[Nn]* ) echo Exiting; return 1;;
-	* ) echo "Please answer yes or no.";;
-	esac
-done
-fn_header
 fn_ut99filesdl
 fn_ut99filesdl
 fn_ut99install
 fn_ut99install
-fn_utloginstall
+fn_loginstall
 fn_getquery
 fn_getquery
-echo "Configuring ${gamename} Server"
+fn_serverconfig
+fn_ut99fix
+fn_header
+fn_details
 echo "================================="
 echo "================================="
-	sleep 1
-	echo "Copying "${defaultcfg}" to ${systemdir}/${ini}"
-	tr -d '\r' < "${defaultcfg}" > "${systemdir}/${ini}"
-	sleep 1
-	echo "Enabling UdpServerUplink"
-	{
-	echo "[IpServer.UdpServerUplink]"
-	echo "DoUplink=True"
-	echo "UpdateMinutes=1"
-	echo "MasterServerAddress=unreal.epicgames.com"
-	echo "MasterServerPort=27900"
-	echo "Region=0"
-	}|tee -a "${systemdir}/${ini}" > /dev/null 2>&1
-	sleep 1
-	echo "Removing dead mplayer.com master server"
-	sed -i '/master.mplayer.com/d' "${systemdir}/${ini}"
-	sleep 1
-	echo "Inserting qtracker.com master server"
-	sed -i '66i\ServerActors=IpServer.UdpServerUplink MasterServerAddress=master.qtracker.com MasterServerPort=27900' "${systemdir}/${ini}"
-	sleep 1
-	echo "Enabling WebAdmin"
-	sed -i 's/bEnabled=False/bEnabled=True/g' "${systemdir}/${ini}"
-	sleep 1
-	echo "Setting WebAdmin port to 8076"
-	sed -i '467i\ListenPort=8076' "${systemdir}/${ini}"
-	sleep 1
-
-	fn_header
-	sleep 1
-	fn_utdetails
-	sleep 1
-	echo "================================="
-	echo "Install Complete!"
-	echo ""
-	echo "To start server type:"
-	echo "${selfname} start"
-	echo ""
+echo "Install Complete!"
+echo ""
+echo "To start server type:"
+echo "${selfname} start"
+echo ""
 }
 }
 
 
 case "$1" in
 case "$1" in
@@ -843,7 +312,7 @@ case "$1" in
 	install)
 	install)
 		fn_install;;
 		fn_install;;
 	map-compressor)
 	map-compressor)
-		fn_ut2k4compressmaps;;
+		fn_ut99compressmaps;;
 	*)
 	*)
 	echo "Usage: $0 {start|stop|restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
 	echo "Usage: $0 {start|stop|restart|monitor|email-test|details|backup|console|debug|install|map-compressor}"
 	exit 1;;
 	exit 1;;