#!/bin/sh # # (C) 2018 Dawid Gan, under the GPLv3 # # A script that manages STK servers # export SELF_PID=$$ export BASENAME="$(basename "$0")" export DIRNAME="$(readlink -e "$(dirname "$0")")" export DATETIME="$(date +%Y%m%d%H%M%S)" ############## General info ############## # Usage: # # Start all servers and close the script: # run_server.sh start # # Start all servers and keep the script running and testing if servers are # alive: # run_server.sh startdaemon # # Stop all servers and close the running daemon: # run_server.sh stop # # By default the script works with following directories structure # --- stk-server/ # ----- data/ # ----- supertuxkart # ----- run_server.sh ################# Config ################# ### General ### # Server name, make sure that it's unique export SERVER_NAME="STK Server" # Login for STK account export LOGIN="xxx" # Password for STK account export PASS="yyy" ### Paths ### # A path for STK server binary file export CMD="$DIRNAME/supertuxkart" # A path in which "data" directory is placed export SUPERTUXKART_DATADIR="$DIRNAME" # A path for STK assets export SUPERTUXKART_ASSETS_DIR="$DIRNAME/data/" # A path for configuration files export HOME="/tmp/stk-server/.config" # A path where logs will be saved export STDOUT_DIR="/tmp/stk-server/" ### Daemon mode ### # How often the script should check if servers are alive export SLEEP_TIME=60 # How many times the script should try to recreate servers export MAX_CREATION_RETRIES=50 # Determines if the script should parse stdout.log files to see if servers are # alive. Set it to 0 to disable. export CHECK_SERVERS=1 # A path to the application that can be used to show GUI messages when error # ocurred, server crashed etc. Atm. it will only work with xmessage/gxmessage. # Zenity and other apps need additional args. export MESSAGE_CMD="/usr/bin/xmessage" # Max number of messages that can be showed at the same time. Set it to 0 to # disable. export MAX_MESSAGES=3 ########################################## show_message() { export MESSAGE="$1" if [ -z "$MESSAGE" ]; then return fi echo "$MESSAGE" if [ ! -x "$MESSAGE_CMD" ]; then return fi if [ ! -z "$TERM" ] && [ "$TERM" != "dumb" ]; then return fi if [ $(pidof -x "$MESSAGE_CMD" | wc -w) -ge $MAX_MESSAGES ]; then return fi "$MESSAGE_CMD" "$MESSAGE" & } run_servers() { echo "Info: Run servers" "$CMD" --ranked \ --max-players=8 \ --min-players=2 \ --difficulty=2 \ --mode=0 \ --port=2760 \ --wan-server="$SERVER_NAME" \ --stdout="$DATETIME-normal.log" \ --stdout-dir="$STDOUT_DIR" \ --no-console-log \ --log=0 &> /dev/null & sleep 5 "$CMD" --owner-less \ --disable-polling \ --max-players=8 \ --min-players=2 \ --difficulty=2 \ --mode=3 \ --soccer-goals \ --port=2761 \ --wan-server="$SERVER_NAME Soccer" \ --stdout="$DATETIME-soccer.log" \ --stdout-dir="$STDOUT_DIR" \ --no-console-log \ --log=0 &> /dev/null & sleep 5 "$CMD" --owner-less \ --disable-polling \ --max-players=8 \ --min-players=2 \ --difficulty=2 \ --mode=2 \ --battle-mode=1 \ --port=2762 \ --wan-server="$SERVER_NAME CTF" \ --stdout="$DATETIME-ctf.log" \ --stdout-dir="$STDOUT_DIR" \ --no-console-log \ --log=0 &> /dev/null & sleep 5 } init_servers() { echo "Info: Init servers" mkdir -p "$STDOUT_DIR" "$CMD" --init-user \ --login="$LOGIN" \ --password="$PASS" \ --stdout="$DATETIME-init.log" \ --stdout-dir="$STDOUT_DIR" \ --no-console-log \ --log=0 &> /dev/null sleep 5 } stop_servers() { echo "Info: Stop servers" for PID in $(pidof -x "$CMD"); do echo "Info: Killing the STK server $PID" kill -15 $PID done sleep 10 for PID in $(pidof -x "$CMD"); do echo "Info: Force killing the STK server $PID" kill -9 $PID done } check_servers() { export SUCCESS=1 for FILE in $(find "$STDOUT_DIR" -type f -name "$DATETIME-*.log"); do echo "Info: Check file: $FILE" FILE_BEGIN=$(cat "$FILE" | head -n100) if [ $(echo $FILE_BEGIN | grep -c "Done saving user, leaving") -gt 0 ]; then echo "Info: Check server: Servers successfully initialized" elif [ $(echo $FILE_BEGIN | grep "Server" | grep -c "is now online.") -gt 0 ]; then echo "Info: Check server: Servers successfully created" elif [ $(echo $FILE_BEGIN | grep -c "Specified server already exists.") -gt 0 ]; then show_message "Error: Check server: Specified server already exists" SUCCESS=0 else show_message "Error: Check server: Unknown error" SUCCESS=0 fi FILE_END=$(cat "$FILE" | tail -n50) if [ $(echo $FILE_END | grep -c "Session not valid. Please sign in.") -gt 0 ]; then show_message "Error: Check server: Session not valid" SUCCESS=0 elif [ $(echo $FILE_END | grep curl_easy_perform | grep -c "Timeout was reached") -gt 0 ]; then show_message "Error: Check server: Timeout was reached" SUCCESS=0 fi done return $SUCCESS } start() { if [ ! -z $(pidof -x "$DIRNAME/$BASENAME" -o $SELF_PID) ]; then show_message "Error: The script is already started" exit fi if [ ! -z $(pidof -s -x "$CMD") ]; then show_message "Error: Some servers are already running" exit fi if [ ! -f "$CMD" ]; then show_message "Error: Couldn't find STK executable in CMD: $CMD" exit fi if [ ! -d "$SUPERTUXKART_DATADIR/data" ]; then show_message "Error: Couldn't find data directory in SUPERTUXKART_DATADIR: $SUPERTUXKART_DATADIR" exit fi if [ ! -d "$SUPERTUXKART_ASSETS_DIR/tracks" ]; then show_message "Error: Couldn't find assets directories in SUPERTUXKART_ASSETS_DIR: $SUPERTUXKART_ASSETS_DIR" exit fi init_servers run_servers if [ $CHECK_SERVERS -eq 1 ]; then check_servers fi echo "Info: Servers started" } startdaemon() { start export SERVERS_COUNT=$(pidof -x "$CMD" | wc -w) export SERVER_OK=1 export LOOP=0 while [ $LOOP -lt $MAX_CREATION_RETRIES ]; do if [ $(pidof -x "$CMD" | wc -w) -lt $SERVERS_COUNT ]; then SERVER_OK=0 fi if [ $SERVER_OK -eq 1 ] && [ $CHECK_SERVERS -eq 1 ]; then check_servers SERVER_OK=$? fi if [ $SERVER_OK -eq 0 ]; then show_message "Error: Some servers don't work, restart is needed" stop_servers DATETIME="$(date +%Y%m%d%H%M%S)" init_servers run_servers SERVERS_COUNT=$(pidof -x "$CMD" | wc -w) SERVER_OK=1 LOOP=$(($LOOP + 1)) fi sleep $SLEEP_TIME done $MESSAGE_CMD "Error: Closing STK server" } stop() { for PID in $(pidof -x "$DIRNAME/$BASENAME" -o $SELF_PID); do echo "Info: Killing the $BASENAME script $PID" kill -9 $PID done stop_servers } if [ "$1" = "startdaemon" ] && [ "$2" != "disown" ]; then sleep 5 && "$DIRNAME/$BASENAME" "$1" disown & exit fi if [ "$1" = "start" ]; then start elif [ "$1" = "startdaemon" ]; then startdaemon elif [ "$1" = "stop" ]; then stop else show_message "Error: The script must be started with start/startdaemon/stop command" fi