Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
10 KiB

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