• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Server Linux KF Dedicated Server Tutorial

An excellent guide, thank you very much for taking the time to make it.

Couple of notes, though. Firstly, a tiny typo in:

[kfserver]$ ./hldsuptatetool.bin

<insert license agreement here and say "yes">

[kfserver]$ ./steam
hldsuptatetool.bin -> hldsupdatetool.bin

And secondly:

This command is fairly obvious in what it does; it will install
Killing Floor to the current directory. You can choose another directory
for the -dir if you wish.
However, that another directory must exist prior to running the command or it will hang without an error message. (If this happens just hit CTRL-C to terminate.)

Regardless, an awesome read. :)
 
Upvote 0
First of all i would like to thank you for your work. Your tutorial helped me a lot setting up my server. By doing this I encountered some problems and found solutions everybody is asking here in the forum.
But first this link: http://wiki.fragaholics.de/index.code/EN:Linux_Kernel_Optimization

It should help you running your linux gameserver more stable. For beginners i would not use a 1000Hz Kernel. The importand things are the realtime,the to your hardware fitted kernel, and mostly importand the rescheduler and idler scipts. If you dont want a kernel try out the scheduler and the idler. Using Source Server (CS:S DOD:S etc) it helped me a lot.

You have to use another reschulder
Code:
#!/bin/sh

PIDS=`ps ax | grep sirq-hrtimer | grep -v grep | sed -e "s/^ *//" -e "s/ .*$//"`
for p in $PIDS; do
  chrt -f -p 99 $p
done

PIDS=`ps ax | grep sirq-timer | grep -v grep | sed -e "s/^ *//" -e "s/ .*$//"`
for p in $PIDS; do
 chrt -f -p 51 $p
done

PIDS=`pidof ucc-bin-real`
for p in $PIDS; do
  chrt -f -p 98 $p
done

Im wondering what this script accually does?
 
Upvote 0
quick n' dirty compression script

quick n' dirty compression script

Thanks for this tutorial. Saved me a lot of time.

A tip though. If you're compressing all maps at once:

You can do (in the "system" folder):

Code:
for i in ../maps/*; do ./ucc-bin compress $i; done

And it will compress _all_ the maps. Quite handy if you got a lot of custom maps that you're going to put up for redirection.

You can also use the -nohomedir option if you don't want it to end up inte the ~/.killingfloor/maps directory

Cheers :)
 
Upvote 0
Hi I have a problem and hope I can help one so I now have a server running on linux debian also hosted just fine I just have a problem with my script, I think!

script:

#!/bin/sh

DIR=/home/kfserver1/system
UPDATEDIR=/home/kfserver1
DAEMON=$DIR/ucc-bin
PARAMS="server KF-BioticsLab.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?AdminName=Teddy?AdminPassword=myPW?multihome=myIP"
PARAMS2="-nohomedir ini=KillingFloor.ini"

NAME=killingfloor
DESC="killingfloor"

case "$1" in
start)
echo "Starting $DESC: $NAME"
if [ -e $DIR ];
then
cd $DIR
screen -d -m -S $NAME $DAEMON $PARAMS $PARAMS2
else echo "No such directory: $DIR!"
fi
;;

stop)
if [[ `screen -ls |grep $NAME` ]]
then
echo -n "Stopping $DESC: $NAME"
kill `screen -ls |grep $NAME |awk -F . '{print $1}'|awk '{print $1}'`
echo " ... done."
else
echo "Coulnd't find a running $DESC"
fi
;;

restart)
if [[ `screen -ls |grep $NAME` ]]
then
echo -n "Stopping $DESC: $NAME"
kill `screen -ls |grep $NAME |awk -F . '{print $1}'|awk '{print $1}'`
echo " ... done."
else
echo "Coulnd't find a running $DESC"
fi

echo -n "Starting $DESC: $NAME"
cd $DIR
screen -d -m -S $NAME $DAEMON $PARAMS $PARAMS2
echo " ... done."
;;

status)
if [[ `screen -ls |grep $NAME` ]]
then
echo "found running prozess: $DESC: $NAME"
else
echo "no running prozess: $DESC: $NAME"
fi
;;

check)
if [[ `screen -ls |grep $NAME` ]]
then
echo "running"
else
echo -n "Starting $DESC: $NAME"
cd $DIR
screen -d -m -S $NAME $DAEMON $PARAMS $PARAMS2
echo " ... done."
fi
;;

update)
if [[ `screen -ls |grep $NAME` ]]
then
echo -n "Stopping $DESC: $NAME"
kill `screen -ls |grep $NAME |awk -F . '{print $1}'|awk '{print $1}'`
echo " ... done."
else
echo "Coulnd't find a running $DESC"
fi

echo "Updating Installation"
cd
cd $UPDATEDIR
./steam -command update -game killingfloor -verify_all

echo -n "Starting $DESC: $NAME"
cd $DIR
screen -d -m -S $NAME $DAEMON $PARAMS $PARAMS2
echo " ... done."
;;
*)
echo "Usage: $0 {start|stop|restart|update}"
exit 1
;;
esac

exit 0



Then I entered the order it restarts itself and searches for updates:

crontab -e

0-59 * * * * cd /home/kfserver1/system && ./kfstart check >/dev/null 2>&1
55 6 * * * cd /home/kfserver1/system && ./kfstart update >/dev/null 2>&1


now my problem if I'm going to screen the server 2 times and every minute there is ne new number as well as

5968.killingfloor (06/03/2011 01:24:06 PM) (Detached)
2934.killingfloor (06/03/2011 01:23:06 PM) (Detached)
7465.killingfloor (06/03/2011 01:22:06 PM) (Detached)
2845.killingfloor (06/03/2011 01:21:06 PM) (Detached)
7367.killingfloor (06/03/2011 01:20:06 PM) (Detached)


and so the whole looks after 5 minutes of me can any one help as he is only there once or is it normal if I do everything so I set hope you know what I mean and can help me thank you ever xD
 
Upvote 0
I have now installed my dedicated KF server:

I launch the server:
./ucc-bin server KF-BioticsLab.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6
I want to connect with my server ingame, but the it shows me ingame: "unknown server".


In my linux client, I get following msg:

RecvFrom returned SOCKET_ERROR 113
Does anybody knows a solution?

PS: I havent changed something in my KillingFloor.ini yet!
 
Upvote 0
Awesome Thread, especially the scripts by Terrorkarotte where very helpful.

check)
if [[ `screen -ls |grep $NAME` ]]
then

I found this didn't work on my sys. either. Don't know the reason, different shell versions might behave differently.

Here's script i'm using:

Code:
#!/bin/sh


DIR=~/kfserver/system
FULLLOGDIR=~/.killingfloor/System/log
LOGFILENAME="server1.log"

# you need to create the folder log first!
# If you do not no log will be written !

LOG=log

DAEMON=./ucc-bin

PARAMS="server KF-BioticsLab.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?AdminName=admin?AdminPassword=password?Mutator=MutKFAntiBlocker.MutKFAntiBlocker ini=KillingFloor.ini log=$LOG/"$LOGFILENAME

SCREEN_NAME=kfserver1
DESC="killingfloor server1"


start()
{
   echo "Starting $DESC: $SCREEN_NAME"
   if [ -e $DIR ];
   then
    cd $DIR
    screen -d -m -S $SCREEN_NAME $DAEMON $PARAMS
   else echo "No such directory: $DIR!"
   fi
}
stop()
{
   PID=`ps ax | grep $SCREEN_NAME | grep SCREEN | awk '{ print $1 }'`

   if [ $PID ]
   then
       echo -n "Stopping $DESC: $SCREEN_NAME pid $PID"
       kill $PID
       echo " ... done."
   else
       echo "Coulnd't find a running $DESC"
   fi
}

case "$1" in
 start)
   start
   ;;

 stop)
   stop
   ;;

 restart)
   stop
   start
   ;;

 watchdog)
   PID=`ps ax | grep $SCREEN_NAME | grep SCREEN | awk '{ print $1 }'`
   if [ $PID ]
   then
       echo '' > /dev/null
   else
      echo $SCREEN_NAME' not found, renaming old logfile and restarting...'
      cd $FULLLOGDIR
      DS=$(date +%s) 
      NN=$LOGFILENAME'.'$DS
      mv $LOGFILENAME $NN
      gzip $NN
      start
   fi
   ;;
 
 *)
   echo "Usage: $0 {start|stop|restart|watchdog}"
   exit 1
   ;;
esac

exit 0
 
Upvote 0
NOTE!!!!
Never EVER edit default.ini!!!!!!
http://forums.tripwireinteractive.com/showthread.php?t=30640

a) Copying default.ini as KillingFloor.ini (I have not tested this method myself)
Code:
[system]$ cp default.ini KillingFloor.ini

This doesnt apply anymore to linux. I ran into a problem where I couldnt access the web panel and few other things.

Its located here ~/.killingfloor/System

Most of all the settings except the ports and advanced settings can be done in the web admin.
 
Upvote 0
Im wondering what this script accually does?

$ man chrt

NAME

chrt - manipulate real-time attributes of a process

OPTIONS

-p, --pid
operate on an existing PID and do not launch a new task

-f, --fifo
set scheduling policy to SCHED_FIFO

The script looks for two kernel processes; sirq-hrtimer, sirq-timer and changes their scheduling to use FIFO (First In First Out). It also massively increases their priority in kernel scheduling, as in how much CPU time it gets given when other processes are demanding CPU time. On my Linux box I do not have those processes, so pointless trying to change them.

The 3rd for loop looks for all ucc-bin-real processes, which is the Killing Floor game server process and also makes it use FIFO and sets a very high priority.

You need to think before using a script like this. It may be worth increasing the priority but not so aggressively. It really depends on what else is running on the server, since it may give a negative effect to other processes on the server.
 
Upvote 0
Here's mine:

Code:
#!/bin/sh

# Product: KFServer startup script
# Author:  Sascha Greuel ([email protected])
# Usage:   update-rc.d kfserver defaults

### BEGIN INIT INFO
# Provides:          kfserver
# Required-Start:    $syslog $local_fs $network $remote_fs
# Required-Stop:     $syslog $local_fs $network $remote_fs
# Should-Start:      $remote_fs $named
# Should-Stop:       $remote_fs $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Killing Floor Server Daemon
# Description:       Starts the Killing Floor Server Daemon
### END INIT INFO

############################ OPTIONS ######################################################
TITLE='KFServer Daemon'
DIR='/home/killingfloor/kfserver/system'
DAEMON='ucc-bin'
USER='root'  # SHOULD BE CHANGED
GROUP='root' # SHOULD BE CHANGED
OPT='server KF-BioticsLab.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?AdminName=ADMIN?AdminPassword=PASSWORD -nohomedir'
LOGFILE='/var/log/kfserver.log'
PIDFILE='/var/run/kfserver.pid'

SUDO='/usr/bin/sudo'
AWK='/usr/bin/awk'
############################ END OPTIONS ##################################################

########################### NO NEED TO EDIT UNDER HERE ####################################

precheck() {
# Checking for sudo
if [ ! -x $SUDO ]; then
    echo
    echo "You do not have Sudo installed. Please install it and try again."
    echo "$(date +"%a, %d %b - %H:%M:%S"): You do not have Sudo installed." >> $LOGFILE
    echo
    exit 1
fi

# Checking for awk
if [ ! -x $AWK ]; then
    echo
    echo "You do not have Awk installed. Please install it and try again."
    echo "$(date +"%a, %d %b - %H:%M:%S"): You do not have awk installed." >> $LOGFILE
    echo
    exit 1
fi

# Checking for binary
if [ ! -x $DIR/$DAEMON ]; then
    echo
    echo "Can't find $DIR/$DAEMON."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Can't find $DIR/$DAEMON." >> $LOGFILE
    echo
  exit 1
fi

# Checking for user
if [ ! $(grep $USER /etc/passwd) ]; then
    echo
    echo "User '$USER' does not exist."
    echo "$(date +"%a, %d %b - %H:%M:%S"): User '$USER' does not exist." >> $LOGFILE
    echo
  exit 1
fi

# Everything seems fine
echo
echo "Everything seems fine, try $0 start."
echo
exit 1
}

service_start() {
TEST=$(ps ax | grep $DAEMON | grep -v export | grep -v grep | wc -l)

# Server not running and no pid-file found
if [ "$TEST" = "0" ] && [ ! -f $PIDFILE ]; then
    echo
    echo "Starting $TITLE..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Starting $TITLE..." >> $LOGFILE

    cd $DIR
    su $USER -c "$DAEMON $OPT" >> $LOGFILE 2>&1 &
    sleep 1
    sudo -u $USER ps ax | grep -v grep | grep $DAEMON | grep -v export | awk '{print $1}' > $PIDFILE
    chown $USER:$GROUP $PIDFILE

    echo "$TITLE screen process ID written to $PIDFILE."
    echo "$TITLE started."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE started." >> $LOGFILE
    echo
    exit 1
fi

# Server not running and a pid-file is found
if [ "$TEST" = "0" ] && [ -f $PIDFILE ]; then
    echo
    echo "Server not running but pid-file present."
    echo "Removing pid-file..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Server not running but pid-file present." >> $LOGFILE
    echo "$(date +"%a, %d %b - %H:%M:%S"): Removing pid-file..." >> $LOGFILE

    rm $PIDFILE

    echo "Old pid file removed."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Old pid file removed." >> $LOGFILE
    echo
    echo "Starting $TITLE..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Starting $TITLE." >> $LOGFILE

    cd $DIR
    su $USER -c "$DAEMON $OPT" >> $LOGFILE 2>&1 &
    sleep 1
    sudo -u $USER ps ax | grep -v grep | grep $DAEMON | grep -v export | awk '{print $1}' > $PIDFILE
    chown $USER:$GROUP $PIDFILE

    echo "$TITLE screen process ID written to $PIDFILE."
    echo "$TITLE started."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE started." >> $LOGFILE
    echo
    exit 1
fi

# Server running and no pid file-found, creates a new one!
if [ "$TEST" = "1" ] && [ ! -f $PIDFILE ]; then
    echo
    echo "Server is running but no pid file. Creating a new pid file..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Server is running but no pid file. Creating a new pid file..." >> $LOGFILE

    sudo -u $USER ps ax | grep -v grep | grep $DAEMON | grep -v export | awk '{print $1}' > $PIDFILE
    chown $USER:$GROUP $PIDFILE

    echo
    echo "$TITLE is running and new pid-file created."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE is running and new pid-file created." >> $LOGFILE
    echo
    exit 1
fi

# Server running and pid-file found
if [ "$TEST" = "1" ] && [ -f $PIDFILE ]; then
    echo
    echo "$TITLE is already running."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE is already running." >> $LOGFILE
    echo
    exit 1
fi
}

service_stop() {
TEST1=$(ps ax | grep -v grep | grep $DAEMON | grep -v export | wc -l)

# Server is not running and no pid-file found
if [ "$TEST1" = "0" ] && [ ! -f $PIDFILE ]; then
    echo
    echo "$TITLE is not running."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE is not running." >> $LOGFILE
    echo
fi

# Server is not running and pid-file found
if [ "$TEST1" = "0" ] && [ -f $PIDFILE ]; then
    echo
    echo "Server is not running but pid-file is present."
    echo "Removing pid-file..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Server is not running but pid-file is present." >> $LOGFILE
    echo "$(date +"%a, %d %b - %H:%M:%S"): Removing pid-file..." >> $LOGFILE

    rm $PIDFILE

    echo
    echo "Pid file removed."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Pid file removed." >> $LOGFILE
    echo
fi

# Server is running but no pid-file found
if [ "$TEST1" = "1" ] && [ ! -f $PIDFILE ]; then
    echo
    echo "$TITLE is running but no pid file found."
    echo "Stopping $TITLE..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE is running but no pid file found." >> $LOGFILE
    echo "$(date +"%a, %d %b - %H:%M:%S"): Stopping $TITLE..." >> $LOGFILE

    sudo -u $USER ps ax | grep -v grep | grep $DAEMON | grep -v export | awk '{print $1}' > $PIDFILE
    chown $USER:$GROUP $PIDFILE

    for id in $(cat $PIDFILE)
        do kill -TERM $id
        echo "Killing process ID $id..."
        echo "Removing $TITLE pid file..."
        rm -rf $PIDFILE
        break
    done

    echo "$TITLE stopped."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE stopped." >> $LOGFILE
    echo
fi

# Server running and pid-file found
if [ "$TEST1" = "1" ] && [ -f $PIDFILE ]; then
    echo
    echo "Stopping $TITLE..."
    echo "$(date +"%a, %d %b - %H:%M:%S"): Stopping $TITLE..." >> $LOGFILE

    for id in $(cat $PIDFILE)
        do kill -TERM $id
        echo "Killing process ID $id..."
        echo "Removing $TITLE pid file..."
        rm -rf $PIDFILE
        break
    done

    echo "$TITLE stopped."
    echo "$(date +"%a, %d %b - %H:%M:%S"): $TITLE stopped." >> $LOGFILE
    echo
fi
}

case "$1" in
    'start')
        service_start
    ;;
    'stop')
        service_stop
    ;;
    'restart')
        service_stop
        sleep 5
        service_start
    ;;
    'precheck')
        precheck
    ;;
*)
    echo
    echo "$0 start          ## Starts the server"
    echo "$0 stop           ## Stops the server"
    echo "$0 restart        ## Restarts the server"
    echo "$0 restart        ## Restarts the server"
    echo "$0 precheck       ## Dependency check"
    echo
esac

exit 0
 
Upvote 0
Just wanted to get this added to the tutorial. (I didn't bother reading past the first post. So if it's been mentioned I apologize.)

When I got to the step to

Code:
./hldsupdatetool.bin

I got an error that said

Code:
sh: uncompress: command not found

I then ran this as the ROOT user

Code:
ln -s /usr/bin/gunzip /usr/bin/uncompress

I was then able to continue.
 
Upvote 0
Thank you guys for all the info you've provided!

Here is mine script, which also can display server status and allows to configure the server via switches (set player count, map, ini, mutators etc.):

Spoiler!

You can download the above file from here: View attachment kfservice.zip.
Archive contains also a systemd service config, whick allows you to automatically launch a KF server on your system startup on modern Linux systems (where SysV is replaced by systemd).
 
Upvote 0