diff --git a/Arma3/CONFIG_Vanilla.cfg b/Arma3/CONFIG_Vanilla.cfg new file mode 100644 index 000000000..e41c648f5 --- /dev/null +++ b/Arma3/CONFIG_Vanilla.cfg @@ -0,0 +1,66 @@ +// +// server.cfg +// +// comments are written with "//" in front of them. +// dont change any of the line numbers, the script *might* break + +// PORTS +//default 2302, needs to be unique if multiple servers on same box +//ignore how the line is commented, it is still interprited by the main script +//serverport=2302 +//default 2304, needs to be unique if multiple servers on same box (master port) +steamport=2304; +//default 2303, needs to be unique if multiple servers on same box (query port) +steamqueryport=2303; + +// GLOBAL SETTINGS +// The name of the server that shall be displayed in the public server list +hostname = "arma3server"; +// Password for joining, eg connecting to the server +//password = "ServerAccessPassword"; +// Password to become server admin. When you're in Arma MP and connected to the server, type '#login xyz' +passwordAdmin = "AdminPassword"; +logFile = "arma3server.log"; +verifySignatures = 2; +//kick if data/mods are not equal +equalModRequired = 0; +//was used to define type of secureID +requiredSecureId = 2; + +// WELCOME MESSAGE ("message of the day") +// It can be several lines, separated by comma +// Empty messages "" will not be displayed at all but are only for increasing the interval +motd[]={ + "Welcome to My Arma 3 Server", + "TS3 Server: teamspeak.somewhere.com", + "Web: www.example.com" +}; +motdInterval = 30; // Time interval (in seconds) between each message + +// JOINING RULES +maxPlayers = 40; // Maximum amount of players. Civilians and watchers, beholder, bystanders and so on also count as player. +kickDuplicate = 1; // Each ArmA version has its own ID. If kickDuplicate is set to 1, a player will be kicked +//requiredBuild = 12345 // Require clients joining to have at least build 12345 of game, preventing obsolete clients to connect + +// VOTING +voteMissionPlayers = 1; // Tells the server how many people must connect so that it displays the mission selection screen. +voteThreshold = 0.33; // 33% or more players need to vote for something, for example an admin or a new map, to become effective +//voteMissionPlayers = 0; + +// INGAME SETTINGS +disableVoN = 1; // If set to 1, Voice over Net will not be available +vonCodecQuality = 0; // supports range 1-30 //8kHz is 0-10 (narrowband), 16kHz is 11-20 (wideband), 32kHz is 21-30 (ultrawideband) +persistent = 1; // If 1, missions still run on even after the last player disconnected. +timeStampFormat = "short"; // Set the timestamp format used on each report line in server-side RPT file. Possible values are "none" (default),"short","full". +BattlEye = 1; // Server to use BattlEye system +allowedLoadFileExtensions[] = {"hpp","txt"}; // only allow files with those extensions to be loaded via loadFile command (since Arma 3 build 1.19.124216) + +// SCRIPTING ISSUES +onUserConnected = ""; // +onUserDisconnected = ""; // +doubleIdDetected = ""; // + +// SIGNATURE VERIFICATION +onUnsignedData = "kick (_this select 0)"; // unsigned data detected +onHackedData = "kick (_this select 0)"; //"ban (_this select 0)"; // tampering of the signature detected +onDifferentData = ""; diff --git a/Arma3/arma3server b/Arma3/arma3server new file mode 100644 index 000000000..2ea8f8f81 --- /dev/null +++ b/Arma3/arma3server @@ -0,0 +1,977 @@ +#!/bin/bash +# ARMA 3 +# Server Management Script +# Author: Daniel Gibbs +# Contributor: Scarsz +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="username" +steampass="password" + +# Server IP +ip="0.0.0.0" + +fn_parms(){ +parms="-netlog -port=${serverport} -ip=${ip} -config=${servercfg}" +} + +#### Advanced Variables #### + +# Steam +appid="233780" + +# Server Details +servicename="arma3-server" +gamename="ARMA 3" +engine="realvirtuality" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}" +executabledir="${filesdir}" +executable="./arma3server" +servercfgdir="${systemdir}" +servercfg="${servicename}.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed -e 's/\//g'| tr -d '=\"; ') +serverport=$(sed -n -e '10 p' ${servercfgfullpath} 2>/dev/null| sed 's/[\/\; ]//g' | tr -cd [:digit:]) +queryport=$(sed -n -e '14 p' ${servercfgfullpath} 2>/dev/null| sed 's/[\/\; ]//g' | tr -cd [:digit:]) +masterport=$(sed -n -e '12 p' ${servercfgfullpath} 2>/dev/null| sed 's/[\/\; ]//g' | tr -cd [:digit:]) + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_arma3details(){ +fn_autoip +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${serverport}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "Admin Password: ${adminpass}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "PROTOCOL DESCRIPTION PORT" +echo "UDP Game port ${serverport}" +echo "UDP STEAM query port ${queryport}" +echo "UDP STEAM master traffic port ${masterport}" +echo "" +echo "You can change ports by editing the" +echo "parameters in ${servercfgfullpath}" +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## Installer +# + +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi +} + +fn_arma3config(){ +echo "Downloading CONFIG_Vanilla.cfg" +echo "=================================" +sleep 1 +cd "${systemdir}" +wget -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 "" +} + +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_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 "" +} + +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 "" +} + +fn_steamfix(){ +echo "Applying steamclient.so fix" +echo "=================================" +sleep 1 +mkdir -pv "${HOME}/.steam" +mkdir -pv "${HOME}/.steam/sdk32" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" +sleep 1 +echo "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_steamfix +fn_loginstall +fn_glibcfix +fn_arma3config +sleep 1 +echo "" +fn_header +sleep 1 +fn_arma3details +sleep 1 +echo "=================================" +echo "Install Complete!" +echo "" +echo "To start server type:" +echo "${selfname} start" +echo "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_arma3details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit diff --git a/BladeSymphony/bsserver b/BladeSymphony/bsserver new file mode 100644 index 000000000..d56a0c08c --- /dev/null +++ b/BladeSymphony/bsserver @@ -0,0 +1,1013 @@ +#!/bin/bash +# Blade Symphony +# Server Management Script +# Author: Daniel Gibbs +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="username" +steampass="password" + +# Start Variables +defaultmap="duel_winter" +maxplayers="16" +port="27015" +sourcetvport="27020" +clientport="27005" +ip="0.0.0.0" + +# https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server +fn_parms(){ +parms="-autoupdate -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +} + +#### Advanced Variables #### + +# Steam +appid="228780" + +# Server Details +servicename="bs-server" +gamename="Blade Symphony" +engine="source" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}/berimbau" +executabledir="${filesdir}" +executable="./srcds_run.sh" +servercfgdir="${systemdir}/cfg" +servercfg="${servicename}.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" +defaultcfg="${servercfgdir}/server.cfg" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} -debug +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_details(){ +fn_autoip +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${port}" +echo "RCON password: ${rcon}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "DIRECTION DESCRIPTION PORT" +echo "INBOUND Game/RCON port ${port}" +if [ ! -z ${sourcetvport} ]; then + echo "INBOUND SourceTV port ${sourcetvport}" +fi +echo "OUTBOUND Client port ${clientport}" +echo "" +echo "You can change ports by editing the" +echo "start parameters in ${selfname}." +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## Installer +# + +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi +} + +fn_header(){ +clear +echo "=================================" +echo "${gamename}" +echo "Linux Game Server Manager" +echo "by Daniel Gibbs" +echo "http://danielgibbs.co.uk" +echo "=================================" +echo "" +} + +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 "" +} + +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 "" +} + +fn_steamfix(){ +echo "Applying steamclient.so fix" +echo "=================================" +sleep 1 +mkdir -pv "${HOME}/.steam" +mkdir -pv "${HOME}/.steam/sdk32" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" +sleep 1 +echo "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +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 "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_steamfix +fn_loginstall +fn_getquery +fn_glibcfix +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 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 "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit \ No newline at end of file diff --git a/CounterStrike/csserver b/CounterStrike/csserver index f148ab4df..2217b600c 100644 --- a/CounterStrike/csserver +++ b/CounterStrike/csserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -25,7 +25,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Command-line_parameters_2 fn_parms(){ -parms="-game cstrike -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game cstrike -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -38,9 +38,10 @@ servicename="cs-server" gamename="Counter Strike 1.6" engine="goldsource" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/cstrike" executabledir="${filesdir}" @@ -50,7 +51,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -116,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -139,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -161,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -190,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -244,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -296,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -365,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -396,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -412,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -428,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -452,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -466,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -497,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -515,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -534,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -548,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -558,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -570,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -617,7 +661,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -637,27 +681,6 @@ echo "" ## Installer # -fn_csappmanifest(){ -appdir="${filesdir}/ec5da605084840d3d7b3ed355e48c098b28a1bd5" -if [ ${pass} == 1 ]; then - echo "Creating appmanifest directory. (app 90 fix)" - sleep 2 - mkdir -v "${filesdir}" - mkdir -v "${appdir}" - cd "${appdir}" - echo "Removing any existing appmanifest files. (app 90 fix)" - sleep 2 - rm -f appmanifest_10.acf appmanifest_70.acf appmanifest_90.acf -elif [ ${pass} == 2 ]; then - echo "Downloading HLDS appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_10.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_70.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_90.acf -fi -} - fn_header(){ clear echo "=================================" @@ -677,7 +700,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -691,13 +714,12 @@ echo "" } 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 -} - -fn_success(){ +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -717,7 +739,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -740,11 +762,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -780,18 +816,13 @@ while true; do done fn_header fn_steamdl -echo "Installing ${gamename} Server" -echo "=================================" -pass=1 -fn_csappmanifest -pass=2 -fn_csappmanifest fn_steaminstall fn_steaminstall fn_steaminstall -fn_success +fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -871,7 +902,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/CounterStrikeConditionZero/csczserver b/CounterStrikeConditionZero/csczserver index b7ae5a4a5..ffa39c656 100644 --- a/CounterStrikeConditionZero/csczserver +++ b/CounterStrikeConditionZero/csczserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -25,7 +25,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Command-line_parameters_2 fn_parms(){ -parms="-game czero -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game czero -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -38,9 +38,10 @@ servicename="cscz-server" gamename="Counter Strike: Condition Zero" engine="goldsource" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/czero" executabledir="${filesdir}" @@ -50,7 +51,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -116,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -139,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -161,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -190,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -244,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -296,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -365,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -396,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -412,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -428,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -452,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -466,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -497,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -515,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -534,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -548,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -558,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -570,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -617,7 +661,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -637,33 +681,6 @@ echo "" ## Installer # -fn_csczappmanifest(){ -appdir="${filesdir}/1ea271ace3aa6eb2cbade5b6f37851d19ffb9e6f" -if [ ${pass} == 1 ]; then - echo "Creating appmanifest directory. (app 90 fix)" - sleep 2 - mkdir -v "${filesdir}" - mkdir -v "${appdir}" - cd "${appdir}" - echo "Removing any existing appmanifest files. (app 90 fix)" - sleep 2 - rm -f appmanifest_10.acf appmanifest_70.acf appmanifest_90.acf -elif [ ${pass} == 2 ]; then - echo "Downloading HLDS appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_10.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_70.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_90.acf -elif [ ${pass} == 3 ]; then - echo "Downloading ${gamename} appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - rm -f appmanifest_90.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/czero/appmanifest_90.acf -fi -} - fn_header(){ clear echo "=================================" @@ -683,7 +700,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -697,13 +714,12 @@ echo "" } 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 -} - -fn_success(){ +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -723,7 +739,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -746,11 +762,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -786,22 +816,10 @@ while true; do done fn_header fn_steamdl -echo "Installing ${gamename} Server" -echo "=================================" -pass=1 -fn_csczappmanifest -pass=2 -fn_csczappmanifest -fn_steaminstall fn_steaminstall -pass=3 -fn_csczappmanifest -fn_steaminstall -fn_steaminstall -fn_steaminstall -fn_success fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -881,7 +899,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/CounterStrikeGlobalOffensive/csgoserver b/CounterStrikeGlobalOffensive/csgoserver index 9bacdee1a..80bf4ef01 100644 --- a/CounterStrikeGlobalOffensive/csgoserver +++ b/CounterStrikeGlobalOffensive/csgoserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -56,9 +56,10 @@ servicename="csgo-server" gamename="Counter Strike: Global Offensive" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/csgo" executabledir="${filesdir}" @@ -68,7 +69,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -93,7 +93,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -134,7 +134,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -157,8 +157,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -179,28 +179,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -208,19 +220,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip -fn_csgoappidfix +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -263,8 +282,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -315,8 +334,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -384,9 +403,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -415,13 +434,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -431,9 +452,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -447,14 +467,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -471,9 +491,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -485,19 +505,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -516,11 +544,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -534,7 +562,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -553,7 +581,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -567,8 +595,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -577,6 +605,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -590,26 +620,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -637,7 +680,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -687,7 +730,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -706,7 +749,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -726,7 +769,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -749,11 +792,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -792,6 +849,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -847,7 +905,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/CounterStrikeSource/cssserver b/CounterStrikeSource/cssserver index 69b9c472a..facbd449b 100644 --- a/CounterStrikeSource/cssserver +++ b/CounterStrikeSource/cssserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,7 +19,6 @@ steampass="" # Start Variables defaultmap="de_dust2" maxplayers="16" -tickrate="64" port="27015" sourcetvport="27020" clientport="27005" @@ -27,7 +26,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-game cstrike -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game cstrike -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -40,9 +39,10 @@ servicename="css-server" gamename="Counter Strike: Source" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/cstrike" executabledir="${filesdir}" @@ -52,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -77,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -118,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -141,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -163,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -192,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -246,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -298,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -367,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -398,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -414,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -430,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -454,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -468,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -499,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -517,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -536,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -550,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -560,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -572,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -619,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -658,7 +701,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -677,7 +720,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -697,7 +740,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -720,11 +763,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -763,6 +820,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -818,7 +876,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/DayOfDefeat/dodserver b/DayOfDefeat/dodserver index 63de63619..f20a8dbda 100644 --- a/DayOfDefeat/dodserver +++ b/DayOfDefeat/dodserver @@ -1,9 +1,9 @@ #!/bin/bash -# Counter Strike +# Day of Defeat # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -25,7 +25,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Command-line_parameters_2 fn_parms(){ -parms="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -38,9 +38,10 @@ servicename="dod-server" gamename="Day of Defeat" engine="goldsource" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/dod" executabledir="${filesdir}" @@ -50,7 +51,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -116,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -139,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -161,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -190,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -244,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -253,7 +273,7 @@ else while true; do read -p "Do you want to start the server? [y/N]" yn case $yn in - [Yy]* ) fn_startserver;break;; + [Yy]* ) fn_startserver; break;; [Nn]* ) break;; * ) echo "Please answer yes or no.";; esac @@ -287,7 +307,7 @@ if [ ${tmuxwc} -eq 1 ]; then 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;; + [Yy]* ) fn_stopserver; break;; [Nn]* ) break;; * ) echo "Please answer yes or no.";; esac @@ -296,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -365,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -396,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -412,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -428,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -452,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -466,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -497,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -515,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -534,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -548,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -558,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -570,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -617,7 +661,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -637,33 +681,6 @@ echo "" ## Installer # -fn_dodappmanifest(){ -appdir="${filesdir}/8afa93e01174026686b12fbaf9ff54e7bffbe8fc" -if [ ${pass} == 1 ]; then - echo "Creating appmanifest directory. (app 90 fix)" - sleep 2 - mkdir -v "${filesdir}" - mkdir -v "${appdir}" - cd "${appdir}" - echo "Removing any existing appmanifest files. (app 90 fix)" - sleep 2 - rm -f appmanifest_10.acf appmanifest_70.acf appmanifest_90.acf -elif [ ${pass} == 2 ]; then - echo "Downloading HLDS appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_10.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_70.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_90.acf -elif [ ${pass} == 3 ]; then - echo "Downloading ${gamename} appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - rm -f appmanifest_90.acf - wget https://raw2.github.com/dgibbs64/linuxgameservers/master/appmanifest/dod/appmanifest_90.acf -fi -} - fn_header(){ clear echo "=================================" @@ -683,7 +700,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -697,13 +714,12 @@ echo "" } 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 -} - -fn_success(){ +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -723,7 +739,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -746,11 +762,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -786,22 +816,13 @@ while true; do done fn_header fn_steamdl -echo "Installing ${gamename} Server" -echo "=================================" -pass=1 -fn_dodappmanifest -pass=2 -fn_dodappmanifest fn_steaminstall fn_steaminstall -pass=3 -fn_dodappmanifest fn_steaminstall fn_steaminstall -fn_steaminstall -fn_success fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -881,7 +902,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/DayOfDefeatSource/dodsserver b/DayOfDefeatSource/dodsserver index 6ac981489..ff8431a03 100644 --- a/DayOfDefeatSource/dodsserver +++ b/DayOfDefeatSource/dodsserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,7 +19,6 @@ steampass="" # Start Variables defaultmap="dod_Anzio" maxplayers="16" -tickrate="64" port="27015" sourcetvport="27020" clientport="27005" @@ -27,7 +26,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game dod -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -40,9 +39,10 @@ servicename="dods-server" gamename="Day of Defeat: Source" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/dod" executabledir="${filesdir}" @@ -52,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -77,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -118,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -141,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -163,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -192,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -246,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -298,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -367,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -398,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -414,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -430,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -454,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -468,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -499,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -517,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -536,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -550,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -560,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -572,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -619,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -658,7 +701,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -677,7 +720,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -697,7 +740,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -720,11 +763,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -763,6 +820,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -818,7 +876,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/FistfulOfFrags/dependencies/libm.so.6 b/FistfulOfFrags/dependencies/libm.so.6 new file mode 100644 index 000000000..39034023b Binary files /dev/null and b/FistfulOfFrags/dependencies/libm.so.6 differ diff --git a/FistfulOfFrags/fofserver b/FistfulOfFrags/fofserver new file mode 100644 index 000000000..5576795f5 --- /dev/null +++ b/FistfulOfFrags/fofserver @@ -0,0 +1,1047 @@ +#!/bin/bash +# Fistful Of Frags +# Server Management Script +# Author: Daniel Gibbs +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="anonymous" +steampass="" + +# Start Variables +defaultmap="fof_depot" +maxplayers="16" +port="27015" +sourcetvport="27020" +clientport="27005" +ip="0.0.0.0" + +# https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server +fn_parms(){ +parms="-game fof -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +} + +#### Advanced Variables #### + +# Steam +appid="295230" + +# Server Details +servicename="fof-server" +gamename="Fistful of Frags" +engine="source" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}/fof" +executabledir="${filesdir}" +executable="./srcds_run" +servercfgdir="${systemdir}/cfg" +servercfg="${servicename}.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" +defaultcfg="${servercfgdir}/server.cfg" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} -debug +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_details(){ +fn_autoip +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${port}" +echo "RCON password: ${rcon}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "DIRECTION DESCRIPTION PORT" +echo "INBOUND Game/RCON port ${port}" +if [ ! -z ${sourcetvport} ]; then + echo "INBOUND SourceTV port ${sourcetvport}" +fi +echo "OUTBOUND Client port ${clientport}" +echo "" +echo "You can change ports by editing the" +echo "start parameters in ${selfname}." +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## Installer +# + +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi +} + +fn_header(){ +clear +echo "=================================" +echo "${gamename}" +echo "Linux Game Server Manager" +echo "by Daniel Gibbs" +echo "http://danielgibbs.co.uk" +echo "=================================" +echo "" +} + +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 "" +} + +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 "" +} + +fn_steamfix(){ +echo "Applying steamclient.so fix" +echo "=================================" +sleep 1 +mkdir -pv "${HOME}/.steam" +mkdir -pv "${HOME}/.steam/sdk32" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" +sleep 1 +echo "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +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 "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_steamfix +fn_loginstall +fn_getquery +fn_glibcfix +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 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" + 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 "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit \ No newline at end of file diff --git a/GameServerQuery/gsquery.py b/GameServerQuery/gsquery.py index 9369261f9..644ce2781 100644 --- a/GameServerQuery/gsquery.py +++ b/GameServerQuery/gsquery.py @@ -1,9 +1,9 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -# Source Game Server Query +# Game Server Query # Author: Anonymous & Daniel Gibbs # # Website: http://danielgibbs.co.uk -# Version: 251213 +# Version: 031014 import optparse import socket @@ -23,10 +23,14 @@ class GameServer: self.query_prompt_string = '\xFF\xFF\xFF\xFFTSource Engine Query\0' if self.option.engine == 'spark': self.query_prompt_string = '\xFF\xFF\xFF\xFFTSource Engine Query\0' + if self.option.engine == 'realvirtuality': + self.query_prompt_string = '\xFF\xFF\xFF\xFFTSource Engine Query\0' elif self.option.engine == 'unreal': self.query_prompt_string = '\x5C\x69\x6E\x66\x6F\x5C' elif self.option.engine == 'unreal2': self.query_prompt_string = '\x79\x00\x00\x00\x00' + elif self.option.engine == 'avalanche': + self.query_prompt_string = '\xFE\xFD\x09\x10\x20\x30\x40' self.connected = False self.response = None self.sanity_checks() diff --git a/GarrysMod/dependencies/libc.so.6 b/GarrysMod/dependencies/libc.so.6 new file mode 100644 index 000000000..ee77b1740 Binary files /dev/null and b/GarrysMod/dependencies/libc.so.6 differ diff --git a/GarrysMod/dependencies/libm.so.6 b/GarrysMod/dependencies/libm.so.6 new file mode 100644 index 000000000..2f0eb4672 Binary files /dev/null and b/GarrysMod/dependencies/libm.so.6 differ diff --git a/GarrysMod/dependencies/libpthread.so.0 b/GarrysMod/dependencies/libpthread.so.0 new file mode 100644 index 000000000..a4bfc2282 Binary files /dev/null and b/GarrysMod/dependencies/libpthread.so.0 differ diff --git a/GarrysMod/dependencies/libstdc++.so.6 b/GarrysMod/dependencies/libstdc++.so.6 new file mode 100644 index 000000000..fa1204704 Binary files /dev/null and b/GarrysMod/dependencies/libstdc++.so.6 differ diff --git a/GarrysMod/gmodserver b/GarrysMod/gmodserver new file mode 100644 index 000000000..c826a7ee8 --- /dev/null +++ b/GarrysMod/gmodserver @@ -0,0 +1,1100 @@ +#!/bin/bash +# Garrys's Mod +# Server Management Script +# Author: Daniel Gibbs +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="anonymous" +steampass="" + +# Workshop Variables +# http://wiki.garrysmod.com/page/Workshop_for_Dedicated_Servers +workshopauth="" +workshopcollectionid="" + +# Start Variables +defaultmap="gm_construct" +maxplayers="16" +port="27015" +sourcetvport="27020" +clientport="27005" +ip="0.0.0.0" + +# https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server +fn_parms(){ +parms="-game garrysmod -strictportbind -ip ${ip} -port ${port} +host_workshop_collection ${workshopcollectionid} -authkey ${workshopauth} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +} + +#### Advanced Variables #### + +# Steam +appid="4020" + +# Server Details +servicename="gmod-server" +gamename="Garrys's Mod" +engine="source" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}/garrysmod" +executabledir="${filesdir}" +executable="./srcds_run" +servercfgdir="${systemdir}/cfg" +servercfg="${servicename}.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" +defaultcfg="${servercfgdir}/server.cfg" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} -debug +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_details(){ +fn_autoip +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${port}" +echo "RCON password: ${rcon}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "DIRECTION DESCRIPTION PORT" +echo "INBOUND Game/RCON port ${port}" +if [ ! -z ${sourcetvport} ]; then + echo "INBOUND SourceTV port ${sourcetvport}" +fi +echo "OUTBOUND Client port ${clientport}" +echo "" +echo "You can change ports by editing the" +echo "start parameters in ${selfname}." +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## Installer +# + +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi +} + +fn_libsteamfix(){ + echo "Applying libsteam.so fix" + echo "=================================" + sleep 1 + mkdir -pv "${HOME}/.steam" + mkdir -pv "${HOME}/.steam/sdk32" + cp -v "${filesdir}/bin/libsteam.so" "${HOME}/.steam/sdk32/libsteam.so" + sleep 1 + echo "" +} + +fn_header(){ +clear +echo "=================================" +echo "${gamename}" +echo "Linux Game Server Manager" +echo "by Daniel Gibbs" +echo "http://danielgibbs.co.uk" +echo "=================================" +echo "" +} + +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 "" +} + +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 "" +} + +fn_steamfix(){ +echo "Applying steamclient.so fix" +echo "=================================" +sleep 1 +mkdir -pv "${HOME}/.steam" +mkdir -pv "${HOME}/.steam/sdk32" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" +sleep 1 +echo "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +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 "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_steamfix +fn_libsteamfix +fn_loginstall +fn_getquery +fn_glibcfix +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 Info" + echo -e "hostname \"${servername}\"" + echo -e "sv_password \"\"" + echo -e "" + echo -e "// RCON Settings" + echo -e "rcon_password \"${rconpass}\"" + 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 "// 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 "" + 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 "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit \ No newline at end of file diff --git a/HalfLife2Deathmatch/hl2dmserver b/HalfLife2Deathmatch/hl2dmserver index 84c6b62ab..8d5cfe1a9 100644 --- a/HalfLife2Deathmatch/hl2dmserver +++ b/HalfLife2Deathmatch/hl2dmserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,7 +19,6 @@ steampass="" # Start Variables defaultmap="dm_lockdown" maxplayers="16" -tickrate="64" port="27015" sourcetvport="27020" clientport="27005" @@ -27,7 +26,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-game hl2mp -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game hl2mp -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -40,9 +39,10 @@ servicename="hl2dm-server" gamename="Half Life 2: Deathmatch" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/hl2mp" executabledir="${filesdir}" @@ -52,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -77,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -118,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -141,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -163,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -192,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -246,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -298,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -367,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -398,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -414,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -430,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -454,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -468,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -499,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -517,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -536,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -550,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -560,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -572,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -619,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -658,7 +701,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -677,7 +720,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -697,7 +740,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -720,11 +763,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -763,6 +820,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -818,7 +876,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/HalfLifeDeathmatchClassic/hldmcserver b/HalfLifeDeathmatchClassic/hldmcserver index 024ebcfc6..2bbe03dbe 100644 --- a/HalfLifeDeathmatchClassic/hldmcserver +++ b/HalfLifeDeathmatchClassic/hldmcserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -25,7 +25,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Command-line_parameters_2 fn_parms(){ -parms="-game valve -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game valve -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -38,9 +38,10 @@ servicename="hldmc-server" gamename="Half Life: Deathmatch Classic" engine="goldsource" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/valve" executabledir="${filesdir}" @@ -50,7 +51,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -116,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -139,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -161,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -190,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -244,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -296,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -365,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -396,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -412,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -428,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -452,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -466,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -497,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -515,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -534,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -548,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -558,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -570,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -617,7 +661,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -637,27 +681,6 @@ echo "" ## Installer # -fn_hldmcappmanifest(){ -appdir="${filesdir}/91aa146f9fda7056098af2c7015b8fb308bf1ce2" -if [ ${pass} == 1 ]; then - echo "Creating appmanifest directory. (app 90 fix)" - sleep 2 - mkdir -v "${filesdir}" - mkdir -v "${appdir}" - cd "${appdir}" - echo "Removing any existing appmanifest files. (app 90 fix)" - sleep 2 - rm -f appmanifest_10.acf appmanifest_70.acf appmanifest_90.acf -elif [ ${pass} == 2 ]; then - echo "Downloading HLDS appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_10.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_70.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_90.acf -fi -} - fn_header(){ clear echo "=================================" @@ -677,7 +700,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -691,13 +714,12 @@ echo "" } 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 -} - -fn_success(){ +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -717,7 +739,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -740,11 +762,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -780,18 +816,13 @@ while true; do done fn_header fn_steamdl -echo "Installing ${gamename} Server" -echo "=================================" -pass=1 -fn_hldmcappmanifest -pass=2 -fn_hldmcappmanifest fn_steaminstall fn_steaminstall fn_steaminstall -fn_success +fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -871,7 +902,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/Insurgency/insserver b/Insurgency/insserver index a39a00f3f..d2c85deee 100644 --- a/Insurgency/insserver +++ b/Insurgency/insserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -26,7 +26,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game insurgency -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -39,9 +39,10 @@ servicename="ins-server" gamename="Insurgency" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/insurgency" executabledir="${filesdir}" @@ -51,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -117,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -140,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -162,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -191,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -245,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -297,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -366,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -397,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -413,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -429,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -453,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -467,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -498,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -516,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -535,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -549,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -559,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -571,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -618,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -638,16 +682,112 @@ echo "" ## Installer # -fn_insdeps(){ -echo "Downloading libc.so.6, libpthread.so.0 & librt.so.1" -echo "=================================" -sleep 1 -cd "${filesdir}/bin" -wget https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 -wget https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 -wget https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 -sleep 1 -echo "" +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi } fn_header(){ @@ -669,7 +809,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -688,7 +828,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -708,7 +848,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -731,11 +871,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -774,7 +928,8 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall -fn_insdeps +fn_getquery +fn_glibcfix echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -830,7 +985,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/JustCause2/jc2server b/JustCause2/jc2server new file mode 100644 index 000000000..900b51f5d --- /dev/null +++ b/JustCause2/jc2server @@ -0,0 +1,862 @@ +#!/bin/bash +# Just Cause 2 +# Server Management Script +# Author: Daniel Gibbs +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="anonymous" +steampass="" + +# Start Variables +maxplayers="10" +port="7777" +ip="0.0.0.0" + +fn_parms(){ +parms="--maxplayers ${maxplayers} --bindip ${ip} --bindport ${port}" +} + +#### Advanced Variables #### + +# Steam +appid="261140" + +# Server Details +servicename="jc2-server" +gamename="Just Cause 2" +engine="avalanche" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}" +executabledir="${filesdir}" +executable="./Jcmp-Server" +servercfgdir="${filesdir}" +servercfg="config.lua" +servercfgfullpath="${servercfgdir}/${servercfg}" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} -debug +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_jc2details(){ +fn_autoip +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${port}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "DIRECTION DESCRIPTION PORT" +echo "INBOUND Game port ${port}" +echo "" +echo "You can change ports by editing the" +echo "start parameters in ${selfname}." +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## Installer +# + +fn_header(){ +clear +echo "=================================" +echo "${gamename}" +echo "Linux Game Server Manager" +echo "by Daniel Gibbs" +echo "http://danielgibbs.co.uk" +echo "=================================" +echo "" +} + +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 "" +} + +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 "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +fn_jc2config(){ +echo "Copying default_config.lua" +echo "=================================" +sleep 1 +cd "${filesdir}" +cp -v default_config.lua config.lua +sleep 1 +echo "" +} + +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 "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_loginstall +fn_jc2config +fn_getquery + sleep 1 + echo "" + fn_header + sleep 1 + fn_jc2details + sleep 1 + echo "=================================" + echo "Install Complete!" + echo "" + echo "To start server type:" + echo "${selfname} start" + echo "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit \ No newline at end of file diff --git a/KillingFloor/kfserver b/KillingFloor/kfserver index 453961c93..5939f8bd3 100644 --- a/KillingFloor/kfserver +++ b/KillingFloor/kfserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,9 +19,10 @@ steampass="password" # Steam appid="215360" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/System" executabledir="${systemdir}" @@ -40,24 +41,27 @@ ip="0.0.0.0" # Logging logdays="7" +gamelogdir="${rootdir}/log/server" scriptlogdir="${rootdir}/log/script" consolelogdir="${rootdir}/log/console" +gamelog="${gamelogdir}/${servicename}-game.log" scriptlog="${scriptlogdir}/${servicename}-script.log" consolelog="${consolelogdir}/${servicename}-console.log" emaillog="${scriptlogdir}/${servicename}-email.log" +gamelogdate="${gamelogdir}/${servicename}-game-$(date '+%d-%m-%Y-%H-%M-%S').log" scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" # Start Variables fn_parms(){ defaultmap="KF-BioticsLab.rom" -parms="server ${defaultmap}?game=KFmod.KFGameType?VACSecured=true -nohomedir ini=${ini} log=${logfile}" +parms="server ${defaultmap}?game=KFmod.KFGameType?VACSecured=true -nohomedir ini=${ini} log=${gamelog}" # Start Variables for Objective mode #defaultmap="KFO-Steamland" -#parms="server ${defaultmap}?Game=KFStoryGame.KFStoryGame?VACSecured=true -nohomedir ini=${ini} log=${logfile}" +#parms="server ${defaultmap}?Game=KFStoryGame.KFStoryGame?VACSecured=true -nohomedir ini=${ini} log=${gamelog}" } ##### Script ##### @@ -66,7 +70,7 @@ parms="server ${defaultmap}?game=KFmod.KFGameType?VACSecured=true -nohomedir ini # what you are doing 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 ] @@ -107,7 +111,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -130,8 +134,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -152,28 +156,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -181,18 +197,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -235,8 +259,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -287,8 +311,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -356,9 +380,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -387,13 +411,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -403,9 +429,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -419,14 +444,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -443,9 +468,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -457,19 +482,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -488,11 +521,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -506,7 +539,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -525,7 +558,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -539,8 +572,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -549,6 +582,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -561,26 +596,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -704,7 +752,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -723,7 +771,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -743,7 +791,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -766,11 +814,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -809,6 +871,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -864,7 +927,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/Left4Dead/l4dserver b/Left4Dead/l4dserver new file mode 100644 index 000000000..65b89dc55 --- /dev/null +++ b/Left4Dead/l4dserver @@ -0,0 +1,915 @@ +#!/bin/bash +# Left 4 Dead +# Server Management Script +# Author: Daniel Gibbs +# Website: http://danielgibbs.co.uk +# Version: 061014 + +#### Variables #### + +# Notification Email +# (on|off) +emailnotification="off" +email="email@example.com" + +# Steam login +steamuser="anonymous" +steampass="" + +# Start Variables +defaultmap="l4d_hospital01_apartment" +maxplayers="8" +port="27015" +clientport="27005" +ip="0.0.0.0" + +# https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server +fn_parms(){ +parms="-game left4dead -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +} + +#### Advanced Variables #### + +# Steam +appid="222840" + +# Server Details +servicename="l4d-server" +gamename="Left 4 Dead" +engine="source" + +# Directories +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +selfname="$0" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" +systemdir="${filesdir}/left4dead" +executabledir="${filesdir}" +executable="./srcds_run" +servercfgdir="${systemdir}/cfg" +servercfg="${servicename}.cfg" +servercfgfullpath="${servercfgdir}/${servercfg}" +defaultcfg="${servercfgdir}/server.cfg" +backupdir="backups" + +# Server Details +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') + +# Logging +logdays="7" +gamelogdir="${systemdir}/logs" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" + +##### Script ##### +# Do not edit +# unless you know +# what you are doing + +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: ${1}" >> ${scriptlog} +} + +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" + exit +fi +} + +fn_syscheck(){ +if [ ! -e "${systemdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" + exit +fi +} + +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 +} + +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 +} + +fn_debugserver(){ +fn_rootcheck +fn_syscheck +fn_autoip +fn_distro +fn_uptime +fn_load +fn_parms +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" +echo "" +echo "Start parameters:" +echo ${parms} +echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +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_stopserver +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd "${executabledir}" +${executable} ${parms} -debug +} + +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 +} + +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" +} + +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 +} + +fn_uptime(){ +uptime=$( /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" +} + +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" +} + +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 +} + +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 +} + +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}" +} + +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}" +} + +fn_restartserver(){ +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +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" +} + +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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi +else + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" +fi +sleep 1 +echo -en "\n" +} + +fn_details(){ +fn_autoip +servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') +rcon=$(grep -s rcon_password "${servercfgfullpath}"|sed 's/rcon_password //g'|sed 's/"//g') +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +echo "" +echo "${gamename} Server Details" +echo "============================" +echo "Server name: ${servername}" +echo "Server IP: ${ip}:${port}" +echo "RCON password: ${rcon}" +echo "Config file: ${servercfgfullpath}" +echo "" +echo "${servername} Ports" +echo "============================" +echo "Ports the server is currently using." +echo "" +echo "DIRECTION DESCRIPTION PORT" +echo "INBOUND Game/RCON port ${port}" +if [ ! -z ${sourcetvport} ]; then + echo "INBOUND SourceTV port ${sourcetvport}" +fi +echo "OUTBOUND Client port ${clientport}" +echo "" +echo "You can change ports by editing the" +echo "start parameters in ${selfname}." +echo "" +if [ "${pid}" == "0" ]; then + echo -e "Status:\e[0;31m OFFLINE\e[0;39m" +else + echo -e "Status:\e[0;32m ONLINE\e[0;39m" +fi +echo "" +} + +# +## 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(){ +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 "" +} + +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 "" +} + +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 "" +} + +fn_steamfix(){ +echo "Applying steamclient.so fix" +echo "=================================" +sleep 1 +mkdir -pv "${HOME}/.steam" +mkdir -pv "${HOME}/.steam/sdk32" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" +sleep 1 +echo "" +} + +fn_loginstall(){ +echo "Creating log directorys" +echo "=================================" +sleep 1 +mkdir -pv "${rootdir}/log" +mkdir -pv "${scriptlogdir}" +touch "${scriptlog}" +mkdir -pv "${consolelogdir}" +touch "${consolelog}" +if [ ! -h ${rootdir}/log/server ]; then + ln -sv "${gamelogdir}" "${rootdir}/log/server" +else + echo "Symbolic link ${gamelogdir} => ${rootdir}/log/server already exists!" +fi +sleep 1 +echo "" +} + +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 "" +} + +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 +} + +fn_install(){ +fn_rootcheck +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 +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_steaminstall +fn_steamfix +fn_loginstall +fn_getquery +fn_l4ddeps +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 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 "" +} + +case "$1" in + start) + fn_startserver;; + stop) + fn_stopserver;; + restart) + fn_restartserver;; + update) + fn_updateserver;; + update-restart) + fn_stopserver + fn_updateserver + fn_startserver;; + validate) + fn_validateserver;; + validate-restart) + fn_stopserver + fn_validateserver + fn_startserver;; + monitor) + fn_monitorserver;; + email-test) + fn_emailtest;; + details) + fn_details;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; + install) + fn_install;; + *) + echo "Usage: $0 {start|stop|restart|update|update-restart|validate|validate-restart|monitor|email-test|details|backup|console|debug|install}" + exit 1;; +esac +exit \ No newline at end of file diff --git a/Left4Dead2/l4d2server b/Left4Dead2/l4d2server index 2d3792df6..aea00cfdb 100644 --- a/Left4Dead2/l4d2server +++ b/Left4Dead2/l4d2server @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,15 +19,13 @@ steampass="" # Start Variables defaultmap="c5m1_waterfront" maxplayers="8" -tickrate="64" port="27015" -sourcetvport="27020" clientport="27005" ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-game left4dead2 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game left4dead2 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -40,9 +38,10 @@ servicename="l4d2-server" gamename="Left 4 Dead 2" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/left4dead2" executabledir="${filesdir}" @@ -77,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -118,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -141,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -163,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -192,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -246,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -298,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -367,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -398,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -414,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -430,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -454,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -468,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -499,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -517,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -536,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -550,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -560,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -572,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -619,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -658,7 +701,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -677,7 +720,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -697,7 +740,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -720,11 +763,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -763,6 +820,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -818,7 +876,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/Mumble/mumbleserver b/Mumble/mumbleserver index 5906844ff..1c05a8598 100644 --- a/Mumble/mumbleserver +++ b/Mumble/mumbleserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 221113 +# Version: 250814 ### Variables #### @@ -19,57 +19,96 @@ servicename="mumble-server" # Directorys rootdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" -filesdir="${rootdir}/murmur" +lockselfname=$(echo ".${servicename}.lock") +filesdir="${rootdir}/serverfiles" ini="murmur.ini" +executable="./murmur.x86 -fg -ini ${ini}" backupdir="backups" # Logging -logdir="${rootdir}/log" -logfile="${logdir}/${servicename}.log" -logfiledate="${logdir}/${servicename}-$( date '+%d-%m-%Y-%H-%M-%S').log" logdays="7" +logdir="${rootdir}/log" +scriptlogdir="${rootdir}/log/script" +consolelogdir="${rootdir}/log/console" + +scriptlog="${scriptlogdir}/${servicename}-script.log" +consolelog="${consolelogdir}/${servicename}-console.log" +emaillog="${scriptlogdir}/${servicename}-email.log" + +scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" +consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" ##### Script ##### # Do not edit # unless you know # what you are doing -fn_rootcheck(){ -if [ `whoami` = "root" ];then - echo -e "[\e[0;31m FAIL \e[0;39m] Script will not run as root!" - exit -fi +fn_scriptlog(){ + echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: '$1'" >> ${scriptlog} } -fn_syscheck(){ -if [ ! -e ${filesdir} ];then - echo -e "[\e[0;31m FAIL \e[0;39m] ${servicename}: cannot access ${filesdir}: No such directory" +# [ FAIL ] +fn_printfail(){ + echo -en "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printfailnl(){ + echo -e "\r\033[K[\e[0;31m FAIL \e[0;39m] $@" +} + +fn_printok(){ + echo -en "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +# [ OK ] +fn_printoknl(){ + echo -e "\r\033[K[\e[0;32m OK \e[0;39m] $@" +} + +fn_printinfo(){ + echo -en "\r\033[K[\e[0;36m INFO \e[0;39m] $@" +} + +fn_printinfonl(){ + 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] $@" +} + +fn_printwarn(){ + echo -en "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +fn_printwarnnl(){ + echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" +} + +# [ .... ] +fn_printdots(){ + echo -en "\r\033[K[ .... ] $@" +} + +fn_rootcheck(){ +if [ `whoami` = "root" ]; then + fn_printfailnl "Script will not run as root!" exit fi } -fn_runcheck(){ -# already running check -pidwc=$(screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}'|wc -l) -if [ ${pidwc} -eq 1 ];then - echo -e "[\e[0;36m INFO \e[0;39m] ${servicename}: ${servername} is already running" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} is already running" >> ${logfile} - exit -# multiple of same instance check -elif [ ${pidwc} -ge 2 ];then - echo -e "[\e[0;31m FAIL \e[0;39m] ${servicename}: ${servername} is running ${pidwc} times" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} is running ${pidwc} times" >> ${logfile} - echo -e "[\e[0;32m OK \e[0;39m] ${servicename}: ${servername} stopping all ${pidwc} instances" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} stopping all ${pidwc} instances" >> ${logfile} - fn_stopserver +fn_syscheck(){ +if [ ! -e "${filesdir}" ]; then + fn_printfailnl "Cannot access ${systemdir}: No such directory" exit fi } fn_inicheck(){ if [ ! -e ${filesdir}/${ini} ]; then - echo -e "[\e[1;33m WARN \e[0;39m] ${servicename}: ${filesdir}/${ini} is missing" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} ${filesdir}/${ini} is missing" >> ${logfile} + fn_printwarnnl "${servicename}: ${filesdir}/${ini} is missing" + fn_scriptlog "${servername} ${filesdir}/${ini} is missing" >> ${scriptlog} fi } @@ -89,34 +128,33 @@ while true; do read -p "Continue? [y/N]" yn case $yn in [Yy]* ) break;; - [Nn]* ) echo Exiting; return 1 ;; + [Nn]* ) echo Exiting; return 1;; * ) echo "Please answer yes or no.";; esac done -pidwc=$(screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}'|wc -l) -if [ ${pidwc} -eq 1 ];then +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;; + [Yy]* ) fn_stopserver; break;; [Nn]* ) break;; * ) echo "Please answer yes or no.";; esac done fi -echo -en "[ .... ] Starting ${servicename}: ${servername} backup" -echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: Starting ${servername} backup" >> ${scriptlog} -sleep 0.5 -echo -en "\r[\e[0;32m OK \e[0;39m] Starting ${servicename}: ${servername} backup" -echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: Started ${servername} backup" >> ${scriptlog} +fn_printdots "Starting backup ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting backup ${servicename}: ${servername}" sleep 1 +fn_scriptlog "Backup started" echo -en "\n" -cd ${rootdir} -mkdir ${backupdir} > /dev/null 2>&1 -tar -cvzf ${backupdir}/${backupname}.tar.gz --exclude ${backupdir} * -echo -en "\r${servicename} backup complete" -echo -e "$(date '+%b %d %H:%M:%S') ${servicename}: backup complete" >> ${scriptlog} +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" } fn_distro(){ @@ -142,7 +180,7 @@ days=$(( uptime/60/60/24 )) } fn_load(){ -load=$(uptime | awk -F 'load average' '{ print $2 }') +load=$(uptime|awk -F 'load average' '{ print $2 }') } fn_emailnotification(){ @@ -150,150 +188,275 @@ fn_distro fn_uptime fn_load { -echo -e "=========================================\nServer information\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 "=========================================\n${servicename} statistics\n=========================================\n" -echo -e "Service: ${servicename}" -echo -e "Server: ${servername}" -echo -e "Failure reason: ${failurereason}" -echo -e "Action Taken: ${actiontaken}\n" -echo -e "=========================================\n${servicename} log summary\n=========================================\n" -}|tee ${logdir}/${servicename}-email.log > /dev/null 2>&1 -tail -50 ${logfile} >> /${logdir}/${servicename}-email.log -mail -s "${subject}" ${email} < /${logdir}/${servicename}-email.log -echo -e "[\e[0;36m INFO \e[0;39m] Sent email notification to ${email}" -echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: sent email notification to ${email}" >> ${logfile} + echo -e "========================================\n${servicename} details\n========================================\n" + echo -e "Service: ${servicename}" + echo -e "Server: ${servername}" + 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}" +sleep 1 +echo -en "\n" +fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ fn_rootcheck fn_syscheck -echo -e "[\e[0;32m OK \e[0;39m] Emailing test notification" -echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Emailing test notification" >> ${logfile} -if [ "${emailnotification}" = "on" ];then +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 - echo -e "[\e[0;31m FAIL \e[0;39m] Email notificaion not enabled" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Email notificaion not enabled" >> ${logfile} + fn_printfailnl "Email notification not enabled" + fn_scriptlog "Email notification not enabled" +fi +sleep 1 +echo -en "\n" +} + +fn_monitorserver(){ +fn_rootcheck +fn_syscheck +if [ ! -f ${lockselfname} ]; then + fn_printinfo "Monitoring ${servicename}: No lock file found: Monitor disabled" + sleep 1 + echo -en "\n" + exit +fi +fn_printdots "Monitoring ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Monitoring ${servername}" +fn_printdots "Monitoring ${servicename}: Checking session: CHECKING" +sleep 1 +fn_scriptlog "Checking session: CHECKING" +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" + sleep 1 + echo -en "\n" + fn_scriptlog "Checking session: OK" + 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 } fn_logmanager(){ -# log manager will active if finds logs older than $logdays -if [ `find ${logdir}/* -mtime +${logdays} |wc -l` -ne "0" ];then - echo -e "[\e[0;32m OK \e[0;39m] Starting log cleaner" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Starting log cleaner" >> ${logfile} - echo -e "[\e[0;36m INFO \e[0;39m] Removing logs older than ${logdays} days" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Removing logs older than ${logdays} days" >> ${logfile} - find ${logdir}/* -mtime +${logdays} |tee >> ${logfile} - count=$(find ${logdir}/* -mtime +${logdays}|wc -l) - find ${logdir}/* -mtime +${logdays} -exec rm {} \; - echo -e "[\e[0;36m INFO \e[0;39m] Log cleaner removed ${count} log files" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Log cleaner removed ${count} log files" >> ${logfile} +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" + sleep 1 + fn_scriptlog "Starting log cleaner" + sleep 1 + echo -en "\n" + fn_printinfo "Removing logs older than ${logdays} days" + sleep 1 + echo -en "\n" + fn_scriptlog "Removing logs older than ${logdays} days" + sleep 1 + find "${scriptlogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}" + find "${consolelogdir}"/* -mtime +${logdays}|tee >> "${scriptlog}" + scriptcount=$(find "${scriptlogdir}"/* -mtime +${logdays}|wc -l) + consolecount=$(find "${consolelogdir}"/* -mtime +${logdays}|wc -l) + count=$((${scriptcount} + ${consolecount})) + find "${scriptlogdir}"/* -mtime +${logdays} -exec rm {} \; + find "${consolelogdir}"/* -mtime +${logdays} -exec rm {} \; + fn_printok "Log cleaner removed ${count} log files" + sleep 1 + echo -en "\n" + fn_scriptlog "Log cleaner removed ${count} log files" fi } fn_restartserver(){ - echo -e "[\e[0;32m OK \e[0;39m] Restarting ${servicename}: ${servername}" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Restarting ${servername}" >> ${logfile} - fn_stopserver - sleep 1 - fn_startserver +fn_scriptlog "Restarting ${servername}" +fn_stopserver +fn_startserver +} + +fn_stopserver(){ +fn_rootcheck +fn_syscheck +pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) +pidwc=$(screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}'|wc -l) + +fn_printdots "Stopping ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Stopping ${servername}" +if [ "${pid}" == "0" ]; then + fn_printfail "Stopping ${servicename}: ${servername} is already stopped" + fn_scriptlog "${servername} is already stopped" +else + #Kill murmur process that spawns separate to tmux process + for s in `tmux list-sessions -F '#{session_name}'` ; do + for pid in `tmux list-panes -s -F '#{pane_pid}' -t "$s"` ; do + kill $pid + done + tmux kill-session -t ${servicename} + fn_printok "Stopping ${servicename}: ${servername}" + fn_scriptlog "Stopped ${servername}" +done +fi +# Remove lock file +rm -f ${lockselfname} +sleep 1 +echo -en "\n" } fn_startserver(){ if [ ! -d ${logdir} ];then mkdir ${logdir} + mkdir ${scriptlogdir} + mkdir ${consolelogdir} echo -e "[\e[0;36m INFO \e[0;39m] ${servicename}: ${servername} Creating log directory ${logdir}" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} Creating log directory ${logdir}" >> ${logfile} + fn_scriptlog " Creating log directory ${logdir}" >> ${scriptlog} fi fn_rootcheck fn_syscheck -fn_runcheck -fn_inicheck fn_logmanager -cd ${filesdir} -if [ -f ${logdir} ];then - cp ${logfile} ${logfiledate} +tmuxwc=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -v failed|grep -E "^${servicename}:"|wc -l) +if [ ${tmuxwc} -eq 0 ]; then + mv "${scriptlog}" "${scriptlogdate}" + mv "${consolelog}" "${consolelogdate}" fi -echo -e "[\e[0;32m OK \e[0;39m] Starting ${servicename}: ${servername}" -echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Starting ${servername}" >> ${logfile} -screen -d -m -S ${servicename} ./murmur.x86 -fg -ini ${ini} +fn_printdots "Starting ${servicename}: ${servername}" sleep 1 -pidwc=$(screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}'|wc -l) -if [ ${pidwc} -eq 0 ];then - echo -e "[\e[0;31m FAIL \e[0;39m] ${servicename}: ${servername} failed to start" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} failed to start" >> ${logfile} +fn_scriptlog "Starting ${servername}" +if [ ${tmuxwc} -eq 1 ]; then + fn_printinfo "Starting ${servicename}: ${servername} is already running" + sleep 1 + echo -en "\n" + fn_scriptlog "${servername} is already running" + exit fi -} - -fn_stopserver(){ -fn_rootcheck -fn_syscheck -pid=$(screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}') -if [ -z ${pid} ];then - echo -e "[\e[0;36m INFO \e[0;39m] ${servicename}: ${servername} is already stopped" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: ${servername} is already stopped" >> ${logfile} +# Create lock file +date > ${lockselfname} +cd ${filesdir} +tmux new-session -d -s ${servicename} "${executable}" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + fn_scriptlog "failed to start ${servername}" else - echo -e "[\e[0;32m OK \e[0;39m] Stopping ${servicename}: ${servername}" - echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Stopping ${servername}" >> ${logfile} - pkill -P `screen -ls |grep -E "^${servicename}:" |awk -F . '{print $1}'|awk '{print $1}'` - screen -wipe > /dev/null 2>&1 + fn_printok "Starting ${servicename}: ${servername}" + fn_scriptlog "Started ${servername}" fi +sleep 1 +echo -en "\n" } fn_debugserver(){ fn_rootcheck fn_syscheck -cd ${filesdir} -if [ -f ${logdir} ];then - cp ${logfile} ${logfiledate} -fi -echo -e "[\e[0;32m OK \e[0;39m] Starting ${servicename}: ${servername} Debug mode!" -sleep 0.5 +echo "" +echo "${gamename} Debug" +echo "============================" +echo "" echo -e "Use for identifying server issues only!" -sleep 2 +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" +echo "Start parameters:" +echo ${executable} +echo "" while true; do - echo "If server is already running it will be stopped" read -p "Continue? [y/N]" yn case $yn in [Yy]* ) break;; - [Nn]* ) echo Exiting; return 1 ;; + [Nn]* ) echo Exiting; return 1;; * ) echo "Please answer yes or no.";; esac done fn_stopserver -echo -e "[\e[0;36m INFO \e[0;39m] ${servicename}: Enter CTRL+C to drop out of debug mode" -sleep 3 -echo -e "[\e[0;32m OK \e[0;39m] Starting ${servicename}: ${servername}" +fn_printdots "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_printok "Starting debug mode ${servicename}: ${servername}" +sleep 1 +fn_scriptlog "Started debug mode ${servername}" +echo -en "\n" +cd ${filesdir} ./murmur.x86 -fg -ini ${ini} } -fn_monitorserver(){ +fn_console(){ fn_rootcheck fn_syscheck -fn_logmanager -echo -e "[\e[0;32m OK \e[0;39m] Checking ${servicename}: ${servername}" -echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Checking ${servername}" >> ${logfile} -fn_runcheck -echo -e "[\e[1;33m WARN \e[0;39m] ${servicename}: Monitor detected ${servername} had stopped!" -echo -e "$( date '+%b %d %H:%M:%S') ${servicename}: Monitor detected ${servername} had stopped!" >> ${logfile} -if [ "${emailnotification}" = "on" ];then - subject="${servicename} Monitor - Starting ${servername}" - failurereason="${servername} had stopped" - actiontaken="restarted ${servername}" - fn_emailnotification +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" + sleep 1 + fn_scriptlog "Console accessed" + 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 -fn_startserver } case "$1" in @@ -305,14 +468,16 @@ case "$1" in fn_restartserver;; monitor) fn_monitorserver;; - debug) - fn_debugserver;; - backup) - fn_backupserver;; email-test) fn_emailtest;; + backup) + fn_backupserver;; + console) + fn_console;; + debug) + fn_debugserver;; *) echo "Usage: $0 {start|stop|restart|monitor|debug|backup|email-test}" exit 1;; esac -exit +exit \ No newline at end of file diff --git a/NaturalSelection2/dependencies/libc.so.6 b/NaturalSelection2/dependencies/libc.so.6 new file mode 100644 index 000000000..ee77b1740 Binary files /dev/null and b/NaturalSelection2/dependencies/libc.so.6 differ diff --git a/NaturalSelection2/ns2server b/NaturalSelection2/ns2server index 167e035a4..a922a93a7 100644 --- a/NaturalSelection2/ns2server +++ b/NaturalSelection2/ns2server @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -17,7 +17,7 @@ steamuser="username" steampass="password" # Start Variables - +rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" defaultmap="ns2_summit" port="27015" maxplayers="24" @@ -26,9 +26,16 @@ servername="NS2 Server" webadminuser="admin" webadminpass="admin" webadminport="8080" +configpath="server1" +modstorage="server1/Workshop" +mods="" password="" +# Add the following line to the parms if you want a private server. Ensuring +# that the password variable above is not left empty. +# -password \"${password}\" + fn_parms(){ -parms="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${webadminuser} -webpassword ${webadminpass} -webport ${webadminport} -map ${defaultmap} -limit ${maxplayers} -password ${password}" +parms="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${webadminuser} -webpassword \"${webadminpass}\" -webport ${webadminport} -map ${defaultmap} -limit ${maxplayers} -config_path \"${rootdir}/${configpath}\" -modstorage \"${rootdir}/${modstorage}\" -mods \"${mods}\"" } #### Advanced Variables #### @@ -40,15 +47,14 @@ servicename="ns2-server" gamename="Natural Selection 2" engine="spark" -# Directorys -rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" +# Directories selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}" executabledir="${filesdir}" executable="./server_linux32" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Logging logdays="7" @@ -69,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -110,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -133,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -155,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -184,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -238,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -290,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -359,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -390,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -406,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -422,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -446,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -460,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -491,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -509,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -528,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -542,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -552,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -564,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -632,14 +682,113 @@ echo "" ## Installer # -fn_ns2deps(){ -echo "Downloading libm.so.6 and libstdc++.so.6" -echo "=================================" -cd "${filesdir}" -wget https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 -wget https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libstdc++.so.6 -sleep 1 -echo "" +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libc.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi } fn_header(){ @@ -661,7 +810,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -680,7 +829,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -700,7 +849,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -723,11 +872,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -766,7 +929,8 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall -fn_ns2deps +fn_getquery +fn_glibcfix fn_header sleep 1 fn_ns2details @@ -791,7 +955,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/NoMoreRoomInHell/nmrihserver b/NoMoreRoomInHell/nmrihserver index cc25a1178..fc866ca7f 100644 --- a/NoMoreRoomInHell/nmrihserver +++ b/NoMoreRoomInHell/nmrihserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -39,9 +39,10 @@ servicename="nmrih-server" gamename="No More Room in Hell" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/nmrih" executabledir="${filesdir}/srcds" @@ -51,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -76,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -117,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -140,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -162,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -191,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -219,7 +239,7 @@ sleep 1 fn_scriptlog "Started debug mode ${servername}" echo -en "\n" cd "${executabledir}" -${executable} ${parms} -debug +${executable} ${parms} -debug -insecure } fn_console(){ @@ -245,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -297,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -366,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -397,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -413,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -429,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -453,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -467,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -498,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -516,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -535,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -549,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -559,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -571,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -618,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -638,14 +682,112 @@ echo "" ## Installer # -fn_nmrihdeps(){ -echo "Downloading libm.so.6" -echo "=================================" -sleep 1 -cd "${filesdir}/srcds" -wget https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 -sleep 1 -echo "" +fn_glibcfix(){ +if [ -z $(command -v ldd) ]; then + echo "" + echo -e "\r\033[K\e[0;31mFAIL\e[0;39m GLIBC is not detected." + sleep 1 + echo "Install GLIBC and retry installation" + sleep 1 + echo "" + while true; do + read -p "Continue install? [y/N]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) echo Exiting; exit;; + * ) echo "Please answer yes or no.";; + esac + done +elif [ "$(ldd --version | sed -n '1 p' | tr -cd [:digit:] | tail -c 3)" -lt 215 ]; then + echo "GLIBC Fix required" + echo "============================" + sleep 1 + echo -e "\e[0;31mWARNING!\e[0;39m ${gamename} requires GLIBC_2.15 or above" + sleep 1 + echo "" + echo "Currently installed: GLIBC_$(ldd --version |grep ldd|awk '{print $NF}')" + echo "Required: => GLIBC_2.15" + echo "" + sleep 1 + echo "The installer will now detect and download the required files to allow ${gamename} server to run on a distro with GLIBC_2.14 or less." + echo "note: This will NOT upgrade GLIBC on your system" + sleep 1 + echo "" + echo "Downloading Required files" + echo "=================================" + sleep 1 + if [ "${gamename}" == "Insurgency" ];then + echo "Detected Insurgency" + sleep 1 + echo "Downloading files for Insurgency GLIBC Fix" + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/librt.so.1 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/Insurgency/dependencies/libpthread.so.0 + sleep 1 + elif [ "${gamename}" == "Garrys's Mod" ];then + echo "Detected Garrys's Mod" + sleep 1 + echo "Downloading files for Garrys's Mod GLIBC Fix" + sleep 1 + cd "${filesdir}/bin" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libc.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libm.so.6 + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/GarrysMod/dependencies/libpthread.so.0 + sleep 1 + echo "" + elif [ "${gamename}" == "Natural Selection 2" ];then + echo "Detected Natural Selection 2" + sleep 1 + echo "Downloading files for Natural Selection 2 GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NaturalSelection2/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "No More Room in Hell" ];then + echo "Detected No More Room in Hell" + sleep 1 + echo "Downloading files for No More Room in Hell GLIBC Fix" + sleep 1 + cd "${filesdir}/srcds" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/NoMoreRoomInHell/dependencies/libm.so.6 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/srcds/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Blade Symphony" ];then + echo "Detected Blade Symphony" + sleep 1 + echo "Downloading files for Blade Symphony GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + elif [ "${gamename}" == "Fistful of Frags" ];then + echo "Detected Fistful of Frags" + sleep 1 + echo "Downloading files for Fistful of Frags GLIBC Fix" + sleep 1 + cd "${filesdir}" + wget -nv -N https://github.com/dgibbs64/linuxgameservers/raw/master/FistfulOfFrags/dependencies/libm.so.6 + sleep 1 + echo "" + elif [ "${gamename}" == "ARMA 3" ];then + echo "Detected ARMA 3" + sleep 1 + echo "Downloading files for ARMA 3 GLIBC Fix" + sleep 1 + cp -v "${rootdir}/steamcmd/linux32/libstdc++.so.6" "${filesdir}/libstdc++.so.6" + sleep 1 + echo "" + else + echo "error: Unable to detect game. Fix not applied" + fi + echo "GLIBC fix has been applied!" + sleep 1 + echo "" +fi } fn_header(){ @@ -667,7 +809,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -686,7 +828,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -706,7 +848,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -729,11 +871,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -772,7 +928,8 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall -fn_nmrihdeps +fn_getquery +fn_glibcfix echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -828,7 +985,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/README.md b/README.md index a477d0126..ef60002f0 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,28 @@ -linuxgameservers -================ +

Linux Game Server Manager

+ +linux game server manager + The Linux Game Server Managers are command line tools for quick, simple deployment and management of various dedicated game servers and voice comms servers. -Main features +

Main features

-Server installer
-Start/Stop/Restart server
-Server updater
-Server monitor (includes optional email notification)
+ +

Compatibility

+The Linux Game Server Manager is tested to work on the following Linux systems. + +The scripts are written in BASH and Python and would probably work with other distros. -Full Documentation and details at: +

Instructions

+Full documentation and instructions can be found here. -http://danielgibbs.co.uk/scripts +http://danielgibbs.co.uk/scripts diff --git a/RedOrchestra/roserver b/RedOrchestra/roserver index fa298fd10..fa50269f2 100644 --- a/RedOrchestra/roserver +++ b/RedOrchestra/roserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -19,9 +19,10 @@ steampass="password" # Steam appid="223250" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/system" executabledir="${systemdir}" @@ -40,20 +41,23 @@ ip="0.0.0.0" # Logging logdays="7" +gamelogdir="${rootdir}/log/server" scriptlogdir="${rootdir}/log/script" consolelogdir="${rootdir}/log/console" +gamelog="${gamelogdir}/${servicename}-game.log" scriptlog="${scriptlogdir}/${servicename}-script.log" consolelog="${consolelogdir}/${servicename}-console.log" emaillog="${scriptlogdir}/${servicename}-email.log" +gamelogdate="${gamelogdir}/${servicename}-game-$(date '+%d-%m-%Y-%H-%M-%S').log" scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" # Start Variables fn_parms(){ defaultmap="RO-Arad.rom" -parms="server ${defaultmap}?game=ROGame.ROTeamGame?VACSecured=true -nohomedir ini=${ini} log=${logfile}" +parms="server ${defaultmap}?game=ROGame.ROTeamGame?VACSecured=true -nohomedir ini=${ini} log=${gamelog}" } ##### Script ##### @@ -62,7 +66,7 @@ parms="server ${defaultmap}?game=ROGame.ROTeamGame?VACSecured=true -nohomedir in # what you are doing 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 ] @@ -103,7 +107,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -126,8 +130,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -148,28 +152,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -177,18 +193,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -231,8 +255,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -283,8 +307,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -352,9 +376,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -383,13 +407,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -399,9 +425,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -415,14 +440,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -439,9 +464,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -453,19 +478,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -484,11 +517,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -502,7 +535,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -521,7 +554,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -535,8 +568,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -545,6 +578,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -557,26 +592,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -700,7 +748,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -719,7 +767,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -739,7 +787,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -762,11 +810,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -805,6 +867,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -860,7 +923,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/TeamFortress2/tf2server b/TeamFortress2/tf2server index 66b203354..7d9c206a8 100644 --- a/TeamFortress2/tf2server +++ b/TeamFortress2/tf2server @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -17,9 +17,8 @@ steamuser="anonymous" steampass="" # Start Variables -defaultmap="de_dust2" +defaultmap="cp_badlands" maxplayers="16" -tickrate="64" port="27015" sourcetvport="27020" clientport="27005" @@ -27,7 +26,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Source_Dedicated_Server fn_parms(){ -parms="-game tf -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game tf -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -40,9 +39,10 @@ servicename="tf2-server" gamename="Team Fortress 2" engine="source" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/tf" executabledir="${filesdir}" @@ -52,7 +52,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -77,7 +76,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -118,7 +117,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -141,8 +140,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -163,28 +162,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -192,18 +203,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -246,8 +265,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -298,8 +317,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -367,9 +386,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -398,13 +417,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -414,9 +435,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -430,14 +450,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -454,9 +474,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -468,19 +488,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -499,11 +527,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -517,7 +545,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -536,7 +564,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -550,8 +578,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -560,6 +588,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -572,26 +602,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -619,7 +662,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -658,7 +701,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -677,7 +720,7 @@ 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 +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -697,7 +740,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -720,11 +763,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -763,6 +820,7 @@ fn_steamdl fn_steaminstall fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -818,7 +876,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/TeamFortressClassic/tfcserver b/TeamFortressClassic/tfcserver index 7d5c5978d..2ae86e816 100644 --- a/TeamFortressClassic/tfcserver +++ b/TeamFortressClassic/tfcserver @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -25,7 +25,7 @@ ip="0.0.0.0" # https://developer.valvesoftware.com/wiki/Command_Line_Options#Command-line_parameters_2 fn_parms(){ -parms="-game tfc -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" +parms="-game tfc -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +map ${defaultmap} -maxplayers ${maxplayers}" } #### Advanced Variables #### @@ -38,9 +38,10 @@ servicename="tfc-server" gamename="Team Fortress Classic" engine="goldsource" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/tfc" executabledir="${filesdir}" @@ -50,7 +51,6 @@ servercfg="${servicename}.cfg" servercfgfullpath="${servercfgdir}/${servercfg}" defaultcfg="${servercfgdir}/server.cfg" backupdir="backups" -steamclient="${rootdir}/steamcmd/linux32/steamclient.so" # Server Details servername=$(grep -s hostname "${servercfgfullpath}"|sed 's/hostname //g'|sed 's/"//g') @@ -75,7 +75,7 @@ consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M- # what you are doing 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 ] @@ -116,7 +116,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -139,8 +139,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -161,28 +161,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -190,18 +202,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -244,8 +264,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -296,8 +316,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -365,9 +385,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -396,13 +416,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -412,9 +434,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -428,14 +449,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -452,9 +473,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -466,19 +487,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -497,11 +526,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -515,7 +544,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} +quit|tee -a "${scriptlog}" } fn_validateserver(){ @@ -534,7 +563,7 @@ 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}" +./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit|tee -a "${scriptlog}" } fn_restartserver(){ @@ -548,8 +577,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -558,6 +587,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -570,26 +601,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -617,7 +661,7 @@ echo "Ports the server is currently using." echo "" echo "DIRECTION DESCRIPTION PORT" echo "INBOUND Game/RCON port ${port}" -if [ "${engine}" = "source" ]; then +if [ ! -z ${sourcetvport} ]; then echo "INBOUND SourceTV port ${sourcetvport}" fi echo "OUTBOUND Client port ${clientport}" @@ -637,33 +681,6 @@ echo "" ## Installer # -fn_tfcappmanifest(){ -appdir="${filesdir}/5cf8446bee28893dd1ff1867b48c26ae8f14e1e7" -if [ ${pass} == 1 ]; then - echo "Creating appmanifest directory. (app 90 fix)" - sleep 2 - mkdir -v "${filesdir}" - mkdir -v "${appdir}" - cd "${appdir}" - echo "Removing any existing appmanifest files. (app 90 fix)" - sleep 2 - rm -f appmanifest_10.acf appmanifest_70.acf appmanifest_90.acf -elif [ ${pass} == 2 ]; then - echo "Downloading HLDS appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_10.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_70.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/appmanifest_90.acf -elif [ ${pass} == 3 ]; then - echo "Downloading ${gamename} appmanifest files. (app 90 fix)" - sleep 2 - cd "${appdir}" - rm -f appmanifest_90.acf - wget https://raw.github.com/dgibbs64/linuxgameservers/master/appmanifest/tfc/appmanifest_90.acf -fi -} - fn_header(){ clear echo "=================================" @@ -683,7 +700,7 @@ mkdir -pv "steamcmd" sleep 1 cd "steamcmd" if [ ! -f steamcmd.sh ]; then - wget http://media.steampowered.com/client/steamcmd_linux.tar.gz + 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 @@ -697,13 +714,12 @@ echo "" } 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 -} - -fn_success(){ +STEAMEXE=steamcmd ./steamcmd.sh +login ${steamuser} "${steampass}" +force_install_dir "${filesdir}" +app_update ${appid} validate +quit echo "" echo "=================================" while true; do @@ -723,7 +739,7 @@ echo "=================================" sleep 1 mkdir -pv "${HOME}/.steam" mkdir -pv "${HOME}/.steam/sdk32" -cp -v "${steamclient}" "${HOME}/.steam/sdk32/steamclient.so" +cp -v "${rootdir}/steamcmd/linux32/steamclient.so" "${HOME}/.steam/sdk32/steamclient.so" sleep 1 echo "" } @@ -746,11 +762,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -786,22 +816,13 @@ while true; do done fn_header fn_steamdl -echo "Installing ${gamename} Server" -echo "=================================" -pass=1 -fn_tfcappmanifest -pass=2 -fn_tfcappmanifest fn_steaminstall fn_steaminstall -pass=3 -fn_tfcappmanifest fn_steaminstall fn_steaminstall -fn_steaminstall -fn_success fn_steamfix fn_loginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 @@ -881,7 +902,7 @@ case "$1" in update-restart) fn_stopserver fn_updateserver - fn_startserver;; + fn_startserver;; validate) fn_validateserver;; validate-restart) diff --git a/UnrealTournament2004/ut2k4server b/UnrealTournament2004/ut2k4server index e2b825730..00654ca10 100644 --- a/UnrealTournament2004/ut2k4server +++ b/UnrealTournament2004/ut2k4server @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -12,14 +12,14 @@ emailnotification="off" email="email@example.com" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/System" executabledir="${systemdir}" executable="./ucc-bin" -executable64="./ucc-bin-linux-amd64" compressedmapsdir="${rootdir}/Maps-Compressed" defaultcfg="${systemdir}/UT2004.ini" backupdir="backups" @@ -34,20 +34,23 @@ ip="0.0.0.0" # Logging logdays="7" +gamelogdir="${rootdir}/log/server" scriptlogdir="${rootdir}/log/script" consolelogdir="${rootdir}/log/console" +gamelog="${gamelogdir}/${servicename}-game.log" scriptlog="${scriptlogdir}/${servicename}-script.log" consolelog="${consolelogdir}/${servicename}-console.log" emaillog="${scriptlogdir}/${servicename}-email.log" +gamelogdate="${gamelogdir}/${servicename}-game-$(date '+%d-%m-%Y-%H-%M-%S').log" scriptlogdate="${scriptlogdir}/${servicename}-script-$(date '+%d-%m-%Y-%H-%M-%S').log" consolelogdate="${consolelogdir}/${servicename}-console-$(date '+%d-%m-%Y-%H-%M-%S').log" # Start Variables fn_parms(){ defaultmap="DM-Rankin" -parms="server ${defaultmap}?game=XGame.xDMGame -nohomedir ini=${ini} log=${logfile}" +parms="server ${defaultmap}?game=XGame.xDeathMatch -nohomedir ini=${ini} log=${gamelog}" } ##### Script ##### @@ -56,7 +59,7 @@ parms="server ${defaultmap}?game=XGame.xDMGame -nohomedir ini=${ini} log=${logfi # what you are doing 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 ] @@ -97,7 +100,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -120,8 +123,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -142,28 +145,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -171,18 +186,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -199,11 +222,7 @@ sleep 1 fn_scriptlog "Started debug mode ${servername}" echo -en "\n" cd "${executabledir}" -if [ `getconf LONG_BIT` = "64" ]; then - ${executable64} ${parms} -else - ${executable} ${parms} -fi +${executable} ${parms} } fn_console(){ @@ -229,8 +248,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -281,8 +300,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -350,9 +369,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -381,13 +400,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -397,9 +418,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -413,14 +433,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -437,9 +457,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -451,19 +471,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -482,11 +510,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -501,8 +529,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -511,6 +539,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -523,30 +553,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -if [ `getconf LONG_BIT` = "64" ]; then - tmux new-session -d -s ${servicename} "${executable64} ${parms}|tee -a '${consolelog}'" -else - tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" -fi +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -673,7 +712,7 @@ cd "${rootdir}" mkdir -pv "${filesdir}" cd "${filesdir}" if [ ! -f dedicatedserver3339-bonuspack.zip ]; then - wget http://downloads.unrealadmin.org/UT2004/Server/dedicatedserver3339-bonuspack.zip + wget -nv -N http://downloads.unrealadmin.org/UT2004/Server/dedicatedserver3339-bonuspack.zip else echo "dedicatedserver3339-bonuspack.zip already downloaded!" fi @@ -694,7 +733,7 @@ else echo "MD5 checksum: PASSED" fi if [ ! -f ut2004-lnxpatch3369-2.tar.bz2 ]; then - wget http://downloads.unrealadmin.org/UT2004/Patches/Linux/ut2004-lnxpatch3369-2.tar.bz2 + 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 @@ -780,15 +819,31 @@ mkdir -pv "${scriptlogdir}" touch "${scriptlog}" mkdir -pv "${consolelogdir}" touch "${consolelog}" +mkdir -pv "${gamelogdir}" +touch "${gamelog}" sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -827,6 +882,7 @@ fn_ut2k4filesdl fn_ut2k4install fn_ut2k4key fn_utloginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1 diff --git a/UnrealTournament99/ut99server b/UnrealTournament99/ut99server index 7aedb1a44..646be59a6 100644 --- a/UnrealTournament99/ut99server +++ b/UnrealTournament99/ut99server @@ -3,7 +3,7 @@ # Server Management Script # Author: Daniel Gibbs # Website: http://danielgibbs.co.uk -# Version: 050214 +# Version: 061014 #### Variables #### @@ -12,9 +12,10 @@ emailnotification="off" email="email@example.com" -# Directorys +# Directories rootdir="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" selfname="$0" +lockselfname=$(echo ".${servicename}.lock") filesdir="${rootdir}/serverfiles" systemdir="${filesdir}/System" executabledir="${systemdir}" @@ -55,7 +56,7 @@ parms="server ${defaultmap}.unr ini=${systemdir}/${ini}" # what you are doing 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 ] @@ -96,7 +97,7 @@ fn_printwarn(){ fn_printwarnnl(){ echo -e "\r\033[K[\e[1;33m WARN \e[0;39m] $@" } - + # [ .... ] fn_printdots(){ echo -en "\r\033[K[ .... ] $@" @@ -119,8 +120,8 @@ fi 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.1) -getipwc=$(ip -o -4 addr|awk '{print $4 }'|grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}'|grep -v 127.0.0.1|wc -l) +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" @@ -141,28 +142,40 @@ 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 + sleep 1 fn_printok "Starting log cleaner" - sleep 1 fn_scriptlog "Starting log cleaner" sleep 1 echo -en "\n" fn_printinfo "Removing logs older than ${logdays} days" - sleep 1 - echo -en "\n" 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" - fn_scriptlog "Log cleaner removed ${count} log files" fi } @@ -170,18 +183,26 @@ fn_debugserver(){ fn_rootcheck fn_syscheck fn_autoip +fn_distro +fn_uptime +fn_load fn_parms echo "" echo "${gamename} Debug" echo "============================" echo "" -echo -e "Use for identifying server issues only!" -echo -e "Press CTRL+c to drop out of debug mode" -echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo -e "Distro: ${os}" +echo -e "Arch: ${arch}" +echo -e "Kernel: ${kernel}" +echo -e "Hostname: $HOSTNAME" echo "" echo "Start parameters:" echo ${parms} echo "" +echo -e "Use for identifying server issues only!" +echo -e "Press CTRL+c to drop out of debug mode" +echo -e "\e[0;31mWARNING!\e[0;39m If ${servicename} is already running it will be stopped" +echo "" while true; do read -p "Continue? [y/N]" yn case $yn in @@ -224,8 +245,8 @@ 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" - sleep 1 fn_scriptlog "Console accessed" + sleep 1 tmux attach-session -t ${servicename} else fn_printfailnl "Starting ${servicename} console: ${servername} not running" @@ -276,8 +297,8 @@ fi fn_printdots "Starting backup ${servicename}: ${servername}" sleep 1 fn_printok "Starting backup ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Backup started" +sleep 1 echo -en "\n" cd "${rootdir}" mkdir -pv "${backupdir}" > /dev/null 2>&1 @@ -345,9 +366,9 @@ if [ ! -z "${gamelogdir}" ]; then 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" -fn_scriptlog "Sent email notification to ${email}" } fn_emailtest(){ @@ -376,13 +397,15 @@ if [ -f gsquery.py ]; then port=$((${gameport} + 1)) elif [ "${engine}" == "spark" ]; then port=$((${port} + 1)) + elif [ "${engine}" == "realvirtuality" ]; then + port=${queryport} fi fn_printinfo "Monitoring ${servicename}: Detected gsquery.py" - sleep 1 fn_scriptlog "Detected gsquery.py" + sleep 1 fn_printdots "Monitoring ${servicename}: Querying port: ${ip}:${port}: QUERYING" - sleep 1 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 @@ -392,9 +415,8 @@ if [ -f gsquery.py ]; then fn_scriptlog "Querying port: ${ip}:${port}: ${serverquery}" if [[ -z "${secondquery}" ]]; then fn_printinfo "Monitoring ${servicename}: Waiting 30 seconds to re-query" - sleep 1 fn_scriptlog "Waiting 30 seconds to re-query" - sleep 29 + sleep 30 secondquery=1 fn_serverquery fi @@ -408,14 +430,14 @@ if [ -f gsquery.py ]; then exit elif [ "${exitcode}" == "0" ]; then fn_printok "Monitoring ${servicename}: Querying port: ${ip}:${port}: OK" - sleep 1 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" - sleep 1 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 @@ -432,9 +454,9 @@ if [ -f gsquery.py ]; then 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" - fn_scriptlog "Querying port: ${ip}:${port}: UNKNOWN ERROR" ./gsquery.py -a ${ip} -p ${port} -e ${engine} exit fi @@ -446,19 +468,27 @@ fn_rootcheck fn_syscheck fn_autoip fn_printdots "Monitoring ${servicename}: ${servername}" -sleep 1 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" - sleep 1 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" - sleep 1 - echo -en "\n" fn_scriptlog "Checking session: OK" + sleep 1 + echo -en "\n" fn_serverquery exit else @@ -477,11 +507,11 @@ if [ "${updatecheck}" = "0" ]; then fi else fn_printinfonl "Monitoring ${servicename}: Detected SteamCMD is checking for updates" - sleep 1 fn_scriptlog "Detected SteamCMD is checking for updates" + sleep 1 fn_printinfonl "Monitoring ${servicename}: When updates complete ${servicename} will start" - sleep 1 fn_scriptlog "When updates complete ${servicename} will start" + sleep 1 fi } @@ -496,8 +526,8 @@ fn_rootcheck fn_syscheck pid=$(tmux list-sessions 2>&1|awk '{print $1}'|grep -E "^${servicename}:"|wc -l) fn_printdots "Stopping ${servicename}: ${servername}" -sleep 1 fn_scriptlog "Stopping ${servername}" +sleep 1 if [ "${pid}" == "0" ]; then fn_printfail "Stopping ${servicename}: ${servername} is already stopped" fn_scriptlog "${servername} is already stopped" @@ -506,6 +536,8 @@ else fn_printok "Stopping ${servicename}: ${servername}" fn_scriptlog "Stopped ${servername}" fi +# Remove lock file +rm -f ${lockselfname} sleep 1 echo -en "\n" } @@ -518,26 +550,39 @@ 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}" -sleep 1 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" - fn_scriptlog "${servername} is already running" exit fi +# Create lock file +date > "${rootdir}/${lockselfname}" cd "${executabledir}" -tmux new-session -d -s ${servicename} "${executable} ${parms}|tee -a '${consolelog}'" +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_printfail "Starting ${servicename}: Failed to start ${servername}" + 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} + rm ${scriptlogdir}/.${servicename}-tmux-error.tmp + fi else fn_printok "Starting ${servicename}: ${servername}" fn_scriptlog "Started ${servername}" @@ -660,7 +705,7 @@ cd "${rootdir}" mkdir -pv "${filesdir}" cd "${filesdir}" if [ ! -f ut-server-436.tar.gz ]; then - wget http://danielgibbs.co.uk/wp-content/uploads/ut-server-436.tar.gz + 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 @@ -681,7 +726,7 @@ else echo "MD5 checksum: PASSED" fi if [ ! -f UTPGPatch451.tar.bz2 ]; then - wget http://danielgibbs.co.uk/wp-content/uploads/UTPGPatch451.tar.bz2 + wget -nv -N http://danielgibbs.co.uk/wp-content/uploads/UTPGPatch451.tar.bz2 else echo "UTPGPatch451.tar.bz2 already downloaded!" fi @@ -757,11 +802,25 @@ sleep 1 echo "" } +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 "" +} + fn_retryinstall(){ while true; do read -p "Retry install? [y/N]" yn case $yn in - [Yy]* ) fn_install;; + [Yy]* ) fn_install; exit;; [Nn]* ) echo Exiting; exit;; * ) echo "Please answer yes or no.";; esac @@ -799,6 +858,7 @@ fn_header fn_ut99filesdl fn_ut99install fn_utloginstall +fn_getquery echo "Configuring ${gamename} Server" echo "=================================" sleep 1