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