Linux-сервер Killing Floor: скрипт запуска через screen, автоперезапуск, обновление по cron и раздача карт через nginx
Эта статья продолжает гайд по установке сервера KF1 на Linux: здесь собраны скрипты, которые выкладывали REGETT и Oyashiro на форуме killingfloor.ru в 2012 году. Пути в примерах: сервер в /opt/KFDS, SteamCMD в /opt/SteamCMD. Подставьте свои.
server.sh: запуск, остановка и автоперезапуск
Один файл, из зависимостей только screen (sudo apt-get install screen). Сервер работает в отдельном screen-сеансе, а «контроллер» через watch каждые 30 секунд вызывает server.sh check и поднимает сервер, если сеанса нет. Падения можно писать в лог.
#! /bin/sh
## v0.0.2
PATH=/usr/bin:/usr/sbin:/bin:/sbin
# Имя screen-сеанса сервера
SERVER_NAME="MyServer"
# Папка System сервера
GAME_PATH="/opt/KFDS/System"
# Имя контроллера
CONTROLLER="MyController"
# Папка, где лежит этот скрипт
PWD_PATH=$(dirname `readlink -f $0`)
# Лог падений: false или путь, например /var/log/kf-crashes.txt
CRASH_LOG="false"
check(){
PID=`ps fax | grep $SERVER_NAME | grep SCREEN | awk '{print $1}'`
if [ -z "$PID" ]
then
if [ "$CRASH_LOG" != "false" ]
then
echo $(date +%d.%m.%Y%t%H:%M:%S%t)"- Game server is crashed!" >>$CRASH_LOG
fi
echo "Game server is not running!"
start
else
echo "Game server is running..."
fi
}
start(){
cd $GAME_PATH && screen -AmdS $SERVER_NAME ./ucc-bin server KF-BioticsLab.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?ini=KillingFloor.ini -nohomedir
echo "Starting Game server...!"
}
controller(){
if test -r "${PWD_PATH}/PPID"
then
echo "$CONTROLLER is running..."
else
watch -n 30 "$PWD_PATH/server.sh check" >>/dev/null &
echo $!>${PWD_PATH}/PPID
echo "Starting Game server and AutoRestart..."
fi
}
stop(){
if [ "$1" = "controller" ]
then
if test -r "${PWD_PATH}/PPID"
then
PID=`cat ${PWD_PATH}/PPID`
kill $PID
rm -rf ${PWD_PATH}/PPID
else
echo "Controller not running!"
fi
else
PID=`ps fax | grep $1 | grep SCREEN | awk '{ print $1 }'`
if [ -z "$PID" ]
then
echo "$1 not running!"
else
kill $PID
fi
fi
}
case "$1" in
start) controller ;;
stop) echo "Stopping Game server and AutoRestart..."; stop controller; stop ${SERVER_NAME} ;;
restart) stop ${SERVER_NAME}; start ;;
check) check ;;
*) echo "Usage: $0 {start|stop|restart|check}"; exit 1
esac
exit 0
Использование: ./server.sh start, ./server.sh stop, ./server.sh restart. Файл PPID рядом со скриптом хранит PID контроллера, не удаляйте его вручную. Сегодня ту же задачу проще решить юнитом systemd с Restart=always, но скрипт удобен, если systemd под рукой нет.
Шпаргалка по screen
| Команда | Что делает |
|---|---|
screen -dmS MyServer команда | Запустить команду в новом сеансе в фоне |
screen -ls | Список всех сеансов |
screen -r MyServer | Подключиться к сеансу (консоль сервера) |
Ctrl+A, затем D | Отключиться, оставив сервер работать |
screen -wipe | Убрать «мёртвые» сеансы |
Закрывать окно консоли сервера через exit или Ctrl+C нельзя — это остановит сервер.
Ежедневное обновление через SteamCMD и cron
Сервер нужно остановить перед обновлением и запустить после. Сценарий для SteamCMD, /opt/KFDS/update.txt:
login USERNAME PASSWORD
force_install_dir /opt/KFDS/
app_update 215360 validate
exit
215360 — app ID сервера KF1 для Linux (для Windows — 215350). Серверу KF1 нужен вход в SteamCMD обычным аккаунтом Steam, покупать игру на нём не обязательно. Заведите для сервера отдельный аккаунт без Steam Guard: пароль хранится в файле открытым текстом, поэтому дайте ему права только для пользователя сервера (chmod 600 update.txt). Обёртка /opt/KFDS/updater.sh (не забудьте chmod +x):
#!/bin/sh
/opt/KFDS/server.sh stop
/opt/SteamCMD/steamcmd.sh +runscript /opt/KFDS/update.txt
/opt/KFDS/server.sh start
В /etc/crontab добавьте строку, например ежедневно в 6:00:
00 6 * * * user /opt/KFDS/updater.sh
Перечитать конфигурацию cron можно без перезапуска службы: killall -HUP cron. Вместо правки /etc/crontab задание можно положить отдельным файлом в /etc/cron.d/.
Раздача сжатых карт через nginx
Для быстрой загрузки карт клиентами (редирект) Apache избыточен, хватит лёгкого nginx:
sudo apt-get install nginx
sudo mkdir /opt/files
Пример /etc/nginx/conf.d/default.conf: первый блок отбрасывает запросы к посторонним именам, второй раздаёт файлы по IP сервера.
server {
listen 80;
server_name _;
return 444;
}
server {
listen 80;
server_name 111.222.333.444;
access_log off;
location ~* \.(uz2|7z|zip|rar)$ {
root /opt/files/;
expires 30d;
}
location ~ /\.ht { deny all; }
}
Проверка и перезапуск: sudo nginx -t, затем sudo systemctl restart nginx. Положите .uz2 в /opt/files/ и пропишите адрес в RedirectToURL секции [IpDrv.HTTPDownload] в KillingFloor.ini.
Чтобы файлы забирала только игра, а не любой браузер, можно пускать к .uz2 лишь клиентов с user-agent Unreal:
location ~* \.uz2$ {
if ( $http_user_agent !~ Unreal ) { return 444; }
root /opt/files/;
expires 30d;
}
Держите сжатые файлы вне общедоступного корня сайта: тогда скачать их можно будет только по прямой ссылке http://адрес/имя.uz2 и только из игры.
Вариант попроще: init.d и проверка через cron
Так делали в 2011 году в теме «Создание сервера на Linux» (mangust, Ren, форум killingfloor.ru) на Debian. Сервер тогда ставили через уже устаревший HLDSUpdateTool, но сама схема автозапуска годится и сейчас, если systemd нет.
Автозапуск при загрузке. Скрипт в /etc/init.d/ (например, KFautostart), значения в кавычках замените своими:
#! /bin/sh
PATH=/usr/bin:/usr/sbin:/bin:/sbin
SCREEN_NAME="kfserver"
GAME_PATH="/home/KF1/system"
start()
{
cd $GAME_PATH && screen -AmdS $SCREEN_NAME ./ucc-bin server [параметры запуска сервера]
}
stop()
{
PID=`ps fax | grep $SCREEN_NAME | grep SCREEN | awk '{ print $1 }'`
kill $PID
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
Сделайте файл исполняемым и зарегистрируйте его командой update-rc.d KFautostart defaults.
Подъём после падения. Задание cron раз в минуту проверяет, есть ли screen-сеанс сервера, и запускает его, если нет (вариант Ren):
#!/bin/sh
if [[ `screen -ls |grep имя_screen` ]]
then
echo
else
команда запуска или скрипт
fi
Строка для crontab: * * * * * /путь/к/скрипту. Скрипт server.sh выше делает то же самое без cron, через watch.
Цикл перезапуска с сохранением логов и rc.local. Вариант baikal_87 из темы «не стартует скрипт из rc.local» (форум killingfloor.ru). Скрипт kf1.sh запускает в screen второй скрипт:
#! /bin/bash
screen -A -m -d -S skf ./kf2.sh
kf2.sh в бесконечном цикле копирует прошлый ucc.log с датой в имени, запускает сервер на первом ядре (taskset -c 0), после выхода добивает процесс, дописывает время падения в kf_crash_times.log и через 3 секунды запускает сервер снова:
#! /bin/bash
while true
do
cd /home/game/KILLINGFLOOR/System/; cp ucc.log /home/game/KILLINGFLOOR/ucc.log; cd /home/game/KILLINGFLOOR/; mv ucc.log ucc-$(date +%d%m%y%H%M).log
cd /home/game/KILLINGFLOOR/System/; taskset -c 0 ./ucc-bin server KF-westlondon.rom?game=KFMod.KFGameType?VACSecured=True?MaxPlayers=20?ini=KillingFLoor.ini +net_public_adr x.xxx.xx.xx -nohomedir
kill -9 $(ps ax | grep KF-westlondon | grep -v grep | awk '{print $1}')
date >> /home/game/KILLINGFLOOR/kf_crash_times.log
echo !!! Waiting 3 seconds to restart...
sleep 3
done
Из терминала это работало, а из rc.local при загрузке нет. siriushard советовал прописать путь к скрипту в rc.local отдельной строкой, без приписок вроде taskset, перед exit 0:
/home/game/KILLINGFLOOR/System/kf1.sh
exit 0
Он же советовал не использовать заглавные буквы в путях. Автор темы о результате не написал.
Готовое решение: LinuxGSM
Всё перечисленное (установка через SteamCMD, запуск и остановка, обновления, мониторинг с уведомлениями, бэкапы, консоль, сжатие карт) умеет скрипт kfserver Дэниела Гиббса, который вырос в проект LinuxGSM. На форуме в 2014 году выкладывали перевод его документации. Если не хочется поддерживать свои скрипты, начните с него. Сравнение вариантов — в статье Варианты сервера, если SteamCMD не работает.