1 |
#!/bin/sh
|
2 |
#
|
3 |
# Copyright (c) 2002, Valve LLC. All rights reserved.
|
4 |
#
|
5 |
# a wrapper script for the main hl dedicated server binary.
|
6 |
# Performs auto-restarting of the server on crash. You can
|
7 |
# extend this to log crashes and more.
|
8 |
#
|
9 |
|
10 |
# setup the libraries, local dir first!
|
11 |
export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH"
|
12 |
|
13 |
init() {
|
14 |
# Initialises the various variables
|
15 |
# Set up the defaults
|
16 |
GAME="valve"
|
17 |
DEBUG=""
|
18 |
RESTART="yes"
|
19 |
HL=./hlds_i486
|
20 |
HL_DETECT=1
|
21 |
TIMEOUT=10 # time to wait after a crash (in seconds)
|
22 |
CRASH_DEBUG_MSG="email debug.log to linux@valvesoftware.com"
|
23 |
GDB="gdb" # the gdb binary to run
|
24 |
DEBUG_LOG="debug.log"
|
25 |
PID_FILE="" # Used for debug and with -pidfile argument
|
26 |
STEAM=""
|
27 |
#PID_FILE_SET=0
|
28 |
STEAMERR=""
|
29 |
SIGINT_ACTION="quit 0" # exit normally on sig int
|
30 |
NO_TRAP=0
|
31 |
AUTO_UPDATE=""
|
32 |
#STEAM_USER=""
|
33 |
#STEAM_PASSWORD=""
|
34 |
BETA_VERSION=""
|
35 |
PARAMS=$*
|
36 |
|
37 |
# Remove any old default pid files
|
38 |
# Cant do this as they may be still running
|
39 |
#rm -f hlds.*.pid
|
40 |
|
41 |
# use the $FORCE environment variable if its set
|
42 |
if test -n "$FORCE" ; then
|
43 |
# Note: command line -binary will override this
|
44 |
HL=$FORCE
|
45 |
HL_DETECT=0
|
46 |
fi
|
47 |
|
48 |
while test $# -gt 0; do
|
49 |
case "$1" in
|
50 |
"-game")
|
51 |
GAME="$2"
|
52 |
shift ;;
|
53 |
"-debug")
|
54 |
DEBUG=1 ;;
|
55 |
# Ensure that PID_FILE is set
|
56 |
#PID_FILE_SET=1
|
57 |
#if test -z "$PID_FILE"; then
|
58 |
# PID_FILE="hlds.$$.pid"
|
59 |
#fi ;;
|
60 |
"-norestart")
|
61 |
RESTART="" ;;
|
62 |
"-pidfile")
|
63 |
PID_FILE="$2"
|
64 |
#PID_FILE_SET=1
|
65 |
shift ;;
|
66 |
"-binary")
|
67 |
HL="$2"
|
68 |
HL_DETECT=0
|
69 |
shift ;;
|
70 |
"-timeout")
|
71 |
TIMEOUT="$2"
|
72 |
shift ;;
|
73 |
"-gdb")
|
74 |
GDB="$2"
|
75 |
shift ;;
|
76 |
"-debuglog")
|
77 |
DEBUG_LOG="$2"
|
78 |
shift ;;
|
79 |
"-autoupdate")
|
80 |
AUTO_UPDATE="yes"
|
81 |
STEAM="./steam"
|
82 |
RESTART="yes" ;;
|
83 |
"-steamerr")
|
84 |
STEAMERR=1 ;;
|
85 |
"-ignoresigint")
|
86 |
SIGINT_ACTION="" ;;
|
87 |
"-notrap")
|
88 |
NO_TRAP=1 ;;
|
89 |
#"-steamuser")
|
90 |
# STEAM_USER="$2";
|
91 |
# shift ;;
|
92 |
#"-steampass")
|
93 |
# STEAM_PASSWORD="$2";
|
94 |
# shift ;;
|
95 |
"-beta")
|
96 |
BETA_VERSION="$2";
|
97 |
shift ;;
|
98 |
"-help")
|
99 |
# quit with syntax
|
100 |
quit 2
|
101 |
;;
|
102 |
esac
|
103 |
shift
|
104 |
done
|
105 |
|
106 |
# Ensure we have a game specified
|
107 |
if test -z "$GAME"; then
|
108 |
echo "Unable to determine game type from command line."
|
109 |
quit 1
|
110 |
elif test ! -d "$GAME"; then
|
111 |
echo "Invalid game type '$GAME' sepecified."
|
112 |
quit 1
|
113 |
fi
|
114 |
|
115 |
if test 0 -eq "$NO_TRAP"; then
|
116 |
# Set up the int handler
|
117 |
# N.B. Dont use SIGINT symbolic value
|
118 |
# as its just INT under ksh
|
119 |
trap "$SIGINT_ACTION" 2
|
120 |
fi
|
121 |
|
122 |
# Only detect the CPU if it hasnt been set with
|
123 |
# either environment or command line
|
124 |
if test "$HL_DETECT" -eq 1; then
|
125 |
detectcpu
|
126 |
fi
|
127 |
|
128 |
if test ! -f "$HL"; then
|
129 |
echo "Half-life binary '$HL' not found, exiting"
|
130 |
quit 1
|
131 |
elif test ! -x "$HL"; then
|
132 |
# Could try chmod but dont know what we will be
|
133 |
# chmoding so just fail.
|
134 |
echo "Half-life binary '$HL' not executable, exiting"
|
135 |
quit 1
|
136 |
fi
|
137 |
|
138 |
# Setup debugging
|
139 |
if test -n "$DEBUG" ; then
|
140 |
#turn on core dumps :) (if possible)
|
141 |
echo "Enabling debug mode"
|
142 |
if test "`ulimit -c`" -eq 0 ; then
|
143 |
ulimit -c 2000
|
144 |
fi
|
145 |
GDB_TEST=`$GDB -v`
|
146 |
if test -z "$GDB_TEST"; then
|
147 |
echo "Please install gdb first."
|
148 |
echo "goto http://www.gnu.org/software/gdb/ "
|
149 |
DEBUG="" # turn off debugging cause gdb isn't installed
|
150 |
fi
|
151 |
fi
|
152 |
|
153 |
#if test -n "$STEAM_PASSWORD" && test -z "$STEAM_USER"; then
|
154 |
# echo "You must set both the steam username and password."
|
155 |
# quit 1
|
156 |
#fi
|
157 |
|
158 |
PID_PASSED="`echo \047$PARAMS\047 | grep -e -pidfile`";
|
159 |
if test -n "$PID_PASSED" || test -n "$DEBUG"; then
|
160 |
if test -z "$PID_FILE"; then
|
161 |
PID_FILE="hlds.$$.pid"
|
162 |
fi
|
163 |
fi
|
164 |
|
165 |
if test -n "$DEBUG" && test -z "$PID_PASSED"; then
|
166 |
HL_CMD="$HL $PARAMS -pidfile $PID_FILE"
|
167 |
else
|
168 |
HL_CMD="$HL $PARAMS"
|
169 |
fi
|
170 |
}
|
171 |
|
172 |
syntax () {
|
173 |
# Prints script syntax
|
174 |
|
175 |
echo "Syntax:"
|
176 |
echo "$0 [-game <game>] [-debug] [-norestart] [-pidfile]"
|
177 |
echo " [-binary [hlds_i486|hlds_i686|hlds_amd]"
|
178 |
echo " [-timeout <number>] [-gdb <gdb>] [-autoupdate]"
|
179 |
#echo " [-steamerr] [-ignoresigint] [-steamuser <username>]"
|
180 |
echo " [-steamerr] [-ignoresigint] [-debuglog <logname>]"
|
181 |
#echo " [-steampass <password>] [-debuglog <logname>]"
|
182 |
echo " [-beta <version>]"
|
183 |
echo "Params:"
|
184 |
echo "-game <game> Specifies the <game> to run."
|
185 |
echo "-debug Run debugging on failed servers if possible."
|
186 |
echo "-debuglog <logname> Log debug output to this file."
|
187 |
echo "-norestart Don't attempt to restart failed servers."
|
188 |
echo "-pidfile <pidfile> Use the specified <pidfile> to store the server pid."
|
189 |
echo "-binary <binary> Use the specified binary ( no auto detection )."
|
190 |
echo "-timeout <number> Sleep for <number> seconds before restarting"
|
191 |
echo " a failed server."
|
192 |
echo "-gdb <gdb> Use <dbg> as the debugger of failed servers."
|
193 |
echo "-steamerr Quit on steam update failure."
|
194 |
#echo "-steamuser <username> Use this username for steam updates."
|
195 |
#echo "-steampass <password> Use this password for steam updates"
|
196 |
#echo " (-steamuser must be specified as well)."
|
197 |
echo "-ignoresigint Ignore signal INT ( prevents CTRL+C quitting"
|
198 |
echo " the script )."
|
199 |
echo "-notrap Don't use trap. This prevents automatic"
|
200 |
echo " removal of old lock files."
|
201 |
echo "-beta <version> Use the specified beta version for autoupdate."
|
202 |
echo ""
|
203 |
echo "Note: All parameters specified are passed through to the server"
|
204 |
echo "including any not listed."
|
205 |
}
|
206 |
|
207 |
debugcore () {
|
208 |
# Debugs any core file if DEBUG is set and
|
209 |
# the exitcode is none 0
|
210 |
|
211 |
exitcode=$1
|
212 |
|
213 |
if test $exitcode -ne 0; then
|
214 |
if test -n "$DEBUG" ; then
|
215 |
echo "bt" > debug.cmds;
|
216 |
echo "info locals" >> debug.cmds;
|
217 |
echo "info sharedlibrary" >> debug.cmds
|
218 |
echo "info frame" >> debug.cmds; # works, but gives an error... must be last
|
219 |
echo "----------------------------------------------" >> $DEBUG_LOG
|
220 |
echo "CRASH: `date`" >> $DEBUG_LOG
|
221 |
echo "Start Line: $HL_CMD" >> $DEBUG_LOG
|
222 |
|
223 |
# check to see if a core was dumped
|
224 |
if test -f core ; then
|
225 |
CORE="core"
|
226 |
elif test -f core.`cat $PID_FILE`; then
|
227 |
CORE=core.`cat $PID_FILE`
|
228 |
elif test -f "$HL.core" ; then
|
229 |
CORE="$HL.core"
|
230 |
fi
|
231 |
|
232 |
if test -n "$CORE"; then
|
233 |
$GDB $HL $CORE -x debug.cmds -batch >> $DEBUG_LOG
|
234 |
fi
|
235 |
|
236 |
echo "End of crash report" >> $DEBUG_LOG
|
237 |
echo "----------------------------------------------" >> $DEBUG_LOG
|
238 |
echo $CRASH_DEBUG_MSG
|
239 |
rm debug.cmds
|
240 |
else
|
241 |
echo "Add \"-debug\" to the $0 command line to generate a debug.log to help with solving this problem"
|
242 |
fi
|
243 |
fi
|
244 |
}
|
245 |
|
246 |
detectcpu() {
|
247 |
# Attempts to auto detect the CPU
|
248 |
echo "Auto detecting CPU"
|
249 |
|
250 |
if test "FreeBSD" = `uname`; then
|
251 |
PROC="/usr/compat/linux/proc"
|
252 |
else
|
253 |
PROC="/proc"
|
254 |
fi
|
255 |
|
256 |
if test -e $PROC/cpuinfo; then
|
257 |
CPU_VERSION="`grep "cpu family" $PROC/cpuinfo | cut -f2 -d":" | tr -d " " | uniq`";
|
258 |
if test $CPU_VERSION -lt 4; then
|
259 |
echo "Error: hlds_l REQUIRES a 486 CPU or better";
|
260 |
quit 1
|
261 |
elif test $CPU_VERSION -ge 15; then
|
262 |
# Core 2 or greater
|
263 |
echo "Using AMD Optimised binary."
|
264 |
HL=./hlds_amd
|
265 |
elif test $CPU_VERSION -ge 6; then
|
266 |
AMD="`grep AMD $PROC/cpuinfo`";
|
267 |
if test -n "$AMD"; then
|
268 |
echo "Using AMD Optimised binary."
|
269 |
HL=./hlds_amd
|
270 |
else
|
271 |
echo "Using Pentium II Optimised binary."
|
272 |
|
273 |
# there is a CPU manufactured by VIA that
|
274 |
# doesn't support some PII instructions...
|
275 |
# detect this.
|
276 |
VIACHIP=`grep CentaurHauls $PROC/cpuinfo`
|
277 |
|
278 |
if test -z "$VIACHIP"; then
|
279 |
HL=./hlds_i686
|
280 |
fi
|
281 |
fi
|
282 |
else
|
283 |
echo "Using default binary."
|
284 |
fi
|
285 |
elif test "FreeBSD" = `uname`; then
|
286 |
CPU="`grep 'CPU:' /var/run/dmesg.boot`"
|
287 |
AMD="`echo $CPU |grep AMD`"
|
288 |
K8="`echo $CPU |grep K8`"
|
289 |
I686="`echo $CPU |grep 686`"
|
290 |
if test -n "$AMD"; then
|
291 |
echo "Using AMD Optimised binary."
|
292 |
HL=./hlds_amd
|
293 |
elif test -n "$K8" ; then
|
294 |
echo "Using AMD Optimised binary."
|
295 |
HL=./hlds_amd
|
296 |
elif test -n "$I686" ; then
|
297 |
echo "Using Pentium II Optimised binary."
|
298 |
HL=./hlds_i686
|
299 |
else
|
300 |
echo "Using default binary."
|
301 |
fi
|
302 |
else
|
303 |
echo "Using default binary."
|
304 |
fi
|
305 |
}
|
306 |
|
307 |
update() {
|
308 |
updatesingle
|
309 |
}
|
310 |
|
311 |
updatesingle() {
|
312 |
# Run the steam update
|
313 |
# exits on failure if STEAMERR is set
|
314 |
|
315 |
if test -n "$AUTO_UPDATE"; then
|
316 |
if test -f "$STEAM"; then
|
317 |
echo "Updating server using Steam."
|
318 |
CMD="$STEAM -command update -game $GAME -dir .";
|
319 |
if test -n "$BETA_VERSION"; then
|
320 |
CMD="$CMD -beta $BETA_VERSION";
|
321 |
fi
|
322 |
#if test -n "$STEAM_USER"; then
|
323 |
# CMD="$CMD -username $STEAM_USER";
|
324 |
#fi
|
325 |
#if test -n "$STEAM_PASSWORD"; then
|
326 |
# CMD="$CMD -password $STEAM_PASSWORD";
|
327 |
#fi
|
328 |
|
329 |
$CMD
|
330 |
if test $? -ne 0; then
|
331 |
if test -n "$STEAMERR"; then
|
332 |
echo "`date`: Steam Update failed, exiting."
|
333 |
quit 1
|
334 |
else
|
335 |
echo "`date`: Steam Update failed, ignoring."
|
336 |
return 0
|
337 |
fi
|
338 |
fi
|
339 |
else
|
340 |
if test -n "$STEAMERR"; then
|
341 |
echo "Could not locate steam binary:$STEAM, exiting.";
|
342 |
quit 1
|
343 |
else
|
344 |
echo "Could not locate steam binary:$STEAM, ignoring.";
|
345 |
return 0
|
346 |
fi
|
347 |
fi
|
348 |
fi
|
349 |
|
350 |
return 1
|
351 |
}
|
352 |
|
353 |
run() {
|
354 |
# Runs the steam update and server
|
355 |
# Loops if RESTART is set
|
356 |
# Debugs if server failure is detected
|
357 |
# Note: if RESTART is not set then
|
358 |
# 1. DEBUG is set then the server is NOT exec'd
|
359 |
# 2. DEBUG is not set the the server is exec'd
|
360 |
|
361 |
if test -n "$RESTART" ; then
|
362 |
echo "Auto-restarting the server on crash"
|
363 |
|
364 |
#loop forever
|
365 |
while true
|
366 |
do
|
367 |
# Update if needed
|
368 |
update
|
369 |
|
370 |
# Run the server
|
371 |
$HL_CMD
|
372 |
retval=$?
|
373 |
if test $retval -eq 0 && test -z "$AUTO_UPDATE"; then
|
374 |
break; # if 0 is returned then just quit
|
375 |
fi
|
376 |
|
377 |
debugcore $retval
|
378 |
|
379 |
echo "`date`: Server restart in $TIMEOUT seconds"
|
380 |
|
381 |
# don't thrash the hard disk if the server dies, wait a little
|
382 |
sleep $TIMEOUT
|
383 |
done # while true
|
384 |
else
|
385 |
# Update if needed
|
386 |
update
|
387 |
|
388 |
# Run the server
|
389 |
if test -z "$DEBUG"; then
|
390 |
# debug not requested we can exec
|
391 |
exec $HL_CMD
|
392 |
else
|
393 |
# debug requested we can't exec
|
394 |
$HL_CMD
|
395 |
debugcore $?
|
396 |
fi
|
397 |
fi
|
398 |
}
|
399 |
|
400 |
quit() {
|
401 |
# Exits with the give error code, 1
|
402 |
# if none specified.
|
403 |
# exit code 2 also prints syntax
|
404 |
exitcode="$1"
|
405 |
|
406 |
# default to failure
|
407 |
if test -z "$exitcode"; then
|
408 |
exitcode=1
|
409 |
fi
|
410 |
|
411 |
case "$exitcode" in
|
412 |
0)
|
413 |
echo "`date`: Server Quit" ;;
|
414 |
2)
|
415 |
syntax ;;
|
416 |
*)
|
417 |
echo "`date`: Server Failed" ;;
|
418 |
esac
|
419 |
|
420 |
# Remove pid file
|
421 |
if test -n "$PID_FILE" && test -f "$PID_FILE" ; then
|
422 |
# The specified pid file
|
423 |
rm -f $PID_FILE
|
424 |
fi
|
425 |
|
426 |
# reset SIGINT and then kill ourselves properly
|
427 |
trap - 2
|
428 |
kill -2 $$
|
429 |
}
|
430 |
|
431 |
# Initialise
|
432 |
init $*
|
433 |
|
434 |
# Run
|
435 |
run
|
436 |
|
437 |
# Quit normally
|
438 |
quit 0
|