#!/bin/sh #---------------------------------------------------------------------------------------- # Стартовые скрипты для игровых серверов # Авторское право (C) 2004,2005 Андрей Заболотный # Все Права Защищены # # Программа распространяется на правах "как есть", # автор не несет ответственности за финансовые убытки, # возникшие по причине использования этой программы :) #---------------------------------------------------------------------------------------- # # Общая часть для всех игровых серверов. # Запускает сервер в фоновом режиме через screen # # Переменные которые должны быть установлены до включения этого файла: # # GAME_NAME - общее имя для семейства игр (Half-Life, Quake III итп) # GAME_DAEMON - имя скрипта который стартует игру (например "hlds_run") # GAME_SIGHUP - имя процесса, которому надо послать SIGHUP чтобы перезагрузил конфиги # GAME_USER - имя пользователя, из-под которого работает сервер игры # GAME_SERVERS - список разновидностей данного сервера (например "cs cz dod") # GAME_PARAMS - общие параметры которые передаются каждой копии игрового демона # GAME_PARAMS_{имя разновидности} - список параметров передаваемых конкретной # разновидности демона (например GAME_PARAMS_osp="+set net_port +27960" # GAME_CPU_{имя разновидности} - список процессоров (для многопроцессорных систем), # на котором будет работать данный сервер. Сервера с высокой нагрузкой имеет # смысл раскидать по независимым процессорам. Список в формате "1,2,5". # GAME_DIR - каталог в котором установлена игра (общий для всех разновидностей), либо # GAME_DIR_{имя разновидности} - если нужен особый каталог для какой-то разновидности # GAME_PRIO - (опционально) приоритет сервера, по умолчанию равен -10 # GAME_PIDF - (опционально) файл с идентификатором процесса сервера # # Возможные параметры для запуска скрипта сервиса: # # service [имя_сервиса] start {список разновидностей сервера} # Стартует все разновидности сервера (если после start никаких аргументов нет) # либо только те разновидности, которые заданы в командной строке. # service [имя_сервиса] stop {список разновидностей сервера} # Останавливает все разновидности сервера (если после stop никаких аргументов нет) # либо только те разновидности, которые заданы в командной строке. # service [имя_сервиса] restart {список разновидностей сервера} # Останавливает, а потом запускает указанный сервис или указанную разновидность # service [имя_сервиса] status # Выводит список PID'ов запущенных серверов # service [имя_сервиса] condrestart # Останавливает, а потом запускает указанный сервис но только в случае, если # сервис был запущен. # service [имя_сервиса] reload # Послать серверам сигнал о том, что надо перечитать свои конфигурационные файлы # (если поддерживается сервером). # unset LANG [ -n "$GAME_LANG" ] && LANG=$GAME_LANG export LANG # Source function library. . /etc/rc.d/init.d/functions unset SUDO [ "`whoami`" != "$GAME_USER" ] && SUDO="sudo -H -u $GAME_USER" [ -z "$GAME_PRIO" ] && GAME_PRIO=-8 [ ${GAME_DAEMON:0:1} == "/" ] || GAME_DAEMON="./$GAME_DAEMON" self=`basename $0 | sed -e 's/^[SK][0-9][0-9]//'` cfgdir="/var/run/gameserver" find_pids() { if [ -n "$GAME_PIDF" ] ; then suspect_pids=`cat $GAME_PIDF 2>/dev/null` else regex='\('`echo "$GAME_SERVERS"|sed -e 's/ \+/\\\\|/g'`'\)' suspect_pids=`$SUDO screen -ls | grep "[0-9]\+\.$regex" | sed -e 's/\..*//'` fi pids="" for x in $suspect_pids; do kill -0 $x &>/dev/null && pids="$pids $x" done echo $pids } check_gameservers() { if [ -n "$*" ]; then local res= for gs in $*; do if echo "$GAME_SERVERS" | grep -qw "$gs"; then if [ -z "$res" ]; then res="$gs" else res="$res $gs" fi else echo $"Invalid game server \"$gs\" specified, ignoring" fi done GAME_SERVERS="$res" if [ -z "$GAME_SERVERS" ]; then echo $"No game servers specified, aborting" exit 255 fi fi } start() { check_gameservers $* if [ -n "$GAME_INIT" ] ; then ( eval $GAME_INIT ) >/dev/null 2>&1 fi pids=`find_pids` if [ -n "$pids" ]; then echo "The server is already running with PID(s) $pids" return 255 fi for game in $GAME_SERVERS; do echo -n $"Starting $GAME_NAME ($game) server: " # Change to server directory eval DIR='$GAME_DIR_'$game [ -z "$DIR" ] && DIR=$GAME_DIR cd $DIR # Create a temporary file for logging commands [ ! -d "$cfgdir" ] && mkdir "$cfgdir" && chmod 755 "$cfgdir" cfg="$cfgdir/$self-$game" [ -f $cfg ] && chattr -i $cfg echo "deflog on" >$cfg echo "logfile flush 3" >>$cfg echo "logfile $DIR/logs/$game.log">>$cfg chown $GAME_USER $cfg chattr +i $cfg eval AFFINITY='$GAME_CPU_'$game if [ "$AFFINITY" != "" ]; then AFFINITY="taskset -c $AFFINITY " fi eval tmp='$GAME_PARAMS_'$game $AFFINITY /bin/nice -n $GAME_PRIO $SUDO screen -c $cfg -d -m -S $game $GAME_DAEMON $GAME_PARAMS $tmp RETVAL=$? [ "$RETVAL" -eq 0 ] && success $"$game_daemon startup" || failure $"$game_daemon startup" echo if [ -x /usr/bin/logger ]; then if [ "$RETVAL" -eq 0 ]; then echo "$GAME_NAME ($game) server started" | /usr/bin/logger -pdaemon.info -t$game_daemon else echo "Failed to start $GAME_NAME ($game) server" | /usr/bin/logger -pdaemon.info -t$game_daemon fi fi done [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$self return $RETVAL } stop() { check_gameservers $* RETVAL=0 pids=`find_pids` if [ -n "$pids" ]; then echo -n $"Stopping $GAME_NAME servers ($GAME_SERVERS): " kill $pids RETVAL=$? if [ -n "$GAME_PIDF" ] ; then timeout=50 while [ $timeout -gt 0 ]; do if [ ! -f $GAME_PIDF ]; then break fi sleep 2 echo -n '.' timeout=$(( $timeout - 1 )) done [ $timeout -eq 0 ] && RETVAL=1 || RETVAL=0 fi [ "$RETVAL" -eq 0 ] && success "$game_daemon shutdown" || failure "$game_daemon shutdown" echo if [ -x /usr/bin/logger ]; then if [ "$RETVAL" -eq 0 ]; then echo "$GAME_NAME ($GAME_SERVERS) server stopped" | /usr/bin/logger -pdaemon.info -t$game_daemon else echo "Failed to stop $GAME_NAME ($GAME_SERVERS) server" | /usr/bin/logger -pdaemon.info -t$game_daemon fi fi fi for game in $GAME_SERVERS; do cfg="$cfgdir/$self-$game" if [ -f $cfg ]; then chattr -i $cfg rm -f $cfg fi done if [ -n "$GAME_EXIT" ] ; then ( $GAME_EXIT ) >/dev/null 2>&1 fi [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$self return $RETVAL } # GAME_DAEMON может содержать также имя каталога, обычно это лишнее game_daemon=`basename $GAME_DAEMON` case "$1" in start) shift start $* ;; stop) shift stop $* ;; status) pid=`find_pids` base=$game_daemon if [ -n "$pid" ]; then echo $"${base} (pid $pid) is running..." else status $game_daemon fi ;; restart) shift stop $* usleep 500000 start $* ;; condrestart) if [ -n `find_pids` ]; then stop start fi ;; reload) if test "x$GAME_SIGHUP" != x; then kill -HUP `pidof $GAME_SIGHUP` else echo "Reloading configuration not supported for this service" fi ;; *) echo $"Usage: $0 {start|stop|restart|reload|condrestart|status}" exit 1 esac exit $RETVAL