Skip to content

Instantly share code, notes, and snippets.

@fernandofig
Created August 1, 2015 00:33
Show Gist options
  • Save fernandofig/7ecc8591bea467cc2005 to your computer and use it in GitHub Desktop.
Save fernandofig/7ecc8591bea467cc2005 to your computer and use it in GitHub Desktop.
Init.d script for starting multiple and concurrent Terraria Server instances
#!/bin/bash
### BEGIN INIT INFO
# Provides: terraria_server
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Start/stop terraria_server
### END INIT INFO
DESC="TShock Terraria Server"
USERID=terraria
BINDIR=/home/terraria
SCREENDAEMON=$(which screen)
#MONODAEMON=$(which mono)
MONODAEMON=$(which mono-sgen) # an experimental version of mono with a more efficient memory handler: apt-get install mono-sgen
#MONODAEMON=$(which mono-boehm) # an experimental version of mono with a more efficient memory handler: apt-get install mono-sgen
WORLDS="World1"
. /etc/default/terraria-server
# All important args for TerrariaServer.exe
DAEMONARGS="-ip 0.0.0.0 -maxplayers 8"
# Command sent to server to exit, try just "exit" to save world before exit. You WILL need to increase EXIT_TIMEOUT (try 30+)
#EXIT_COMMAND="exit-nosave"
EXIT_COMMAND="exit"
# wait X seconds for terraria to exit
#EXIT_TIMEOUT=5
EXIT_TIMEOUT=30
# Exit if not lib functions
[ -r /lib/lsb/init-functions ] || exit 0
. /lib/lsb/init-functions
# Exit if screen cant be found
[ -x "${SCREENDAEMON}" ] || exit 0
# Exit if mono cant be found
[ -x "${MONODAEMON}" ] || exit 0
# Exit if base directory for instances cant be found
[ -d "${BINDIR}" ] || exit 0
# Exit if no Worlds specified
[ -n "${WORLDS}" ] || exit 0
checkScreen() {
#INST_NAME=${NAME}
if [ -e /var/run/screen/S-${USERID}/*.${INST_NAME} ]; then return 0; fi
return 1
}
checkPID() {
#INST_PATH=${BINDIR}
PIDFILE=${INST_PATH}/tshock/tshock.pid
if [ -e ${PIDFILE} ] && kill -0 $(cat ${PIDFILE} 2>/dev/null) > /dev/null 2>&1; then return 0; fi
return 1
}
cd ${BINDIR}
case "$1" in
start)
OIFS=$IFS
IFS=","
for WLD in $WORLDS; do
INST_PATH=$BINDIR/$WLD
INST_NAME="Terraria_Inst_${WLD}"
rm -f $INST_PATH/ServerLog.txt
find $INST_PATH/tshock/ -maxdepth 1 -iname "*.log" -exec mv {} $INST_PATH/tshock/oldlogs/ \;
log_daemon_msg "Starting TShock instance ${WLD} ... "
EC=1
if [ ! -d "${INST_PATH}" ]; then
log_progress_msg "ERR: Instance folder not found.";
elif [ ! -r "${INST_PATH}/TerrariaServer.exe" ]; then
log_progress_msg "ERR: Instance Daemon not found.";
elif checkScreen || checkPID; then
log_progress_msg "(already running)";
else
su ${USERID} -c "cd ${INST_PATH}; ${SCREENDAEMON} -dmS ${INST_NAME} ${MONODAEMON} ${INST_PATH}/TerrariaServer.exe ${DAEMONARGS} -world ${INST_PATH}/Terraria/Worlds/${WLD}.wld";
# Wait up to 5 seconds for it to start
for i in {0..5}; do
if checkPID; then EC=0; break; fi # found running PID
sleep 1
done
fi
log_end_msg $EC
done
IFS=$OIFS
;;
debug)
OIFS=$IFS
IFS=","
if [ -n "$2" ]; then
WLD=$2
INST_PATH=$BINDIR/$WLD
rm -f $INST_PATH/ServerLog.txt
find $INST_PATH/tshock/ -maxdepth 1 -iname "*.log" -exec mv {} $INST_PATH/tshock/oldlogs/ \;
if [ ! -d "${INST_PATH}" ]; then
echo "ERR: Instance folder not found.";
elif [ ! -r "${INST_PATH}/TerrariaServer.exe" ]; then
echo "ERR: Instance Daemon not found.";
elif checkPID; then
echo "Server instance for this world already running on background!";
else
su ${USERID} -c "cd ${INST_PATH}; ${INST_NAME} ${MONODAEMON} ${INST_PATH}/TerrariaServer.exe ${DAEMONARGS} -world ${INST_PATH}/Terraria/Worlds/${WLD}.wld";
fi
else
echo "You should provide an instance name (according to the WORLDS config variable)"
fi
IFS=$OIFS
;;
stop)
OIFS=$IFS
IFS=","
for WLD in $WORLDS; do
INST_PATH=$BINDIR/$WLD
INST_NAME="Terraria_Inst_${WLD}"
log_daemon_msg "Stopping TShock instance ${WLD} ... "
EC=1
if [ ! -d "${INST_PATH}" ]; then
log_progress_msg "ERR: Instance folder not found.";
elif [ ! -r "${INST_PATH}/TerrariaServer.exe" ]; then
log_progress_msg "ERR: Instance Daemon not found.";
elif ! checkScreen || ! checkPID; then
log_progress_msg "(not running, or stale pidfile)";
else
# Use screen to stuff text to console
su "${USERID}" -c 'screen -dr '${INST_NAME}' -X stuff "'${EXIT_COMMAND}'$(printf \\r)"'
# Wait for the process to end
n=${EXIT_TIMEOUT}
for (( i=0; i<n; i++ )); do
if ! checkScreen; then EC=0; break; fi;
sleep 1;
done
fi
log_end_msg $EC
done
IFS=$OIFS
;;
restart)
$0 stop
$0 start
;;
connect)
if [ -n "$2" ]; then
INST_NAME="Terraria_Inst_$2"
if checkScreen; then
# Use script to bypass TTY issues
su "${USERID}" -c "script -qc \"screen -dr ${INST_NAME}\" /dev/null"
else
echo "${INST_NAME}: Connect failed. (screen not running or no instance with that name found)"
fi
else
echo "You should provide an instance name (according to the WORLDS config variable)"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|connect <inst>}" 2>&1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment