PDA

View Full Version : Linux init script to start server on boot (scripts only)



siosios
03-15-2009, 07:18 PM
add this script to your /etc/init.d directory



#!/bin/sh
# Source Dedicated Server Init Script

# Server options
TITLE='Source Dedicated Server' # Script initialization title
LONGNAME='Team Fortress 2' # Full title of game type
NAME='tf2' # Server handle for the screen session
DAEMON='srcds_run' # The server daemon
STEAM='/home/tf2/orangebox' # STEAM to Steam installation
USER='tf2'

# Game options
IP='72.52.248.250' # IP of the server
PORT='27015' # Port number to
MAP='ctf_2fort' # Initial map to start
GAME='tf' # Game type (tf|cstrike|valve|hl2mp)
SIZE='24' # Maximum number of players

# Server options string
OPTS="-game $GAME +hostname \"$CLIENT\" +map $MAP +ip $IP -port $PORT \
-autoupdate +maxplayers $SIZE -pidfile $STEAM/$GAME/$NAME.pid"

# Screen command
INTERFACE="/usr/bin/screen -A -m -d -S $NAME"

service_start() {
# Check if the pid files currently exist
if [ ! -f $STEAM/$GAME/$NAME.pid ] && [ ! -f $STEAM/$GAME/$NAME-screen.pid ]; then
if [ -x $STEAM/$DAEMON ]; then
echo "Starting $TITLE - $LONGNAME"
echo "Server IP: $IP"
echo "Server port: $PORT"
echo "Server size: $SIZE players"
cd $STEAM
$INTERFACE $STEAM/$DAEMON $OPTS
# Prevent race condition on SMP kernels
sleep 1
# Find and write current process id of the screen process
ps -ef | grep SCREEN | grep "$NAME" | grep -v grep | awk '{ print $2}' > $STEAM/$GAME/$NAME-screen.pid
echo "$TITLE screen process ID written to $STEAM/$GAME/$NAME-screen.pid"
echo "$TITLE server process ID written to $STEAM/$GAME/$NAME.pid"

echo "$TITLE started."
fi
else
echo -e "Cannot start $TITLE. Server is already running."
#exit 1
fi
}

service_stop() {
if [ -f $STEAM/$GAME/$NAME.pid ] && [ -f $STEAM/$GAME/$NAME-screen.pid ]; then
echo "Stopping $TITLE - $LONGNAME."
# Get the process ID from the pid file we created earlier
for id in `cat $STEAM/$GAME/$NAME-screen.pid`
do kill -9 $id
echo "Killing process ID $id"
echo "Removing $TITLE screen pid file"
rm -rf $STEAM/$GAME/$NAME-screen.pid
break
done
# Remove server pid file
echo "Removing $TITLE pid file"
rm -rf $STEAM/$GAME/$NAME.pid
# Wipe all old screen sessions
screen -wipe 1> /dev/null 2> /dev/null
echo "$TITLE stopped."
else
echo -e "Cannot stop $TITLE. Server is not running."
#exit 1
fi
}


case "$1" in
'start')
service_start
;;
'stop')
service_stop
;;
'restart')
service_stop
sleep 1
service_start
;;
*)
echo "Usage $0 start|stop|restart"
esac






#Source Dedicated Server Init Script

# Server options
TITLE='Source Dedicated Server' # Script initialization title
LONGNAME='Team Fortress 2' # Full title of game type
NAME='tf2' # Server handle for the screen session
DAEMON='srcds_run' # The server daemon
UPDATER='/usr/srcds' # The Steam updater. I recommend keeping it one directory below orangebox for tf2 servers.
STEAM='/usr/srcds/orangebox' # STEAM to Steam installation
USER='srcds' # User that this will be running under. Currently not functional part of this script.

# Game options
CLIENT='Team Fortress 2' #Game Server name.
IP='127.0.0.1' # IP of the server
PORT='27015' # Port number to
MAP='ctf_2fort' # Initial map to start
GAME='tf' # Game type (tf|cstrike|valve|hl2mp)
SIZE='32' # Maximum number of players
HIGHPRIORITY=1 #Set server renice to -20 will make server take priority over all other applications on server. 1 being on and 0 being off.

# Server options string
OPTS="-game $GAME +hostname \"$CLIENT\" +map $MAP +ip $IP -port $PORT \
-autoupdate +maxplayers $SIZE -pidfile $STEAM/$GAME/$NAME.pid"

# Screen command
INTERFACE="/usr/bin/screen -A -m -d -S $NAME"

service_start() {
# Check if the pid files currently exist
if [ -f $STEAM/$GAME/$NAME.pid ] || [ -f $STEAM/$GAME/$NAME-screen.pid ]; then
# Pid files allready exist check if the process is still running.
if [ "$(ps -p `cat $STEAM/$GAME/$NAME.pid` | wc -l)" -gt 1 ]; then
# Process is still running.
echo -e "Cannot start $TITLE. Server is already running."
#exit 1
else
# Process exited with out cleaning up pid files.
if [ "$(ps -p `cat $STEAM/$GAME/$NAME.pid` | wc -l)" -gt 1 ]; then
# Screen is still running.
# Get the process ID from the pid file we created earlier
for id in `cat $STEAM/$GAME/$NAME-screen.pid`
do kill -9 $id
echo "Killing process ID $id"
echo "Removing $TITLE screen pid file"
rm -rf $STEAM/$GAME/$NAME-screen.pid
break
done
fi
# Remove server pid file
echo "Removing $TITLE pid file"
rm -rf $STEAM/$GAME/$NAME.pid
# Wipe all old screen sessions
screen -wipe 1> /dev/null 2> /dev/null
service_start
fi
else
# Server is not running start the server.
if [ -x $STEAM/$DAEMON ]; then
echo "Starting $TITLE - $LONGNAME - $CLIENT"
echo "Server IP: $IP"
echo "Server port: $PORT"
echo "Server size: $SIZE players"
cd $STEAM
$INTERFACE $STEAM/$DAEMON $OPTS
# Prevent race condition on SMP kernels
sleep 1
# Find and write current process id of the screen process
ps -ef | grep SCREEN | grep "$NAME" | grep -v grep | awk '{ print $2}' > $STEAM/$GAME/$NAME-screen.pid
echo "$TITLE screen process ID written to $STEAM/$GAME/$NAME-screen.pid"
echo "$TITLE server process ID written to $STEAM/$GAME/$NAME.pid"

echo "$TITLE started."
# Was having problems with directory permisions due to ftp access making these files unreadable by users other than owner.
chmod 666 $STEAM/$GAME/*.pid 1> /dev/null 2> /dev/null
sleep 2
if [ $HIGHPRIORITY = 1 ]; then
renice -20 `cat $STEAM/$GAME/$NAME.pid` >/dev/null 2>&1
fi
fi
fi
}

service_stop() {
if [ -f $STEAM/$GAME/$NAME.pid ] || [ -f $STEAM/$GAME/$NAME-screen.pid ]; then
echo "Stopping $TITLE - $LONGNAME."
# Get the process ID from the pid file we created earlier
for id in `cat $STEAM/$GAME/$NAME-screen.pid`
do kill -9 $id
echo "Killing process ID $id"
echo "Removing $TITLE screen pid file"
rm -rf $STEAM/$GAME/$NAME-screen.pid
break
done
# Remove server pid file
echo "Removing $TITLE pid file"
rm -rf $STEAM/$GAME/$NAME.pid
# Wipe all old screen sessions
screen -wipe 1> /dev/null 2> /dev/null
echo "$TITLE stopped."
else
echo -e "Cannot stop $TITLE. Server is not running."
#exit 1
fi
}
service_clear() {
# Removing all pid files
echo "Removing all Service pid files."
rm -rf $STEAM/$GAME/*.pid 1> /dev/null 2> /dev/null
}

service_update() {
echo "Stopping and Clearing all Service files."
service_stop
sleep 2
service_clear
sleep 2
echo "Updating Steam Updater"
cd $UPDATER
./steam 1> /dev/null 2> /dev/null
echo "Updating Game Files"
./steam -command update -game $GAME -dir . 1> /dev/null 2> /dev/null
sleep 2
service_start
}


case "$1" in
'start')
service_start
;;
'stop')
service_stop
;;
'restart')
service_stop
sleep 1
service_start
;;
'clear')
service_clear
;;
'update')
service_update
;;
*)
echo "Usage $0 start|stop|restart|clear|update"
esac





Code:
#Source Dedicated Server Init Script

# Server options
TITLE='Source Dedicated Server' # Script initialization title
LONGNAME='Team Fortress 2' # Full title of game type
NAME='tf2' # Server handle for the screen session
DAEMON='srcds_run' # The server daemon
UPDATER='/usr/srcds' # The Steam updater. I recommend keeping it one directory below orangebox for tf2 servers.
STEAM='/usr/srcds/orangebox' # STEAM to Steam installation
USER='srcds' # User that this will be running under. Currently not functional part of this script.

# Game options
CLIENT='Team Fortress 2' #Game Server name.
IP='127.0.0.1' # IP of the server
PORT='27015' # Port number to
MAP='ctf_2fort' # Initial map to start
GAME='tf' # Game type (tf|cstrike|valve|hl2mp)
SIZE='32' # Maximum number of players
HIGHPRIORITY=1 #Set server renice to -20 will make server take priority over all other applications on server. 1 being on and 0 being off.

# Server options string
OPTS="-game $GAME +hostname \"$CLIENT\" +map $MAP +ip $IP -port $PORT \
-autoupdate +maxplayers $SIZE -pidfile $STEAM/$GAME/$NAME.pid"

# Screen command
CURRENT_USER=$(/usr/bin/whoami)
if [ "$CURRENT_USER" = "$USER" ]; then
INTERFACE="/usr/bin/screen -A -m -d -S $NAME"
else
INTERFACE="sudo -u $USER /usr/bin/screen -A -m -d -S $NAME"
fi


service_start() {
# Check if the pid files currently exist
if [ -f $STEAM/$GAME/$NAME.pid ] || [ -f $STEAM/$GAME/$NAME-screen.pid ]; then
# Pid files allready exist check if the process is still running.
if [ "$(ps -p `cat $STEAM/$GAME/$NAME.pid` | wc -l)" -gt 1 ]; then
# Process is still running.
echo -e "Cannot start $TITLE. Server is already running."
#exit 1
else
# Process exited with out cleaning up pid files.
if [ "$(ps -p `cat $STEAM/$GAME/$NAME.pid` | wc -l)" -gt 1 ]; then
# Screen is still running.
# Get the process ID from the pid file we created earlier
for id in `cat $STEAM/$GAME/$NAME-screen.pid`
do kill -9 $id
echo "Killing process ID $id"
echo "Removing $TITLE screen pid file"
rm -rf $STEAM/$GAME/$NAME-screen.pid
break
done
fi
# Remove server pid file
echo "Removing $TITLE pid file"
rm -rf $STEAM/$GAME/$NAME.pid
# Wipe all old screen sessions
screen -wipe 1> /dev/null 2> /dev/null
service_start
fi
else
# Server is not running start the server.
if [ -x $STEAM/$DAEMON ]; then
echo "Starting $TITLE - $LONGNAME - $CLIENT"
echo "Server IP: $IP"
echo "Server port: $PORT"
echo "Server size: $SIZE players"
cd $STEAM
$INTERFACE $STEAM/$DAEMON $OPTS
# Prevent race condition on SMP kernels
sleep 1
# Find and write current process id of the screen process
ps -ef | grep SCREEN | grep "$NAME" | grep -v grep | awk '{ print $2}' > $STEAM/$GAME/$NAME-screen.pid
echo "$TITLE screen process ID written to $STEAM/$GAME/$NAME-screen.pid"
echo "$TITLE server process ID written to $STEAM/$GAME/$NAME.pid"

echo "$TITLE started."
# Was having problems with directory permisions due to ftp access making these files unreadable by users other than owner.
chmod 666 $STEAM/$GAME/*.pid 1> /dev/null 2> /dev/null
# Make any pid files created by different users owned by the set user.
chown $USER $STEAM/$GAME/*.pid 1> /dev/null 2> /dev/null
sleep 2
if [ $HIGHPRIORITY = 1 ]; then
renice -20 `cat $STEAM/$GAME/$NAME.pid` >/dev/null 2>&1
fi
fi
fi
}

service_stop() {
if [ -f $STEAM/$GAME/$NAME.pid ] || [ -f $STEAM/$GAME/$NAME-screen.pid ]; then
echo "Stopping $TITLE - $LONGNAME."
# Get the process ID from the pid file we created earlier
for id in `cat $STEAM/$GAME/$NAME-screen.pid`
do kill -9 $id
echo "Killing process ID $id"
echo "Removing $TITLE screen pid file"
rm -rf $STEAM/$GAME/$NAME-screen.pid
break
done
# Remove server pid file
echo "Removing $TITLE pid file"
rm -rf $STEAM/$GAME/$NAME.pid
# Wipe all old screen sessions
screen -wipe 1> /dev/null 2> /dev/null
echo "$TITLE stopped."
else
echo -e "Cannot stop $TITLE. Server is not running."
#exit 1
fi
}
service_clear() {
# Removing all pid files
echo "Removing all Service pid files."
rm -rf $STEAM/$GAME/*.pid 1> /dev/null 2> /dev/null
}

service_update() {
echo "Stopping and Clearing all Service files."
service_stop
sleep 2
service_clear
sleep 2
echo "Updating Steam Updater"
cd $UPDATER
./steam 1> /dev/null 2> /dev/null
echo "Updating Game Files"
./steam -command update -game $GAME -dir . 1> /dev/null 2> /dev/null
sleep 2
service_start
}


case "$1" in
'start')
service_start
;;
'stop')
service_stop
;;
'restart')
service_stop
sleep 1
service_start
;;
'clear')
service_clear
;;
'update')
service_update
;;
*)
echo "Usage $0 start|stop|restart|clear|update"
esac



Ok for all you guys out there I have a start.sh and stop.sh for my CSS server. Makes things a whole lot easier.

Start.sh:

#!/bin/sh
./srcds_run -game cstrike +map de_prodigy +maxplayers MAX_PLAYERS +ip SERVER_IP -autoupdate &

You need to change SERVER_IP and MAX_PLAYERS to the settings you want for your server,

Stop.sh:

#!/bin/sh
kill `ps xww | grep "srcds" | cut -c1-5` 2>/dev/null
ps xww | grep "srcds" | cut -c1-5 | xargs kill 2>/dev/null

Simply copy and past these commands in two text files then rename them to start.sh and stop.sh. When logged in via SSH to your server run the scripts like this:

./start.sh - to start the server
./stop.sh - to stop the server

These files must be saved in the same dir as srcds_run



Use this script to run srcds as a deamon via 'screen': (apt-get update && apt-get install screen if you don't already have it)

Put this in a file in the /etc/init.d folder
#! /bin/sh
#
# Start the Counter-Strike Source dedicated server as non-root.
#
# A modification of the CS Server startup script, to run the server
# as a non-root user.
#
# ORIGINAL AUTHORS :
#
# Julien Escario ( pandemik@asylog.net )
# &
# Cedric Rochat ( crochat@younics.org )
#
# ===========================================
#
# What you need:
#
# Linux :)
# awk
# screen
# srcds & cstrike-files OR
#
# YES, this script works fine with fine with CS 1.6
#
# How to use:
#
# Edit the DIR-var to fit your system (just contains the path to the dir that contains hlds_run)
# Edit the PARAMS-var to fit your needs
# Edit the CS_USER-var to the name of the user that will run the server
#
# How to see the server-console:
#
# Just type in: screen -r srcds (or whatever you set $NAME to)
# More info about screen can be found by typing "man screen" or using this nice link
# http://server.counter-strike.net/server.php?cmd=howto&show=screen
#
# The easist way is to use this script simple as a start-script for your server
# If you want to use it as a script to start the server at boot-time:
#
# When this is done, copy the file to /etc/rc.d/init.d (or whereever your system stores the
# scripts for starting the services
# Now you can link the script to your runlevel-dir, here's an example for runlevel 3:
# (THIS IS FOR DEBIAN! If you use e.g. Redhat you must change these dirs!!!)
#
# ln -s /etc/init.d/hlds /etc/rc3.d/S90hlds
# ln -s /etc/init.d/hlds /etc/rc6.d/K50hlds
#
# Or use it manualy like:
# /etc/rc.d/init.d/hlds start
# /etc/rc.d/init.d/hlds stop
#
# If you don't want to start the server as root you have to change this:
# add the var CS_USER and uncomment it
# change the lines at the "start-block"
#
# You must be logged in as this user to re-attach the screen!
#
# DOC by jwm (jwm@counter-strike.de)

# The user that will run the server
CS_USER=source

# Leave this alone.
NAME=css

PATH=/bin:/usr/bin:/sbin:/usr/sbin

# DON'T FORGET TO CHANGE THE PATH TO YOUR NEEDS!
DIR=/games/steam/source

# Leave this alone.
DAEMON=srcds_run

# Internet-server:
PARAMS="-game cstrike +map playground_x_s +maxplayers 16 +ip 12.170.232.150 -port 27015 -steamuser <user> -steampass <pass> -autoupdate"

# Leave this alone.
DESC="Counter-Strike Source Dedicated Server"

case "$1" in
start)
if [[ `su $CS_USER -c "screen -ls |grep $NAME"` ]]
then
echo "$DESC is already running"
else
echo "Starting $DESC: $NAME"
su $CS_USER -c "cd $DIR; screen -m -d -S css ./$DAEMON $PARAMS"
fi
;;

stop)
if [[ `su $CS_USER -c "screen -ls |grep $NAME"` ]]
then
echo -n "Stopping $DESC: $NAME"
kill `ps aux | grep -v grep | grep -i $CS_USER | grep -i screen | grep -i $NAME | awk '{print $2}'`
echo " ... done."
else
echo "Coulnd't find a running $DESC"
fi
;;

restart)
if [[ `su $CS_USER -c "screen -ls |grep $NAME"` ]]
then
echo -n "Stopping $DESC: $NAME"
kill `ps aux | grep -v grep | grep -i $CS_USER | grep -i screen | grep -i $NAME | awk '{print $2}'`
echo " ... done."
else
echo "Coulnd't find a running $DESC"
fi

echo -n "Starting $DESC: $NAME"
su $CS_USER -c "cd $DIR; screen -m -d -S css ./$DAEMON $PARAMS"
echo " ... done."
;;

status)
ps aux | grep -v grep | grep srcds_r > /dev/null
CHECK=$?
[ $CHECK -eq 0 ] && echo "$DESC is UP" || echo "$DESC is DOWN"
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac

exit 0

This script assumes you have a user 'source' on your machine but you can change it to whatever you want. For each server just changed the 'PARAMS' argument to match your configuration and change the 'screen' name. When you use screen you can disconnect from the machine and come back later. In the example above you would do:screen -r cssto access this program, and Ctrl+A Ctrl+D to retrun to the shell. I run two servers as well so I have two similar versions of the script in /etc/init.d.

The last part is getting it to run on startup. As in the comments above, you need to make static links to these scripts from the appropriate startup folders. Assuming you have two scripts /etc/init.d/css1 & css2:ln -s /etc/init.d/css1 /etc/rc2.d/S90css1
ln -s /etc/init.d/css1 /etc/rc6.d/K90css1
ln -s /etc/init.d/css2 /etc/rc2.d/S90css2
ln -s /etc/init.d/css2 /etc/rc6.d/K90css2
S and K refer to start and kill. since your default run level on a debian server is 2, hence all the scripts in rc2.d will be run at startup. run level 6 is the reboot runlevel, so then the serer is rebooting, the servers are killed.

You can therefor restart your server by:/etc/init.d/css1 restart



#!/bin/sh
dir="/home/user/office/cstrike"
sreen="home/user/screen"
# change this to how you normally run your srcds:
srcdexe="$sreen -A -m -d -S office-server taskset 0x4 ./srcds_run -console -game cstrike +map cs_office_unlimited_fixed +mp_dynamicpricing 0 +fps_max 0 -tickrate 66 +ip xxx.xxx.xxx.xxx -port 27015 +maxplayers 50 -binary ./srcds_i486 -pidfile office.pid"
# I wouldn't touch this if I were you.
srcdname="office.pid"
########## you probably don't need to change anything below here ##########
cd $dir
if test -r $srcdname; then
# there is a pid file -- is it current?
srcdpid=`cat $srcdname`
if `kill -CHLD $srcdpid >/dev/null 2>&1`; then
# it's still going
# back out quietly
exit 0
fi
echo "Source Dedicated Server Crontab notice:"
echo ""
echo "Stale $srcdname file (erasing it)"
rm -f $srcdname
fi
echo ""
echo "Couldn't find the srcds running. Reloading it..."
echo ""
cd ..
/$srcdexe

more to come


---------------------------------------------------------------------------------------------------------------------


Say, your linux user name is zerosin, your home directory is '/home/zerosin' and your server directory is '/home/zerosin/server' (there you put your hldsupdatetool.bin and steam executable).

You probably downloaded the server files via

./steam -command update -game "cstrike" -dir .
Now you should see the following directories:
/home/zerosin/server/hl2
/home/zerosin/server/cstrike
/home/zerosin/server/cstrike/cfg
and some more subdirectories. The main server executable srcds_run can be found directly in /home/zerosin/server.

To start the server, you would type:


cd /home/zerosin/server/
./srcds_run -console -game cstrike -port 27015 +ip 123.123.123.123 +map de_dust +maxplayers 14

You will see the server console, so just type 'quit' to stop the server.

This has quite some disadvantages:
- The command is not easy to remember/fast to type
- You cannot close the Terminal without killing the server (which is ok if the server is in your flat with an own monitor/keyboard, but its bad if you manage the server remotely)

The provided script now solves those problems. Copy the two files 'startscript' and 'startscript.conf' directly into the folder '/home/zerosin/server'. You need to do the following modifications in startscript.conf:

Code:


DSPATH='/home/zerosin/server'
DSUSER='zerosin'
DSIP='whatever ip your server has'and in startscript:


Code:

cd /home/zerosin/server (changed from cd /css/1)Then execute 'chmod +x starscript' to make the script executable.

Now you can start the server with the command
/home/zerosin/server/startscript start
(or just 'server/startscript start', if you are in your home directory)

To make that even easier, do the following:


cd /bin
sudo ln -s /home/zerosin/server/startscript server1


Now you can just call 'server1 start' no matter what directory you are in. The 'sudo' command may require you to type in your login password or maybe the root password.

You can stop the server with

server1 stop

And to open the server console

server1 watch
(to close the console without killing the server, use the key combination CTRL+A CTRL+D)

If you install a TF2 server in the same directory:


cd /home/zerosin/server
./steam -command update -game "tf" -dir .
then you will see a slightly different directory structure. Games from the Orange Box will create the 'hl2' folder (as CSS) but put everything else into an 'orangebox' folder:
/home/zerosin/server/hl2
/home/zerosin/server/orangebox/tf
/home/zerosin/server/orangebox/tf/cfg

Also the server executable resides in /home/zerosin/server/orangebox/tf. If you want to use the script for TF2, do the following:


cd /home/zerosin/server
cp startscript startscript2
cp startscript.conf startscript2.conf
And change those values in startscript.conf:

Code:


CLIENT='srcds_2'
TITLE='SRCDS 2'
(it is important that CLIENT and TITLE are different from your css server config)
DSPATH='/home/zerosin/server/orangebox'
(dont forget the 'orangebox)
DSNAMESHORT='srcds_2'
(also change this to a different value than your CSS config)
DSIP='whatever ip you have'
DSGAME='tf'
DSIMAP='cp_badlands'
DSPORT='27035'
(use your other port 27015 plus 20, always increment by 20 when you start a new server)
DSSIZE='16'
DSUSER='zerosin'
DSTICKRATE='66'
DSSERVERFPS='333'
(those rates are default for TF2, no need put something else here)And change the '. ./startscript.conf' into '. ./startscript2.conf' in your startscript2 file.

Now use serverscript2 to start/stop your TF2 server. And create a link

sudo ln -s /home/zerosin/server/startscript2 /bin/server2
for simply calling 'server2 start', etc.


I am using a modified version of TheMG's script on my server. The list of modifications include:
- The original script is checking the user name, but it is not changing the user (sudo)
- Autodetecting configuration file name (based on script name)
- Added steam update/verify options
- Added options to edit main configuration files
- Added rcon command execution

Here is my runserver1.conf for a TF2 server (called master config in the script)

Code:


#!/bin/sh
DSID='tf2ds_1a';
DSTITLE='TF2 Server 1 a (20 slots)';
DSGAME='tf';
DSIMAP='cp_badlands';
DSPORT='27015';
DSSIZE='20';
DSCONF='server_a.cfg'

# Only modify if this game server has a separate directory.
STPATH='/home/hlds'; # Where Steam is installed
UPPATH='/home/hlds/server1'; # Base path for hlswupdatetool operations
DSPATH='/home/hlds/server1/orangebox'; # The gameservers subdirectory
CFPATH="$DSPATH/$DSGAME/cfg"; # Path to cfg files

# Don't modify these values.
DSIP='123.123.123.123'; # IP address you want to use to start server with
DSEXEC="$DSPATH/srcds_run"; # Either hlds_run or srcds_run
STEXEC="$STPATH/steam" # Steam executable (for game server updates)
DSUSER='hlds' # User account to run game server server and hlswupdatetool
DSTICK='66'; # Tick Rate
DSFPS='333'; # Server FPS Rate

# Don't edit this unless you need the script to do something special
DSSERVERPID="$DSID.server.pid"
DSSCREENPID="$DSID.screen.pid"
DSOPTS="-console -game $DSGAME +hostname \"$DSID\" +map $DSIMAP -ip $DSIP -port $DSPORT -autoupdate +maxplayers $DSSIZE -tickrate $DSTICK +fps_max $DSFPS +exec $DSCONF"

# This is the caller for the screen process.
# Only change if this is different from where your screen process currently resides.
DSINTERFACE="/usr/bin/screen -A -m -d -S $DSID"
If you have just one server directory containing the steam executables as well (use steam ... -dir .), then STPATH and UPPATH are the same. in the former config I am using 'steam ... -dir server1'. If you are running cstrike (or any non-orangebox game), then DSPATH is the same as well.

Here is my startscript

Code:


#!/bin/sh
# Start/stop/restart a Valve dedicated server
# All configuration changes should occur in <scriptname>.conf.

# Only change the name of the call below if you are using a different name for the script
BASEPATH='/home/hlds'

if [ ! -f "$BASEPATH/$0.conf" ]; then
echo "master config file '$BASEPATH/$0.conf' not found"
exit 0
fi

. "$BASEPATH/$0.conf"

WHOAMI=`whoami`
EDITOR='/bin/nano'
RCONCMD='/usr/bin/java -cp rcon.jar SourceRconCLI'

if [ "$WHOAMI" != "$DSUSER" ]; then
if [ "$WHOAMI" = 'root' ]; then
echo "Script called as root. Switch to user $DSUSER."
sudo -u $DSUSER "$0" "$@"
exit 0
else
ALLOWED="$DSUSER"
if [ "$DSUSER" != 'root' ]; then
ALLOWED="root or $DSUSER"
fi
echo "Script called as $WHOAMI. Please login as $ALLOWED."
exit 0
fi
fi

if [ "$DSUSER" = 'root' ]; then
echo "Running the script as root is not recommanded."
fi


service_start() {
# Currently checking to see if the pid files that are creates during
# the startup process exist. If neither exists it will go ahead.
if [ ! -f $DSPATH/$DSSERVERPID ] && [ ! -f $DSPATH/$DSSCREENPID ]; then
if [ -x $DSEXEC ]; then
echo "Starting '$DSTITLE' ..."

cd $DSPATH; $DSINTERFACE $DSEXEC $DSOPTS

# prevent race condition on SMP kernels
sleep 1

# Finding and writing current process id of the screen process
ps -ef | grep SCREEN | grep "$DSID" | grep -v grep | awk '{ print $2 }' > $DSPATH/$DSSCREENPID
ps -ef | grep srcds_run | grep "$DSID" | grep -v grep | grep -v SCREEN | awk '{ print $2 }' > $DSPATH/$DSSERVERPID
else
echo "Cannot start '$DSTITLE': executable $DSEXEC not found."
fi
else
# It found that one of the pid files exists. Perhaps the server
# did not shut down with the script being used... if this is the
# case use '<scriptname> clean' to fix it
echo "Server '$DSTITLE' already started."

# TODO: check whether there is no proper process running
# then delete the pid files and start the server
fi
}


service_stop() {
# This script is just getting the process id of the server that was
# written to the file it created earlier so it can kill it.
if [ -f $DSPATH/$DSSERVERPID ]; then
echo "Stopping '$DSTITLE' ..."
for vdspid in $(cat $DSPATH/$DSSERVERPID);
do
kill $vdspid;
break;
done
rm -rf $DSPATH/$DSSERVERPID;
else
echo "Server '$DSTITLE' not running."
fi
rm -rf $DSPATH/$DSSCREENPID;
# This command is just clearing out any *DEAD* screen sessions.
# Those can become a pain really quick.
screen -wipe 1> /dev/null 2> /dev/null
}


service_restart() {
# Simple enough. It is making a call to the stop service and then
# it waits for a second then it calls the start script.
service_stop
sleep 1
service_start
}


service_status() {
# This is checking to see if $DSNAME.pid file exists

SCREEN_PID=`ps -ef | grep SCREEN | grep "$DSID" | grep -v grep | awk '{ print $2 }'`

if [ -f $DSPATH/$DSSERVERPID ]; then
# Pulling in the values to evaulate if they are true or not
SCREEN_FILE_PID=`cat $DSPATH/$DSSCREENPID`
SERVER_FILE_PID=`cat $DSPATH/$DSSERVERPID`

# This is checking to see if the currently running process ID
# matches with the pid created when the server was started.
if [ "$SCREEN_PID" = "$SCREEN_FILE_PID" ]; then
# It found this process ID matches and is outputting what it is currently running on
echo "Server '$DSTITLE' is running"
if [ "$1" != 'quick' ]; then
echo "screen process: $SCREEN_FILE_PID"
echo "server process: $SERVER_FILE_PID"
fi
fi
else
# Apparently the server is offline
echo "Server '$DSTITLE' is offline."
if [ "$SCREEN_PID" ]; then
# Wait, it found another server matching the same criteria running under a different process ID.
echo "screen process: $SCREEN_PID"
fi
fi

if [ "$1" != 'quick' ]; then
echo "directory : $DSPATH"
echo "address : $DSIP:$DSPORT"
echo "slots : $DSSIZE"
echo "pid files : $DSPATH/$DSSCREENPID"
echo " $DSPATH/$DSSERVERPID"
echo "script file : $BASEPATH/$0"
fi
}


service_watch() {
# This service is used watch the process that is currently running

# Check if there is someone already attached
if [ `screen -wipe | grep "$DSID" | grep -v grep | awk '{ print $2 }'` = '(Attached)' ]; then
# Oops someone is already attached to it...
# better wait your turn or go chew someone $%^ out
echo -e "Someone is already attached to the console of the server.\nMight want to check who"
else
# Looks like noone is watching it right now...
# peeping tom time !!!
screen -r "$DSID"
fi
}


parse_config_value() {
FILE="$1"
ENTRY="$2"
grep "^$ENTRY" "$FILE" | sed -e "s/^$ENTRY//" -e 's/^[[:space:]]*//' -e 's/^["]//' -e 's/["]$//'
}


service_rcon() {
PW=`parse_config_value "$CFPATH/$DSCONF" rcon_password`
cd $BASEPATH; $RCONCMD "$DSIP:$DSPORT" "$PW" "$@"
}


service_clean() {
# This service is used to clean house if the script is reporting erroneous info.
rm -rf $DSPATH/$DSSERVERPID $DSPATH/$DSSCREENPID
screen -wipe 1> /dev/null 2> /dev/null;
}


edit_file() {
if [ -f "$1" ]; then
$EDITOR "$1"
else
echo "Server '$DSTITLE' file not found: '$1'."
fi
}


service_edit() {
case "$1" in
'')
edit_file "$CFPATH/$DSCONF"
;;
'cfg')
edit_file "$CFPATH/$DSCONF"
;;
'master')
edit_file "$BASEPATH/$0.conf"
;;
'mapcycle')
FILE=`parse_config_value "$CFPATH/$DSCONF" 'mapcyclefile'`
edit_file "$DSPATH/$DSGAME/$FILE"
;;
'motd')
FILE=`parse_config_value "$CFPATH/$DSCONF" 'motdfile'`
edit_file "$DSPATH/$DSGAME/$FILE"
;;
*)
echo "Unknown edit entry: '$1'"
esac
}


list_files() {
DIR="$1"
EXT="$2"
cd "$DIR"; find -L -type f -name "*.$EXT" | sed -e "s/^[.][/]//" | sort
}


service_list() {
case "$1" in
'')
echo "Please select list type: maps demo cfg"
;;
'maps')
list_files "$DSPATH/$DSGAME/maps" bsp
;;
'demo')
list_files "$DSPATH/$DSGAME" dem
;;
'cfg')
list_files "$DSPATH/$DSGAME/cfg" cfg
;;
*)
echo "Unknown list entry: '$1'"
esac
}


service_update() {
if [ -x $STEXEC ]; then
echo "Updating '$DSTITLE' ..."
cd $STPATH; $STEXEC -command update -game "$DSGAME" -dir $UPPATH
else
echo "Cannot update '$DSTITLE': executable '$STEXEC' not found."
fi
}


service_verify() {
if [ -x $STEXEC ]; then
echo "Verifying '$DSTITLE' ..."
cd $STPATH; $STEXEC -command update -game "$DSGAME" -dir . -verify_all
else
echo "Cannot verify '$DSTITLE': executable '$STEXEC' not found."
fi
}


case "$1" in
'start')
service_start
;;
'stop')
service_stop
;;
'restart')
service_restart
;;
'status')
service_status
;;
'quickstatus')
service_status quick
;;
'watch')
service_watch
;;
'rcon')
shift;
service_rcon "$@"
;;
'clean')
service_clean
;;
'edit')
service_edit "$2"
;;
'editmaster')
service_edit 'master'
;;
'list')
service_list "$2"
;;
'update')
service_update
;;
'verify')
service_verify
;;
*)
echo "usage $0 <action> <options>"
echo " <action> = start|stop|restart|status|watch|clean"
echo " <action> = rcon <command>"
echo " <command> = any command for the server console"
echo " <action> = edit <file>"
echo " <action> = update|verify"
echo " <file> = cfg | master | motd | mapcycle"
echo " <action> = list <type>"
echo " <type> = maps | demo | cfg"
esacIf we run the script as root (but DSUSER is not root) then just switch user and recall the script. The filenames for MotD and MapCycle files and the RCon password are directly parsed from the server config file. To execute rcon commands I am using a little Java program calling the Rconed Java Library (http://rconed.sourceforge.net/). The Library and my little code (http://game-control.net/download/rcon.jar/) are available under GPL.

For that script to work, you need the following directory structure:


/home/hlds (home directory of user hlds)
/home/hlds/hldsupdatetool.bin
/home/hlds/steam
/home/hlds/rcon.jar (available here (http://game-control.net/download/rcon.jar/))
/home/hlds/startscript (the script)
/home/hlds/runserver1 -> startscript (just a symlink)
/home/hlds/runserver1.conf
/home/hlds/runserver2 -> startscript
/home/hlds/runserver2.conf
/home/hlds/server1/orangebox/srcds_run
/home/hlds/server1/orangebox/tf/...

It is not necessary to copy the main script or to change anything in there for different servers. The script is loading appropriate settings based on the name of the symbolic link it was called with.

Now have fun using the following commands:


runserver1 start
runserver1 rcon mp_timelimit 30
runserver1 update
runserver1 edit cfg

If you have multiple servers running, then you could use a little script to start/stop/restart/update all servers with a single call. Here you go:

Code:

#!/bin/sh
# Start/stop/restart all Valve dedicated servers

SERVERS='runserver1 runserver2'


service_exec() {
echo "Invoking command '$1' on all game servers"
for server in $SERVERS;
do
echo
sh $server $1
done
}


case "$1" in
'start')
service_exec start
;;
'stop')
service_exec stop
;;
'restart')
service_exec restart
;;
'status')
service_exec status
;;
'quickstatus')
service_exec quickstatus
;;
'clean')
service_exec clean
;;
'update')
service_exec update
;;
'verify')
service_exec verify
;;
*)
echo "usage $0 start|stop|restart|status|quickstatus|clean|update |verify"
esac
Change the list of $SERVERs accordingly (the script could automatically retrieve that list from the set of .conf-files, but well).

The script still has some problems. If the server exits (quit on console or crash), the pid files are still there, so you need to 'runserver1 clean' and 'runserver1 start' to restart the server. instead 'runserver1 start' should recognize, that the pid files are there, but the server is not running. Due to the 'ps | grep' hacks, we don't need the pid files at all.

First I tried to disable the user 'hlds' (no password, no login, no shell; you can still 'sudo -u hlds'), but if you start a screen process, it tries to attach to the current 'tty' which does not belong to hlds, but to the user you logged in with. The server still works, but you cannot attach to the screen process (runserver1 watch). So I make hlds a regular login account.