[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Running a game server using start-stop-daemon and /etc/init.d



Hello all,

I am currently trying to modify the way one of my boxes starts, stops,
and restarts a typical game server. For this example, lets use quake2.
The way it's set up currently is as follows. There is a 'quake2' user
account on the box, with a /bin/bash shell. Someone logs in as 'quake2',
runs a script that starts up q2ded (the executable) in a screen process.
Then that user logs off. Anyone else can log in, attach to the screen,
fiddle with things, shut it down, etc.

The problems with this setup are as follows:

1) The user 'quake2' needs a shell. This is insecure. /bin/false would
be safer.

2) The person who logs in needs to know the password for the 'quake2'
user. In a machine with multiple such accounts, multiple passwords are
floating around, making the machine more susceptible to hacking.

3) The amount of work needed to modify some setting is high, including
needing a new ssh session, if that person is logged in as his own
account.

4) It's just not a very clean setup, for a machine with multiple such
game servers.

What I want to do is use debian's "start-stop-daemon" program to manage
a game server. Returning to our example of quake2, I began examining the
man page for start-stop-daemon, and some of the scripts already present
in init.d. My ultimate plan is to write several scripts for game
servers, place them in init.d, and give certain users sudo priveledges
to run them. The user then obtains root priveledges, runs the script,
and activates the daemon. The daemon changes to the 'quake2' user, and
runs the program, or kills it. No more juggling passwords, no more
separate ssh sessions, and the ability to add /bin/false to /etc/passwd.
:)

Here is an /etc/init.d script I've written for my example, quake2. It's
based on the skeleton script:

#!/bin/sh

NAME=aq2pub
GAMEPATH=/var/games/quake2
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DAEMON=q2ded
PIDFILE=$NAME.pid
NET_PORT=27910
CONFIG=server.cfg
DEDFLAG=2
MOD=action

test -f $GAMEPATH/$DAEMON || exit 0

case "$1" in
  start)
    cd $GAMEPATH
    start-stop-daemon --start --make-pidfile --pidfile
$PIDFILE --background --chuid quake2:quake2 --verbose --exec $DAEMON --
+set game $MOD +set dedicated $DEDFLAG +set port $NET_PORT +exec $CONFIG
    cd /etc/init.d
    ;;
  stop)
    cd $GAMEPATH
    start-stop-daemon --stop --pidfile $PIDFILE --verbose --exec $DAEMON
    rm $PIDFILE
    cd /etc/init.d
    ;;
  #reload)
    #
    # If the daemon can reload its config files on the fly
    # for example by sending it SIGHUP, do it here.
    #
    # If the daemon responds to changes in its config file
    # directly anyway, make this a do-nothing entry.
    #
    # start-stop-daemon --stop --signal 1 --verbose --exec $DAEMON
    # ;;
  restart|force-reload)
  #
  # If the "reload" option is implemented, move the "force-reload"
  # option to the "reload" entry above. If not, "force-reload" is
  # just the same as "restart".
  #
    cd $GAMEPATH
    start-stop-daemon --stop --pidfile $PIDFILE --verbose --exec $DAEMON
    sleep 10
    rm $PIDFILE
    start-stop-daemon --start --make-pidfile --pidfile
$PIDFILE --background --chuid quake2:quake2 --verbose --exec $DAEMON --
+set game $MOD +set dedicated $DEDFLAG +set port $NET_PORT +exec $CONFIG
    cd /etc/init.d
    ;;
  *)
    echo "Usage: /etc/init.d/game-aq2pub
{start|stop|restart|force-reload}"
    exit 1
    ;;
esac

exit 0

In writing this script, there are several things I noticed. First of
all, the quake2 server does not respond to any signals, short of the
ones that kill it. Meaning, restarting it entails stopping it and
starting it again. Secondly, the quake2 server does not create a
pidfile, so I had to include --make-pidfile. Since start-stop-daemon
does not remove created pidfiles upon stopping, I included that into the
stop setting. Thirdly, q2ded MUST be started from its directory. When it
loads, it takes the current directory and tries to read its data files
from there. So, it must be run out of /var/games/quake2. This is why I
added the cd commands before and after. However, this is where I am
stuck. Running this script yields the following:

dh3:/etc/init.d# ./game-aq2pub start
Starting ./q2ded...
Detatching to start ./q2ded...done.
dh3:/etc/init.d# ps aux | grep quake2
root      2699  0.0  0.0  1336  436 pts/0    S    05:09   0:00 grep
quake2
dh3:/etc/init.d#


Without the --background, it works perfectly. Not only does the daemon
start up, but doing ./game-aq2pub stop terminates it. There is only one
problem. The game server console window attaches to the shell I'm in,
hence the need for --background. So, what I'm asking is, is there any
way I can make this work?

I can fall back on a less graceful approach, whereby I use su quake2 -c
"cd /var/games/quake2 && ./q2ded..." to start a server, and "ps aux |
grep q2ded | grep... | awk...| other handling | xargs kill" to kill it.
However, this is less graceful, and I would love to leverage
start-stop-daemon to handle this task, as it is built for this kind of
scenario.

The main problem is that these server programs aren't made for this.
q2ded responds equally to almost all signals (terminates itself). It
doesn't create a .pid file in /var/run, as apache, screen, and others
do. Finally, it doesn't fork itself as a separate process when run,
making it difficult to use in this context.


All that being said, any input or ideas would be VERY appreciated :)

-Adar Dembo




Reply to: