Advertisement
Guest User

Untitled

a guest
Jun 29th, 2014
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.82 KB | None | 0 0
  1. #!/bin/bash
  2. # /etc/init.d/minecraft
  3. # version 2014-03-02 (YYYY-MM-DD)
  4.  
  5. ### BEGIN INIT INFO
  6. # Provides: minecraft
  7. # Required-Start: $local_fs $remote_fs
  8. # Required-Stop: $local_fs $remote_fs
  9. # Should-Start: $network
  10. # Should-Stop: $network
  11. # Default-Start: 2 3 4 5
  12. # Default-Stop: 0 1 6
  13. # Short-Description: Minecraft server
  14. # Description: Starts the CraftBukkit Minecraft server
  15. ### END INIT INFO
  16.  
  17. # minecraft-init-script - An initscript to start Minecraft or CraftBukkit
  18. # Copyright (C) 2011-2014 Super Jamie <jamie@superjamie.net>
  19. #
  20. # This program is free software: you can redistribute it and/or modify
  21. # it under the terms of the GNU General Public License as published by
  22. # the Free Software Foundation, either version 3 of the License, or
  23. # (at your option) any later version.
  24. #
  25. # This program is distributed in the hope that it will be useful,
  26. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. # GNU General Public License for more details.
  29. #
  30. # You should have received a copy of the GNU General Public License
  31. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  32.  
  33. # Source the function library
  34. ## CentOS/Fedora
  35. if [ -f /etc/rc.d/init.d/functions ]
  36. then
  37. . /etc/rc.d/init.d/functions
  38. fi
  39. ## Ubuntu
  40. if [ -f /lib/lsb/init-functions ]
  41. then
  42. . /lib/lsb/init-functions
  43. fi
  44.  
  45. <<COMMENT
  46. ## ---------------------------------------------------------
  47. ## copy between these lines and place them at /etc/default/minecraft
  48. ## do not include the <<COMMENT and COMMENT words
  49.  
  50. ## Settings for minecraft-init-script
  51.  
  52. # Nice looking name of service for script to report back to users
  53. SERVERNAME="CraftBukkit"
  54.  
  55. # Filename of server binary
  56. SERVICE="craftbukkit.jar"
  57.  
  58. # URL of server executable for update checking - http://cbukk.it/craftbukkit.jar is the recommended latest Craftbukkit URL
  59. SERVER_URL="http://cbukk.it/craftbukkit.jar"
  60.  
  61. # Username of non-root user who will run the server
  62. USERNAME="bukkit"
  63.  
  64. # Path of server binary and world
  65. MCPATH="/home/bukkit/craftbukkit"
  66.  
  67. # Number of CPU cores to thread across if using multithreaded garbage collection
  68. CPU_COUNT="2"
  69.  
  70. # Where backups go
  71. BACKUPPATH="/home/bukkit/backups"
  72.  
  73. # How many days worth of backups to keep (default 7)
  74. BACKUPS_TO_KEEP="7"
  75.  
  76. # Name of Screen session
  77. SCRNAME="minecraft"
  78.  
  79. ## The Java command to run the server, uncomment one INVOCATION line only!
  80.  
  81. # Nothing special, just start the server with 1Gb RAM
  82. # INVOCATION="java -Xms1024M -Xmx1024M -Djava.net.preferIPv4Stack=true -jar $SERVICE nogui"
  83.  
  84. # This is what I run my server with, tune your RAM usage accordingly
  85. # Tested fastest GC - Default parallel new gen collector, plus parallel old gen collector
  86. INVOCATION="java -Xms1024M -Xmx1024M -Djava.net.preferIPv4Stack=true -XX:MaxPermSize=128M -XX:UseSSE=3 -XX:-DisableExplicitGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=$CPU_COUNT -XX:+AggressiveOpts -XX:+UseCompressedStrings -jar $SERVICE nogui"
  87.  
  88. # I removed these "performance" commands as I don't see any difference with them
  89. # -XX:+UseFastAccessorMethods -XX:+UseAdaptiveGCBoundary
  90.  
  91. # I've had a suggestion from a Java tuning engineer to use these
  92. # -XX:+AggressiveOpts -XX:+UseCompressedStrings
  93.  
  94. # Add HugePage support if you have it configured on the OS
  95. # You should be using HugePages if you give more than 4Gb on the Java invocation line
  96. # -XX:+UseLargePages
  97.  
  98. SETTINGS_FILE_WORKING="1"
  99. ## End of settings file
  100. ## ---------------------------------------------------------
  101. COMMENT
  102.  
  103. ### ### ### ### ### ### ### ### ### ### ### ### ### ###
  104. ### You shouldn't need to edit anything below here! ###
  105. ### ### ### ### ### ### ### ### ### ### ### ### ### ###
  106.  
  107. ## Apply the settings file
  108.  
  109. # define the location of the settings file from the name of this script
  110. SETTINGSFILE="/etc/default/minecraft"
  111.  
  112. # check the file exists, and fail if not
  113. if [ ! -f "$SETTINGSFILE" ]
  114. then
  115. echo " * [ERROR] Settings file $SETTINGSFILE does not exist. Can't run!"
  116. exit 1;
  117. fi
  118.  
  119. # if exists so source it
  120. . "$SETTINGSFILE"
  121.  
  122. # if the settings are not applying for some reason, then fail
  123. if [ ! "$SETTINGS_FILE_WORKING" == "1" ]
  124. then
  125. echo " * [ERROR] Settings file $SETTINGSFILE is not applying. Can't run!"
  126. echo " Check your options are uncommented and you haven't copied the <<COMMENT block."
  127. exit 1;
  128. fi
  129.  
  130. ## Get some more info from the settings file
  131.  
  132. # Find the world name from the existing server file
  133. WORLDNAME="$(cat $MCPATH/server.properties | grep -E 'level-name' | sed -e s/.*level-name=//)"
  134.  
  135. # Find the port number from the existing server file
  136. SERVERPORT="$(cat $MCPATH/server.properties | grep -E 'server-port' | sed -e s/.*server-port=//)"
  137.  
  138. ## Runs all commands as the non-root user
  139.  
  140. as_user() {
  141. ME="$(whoami)"
  142. if [ "$ME" == "$USERNAME" ]
  143. then
  144. bash -c "$1"
  145. else
  146. su - "$USERNAME" -c "$1"
  147. fi
  148. }
  149.  
  150. ## Check if the server is running or not, and get the Java Process ID if it is
  151.  
  152. server_running() {
  153. # Get the PID of the running Screen session:
  154. # ps, remove grep, look for screen, look for the screen session $SCRNAME to differentiate between multiple servers, awk out everything but the pid
  155. SCREENPID=""
  156. SCREENPID="$(ps -ef | grep -v grep | grep -i screen | grep $SCRNAME | awk '{print $2}')"
  157. # if the screen session with $SCRNAME is not running, then the server is not running, so we return 1 and exit the function
  158. if [ -z "$SCREENPID" ]
  159. then
  160. return 1
  161. fi
  162. # PID="$(ps -ef | grep -v grep | grep -i screen | grep $SCRNAME | awk '{print $2}' | xargs ps -f --ppid | grep $SERVICE | awk '{print $2}')"
  163. # use the screen session pid to get the parent pid, which is the actual pid of the java process, check that process is actually $SERVICE
  164. JAVAPID="$(ps -f --ppid $SCREENPID | grep $SERVICE | awk '{print $2}')"
  165. # if the java process is not running, then the server is not running, so we return 1 to exit the function
  166. if [ -z "$JAVAPID" ]
  167. then
  168. return 1
  169. fi
  170. # if we haven't failed those two tests, we have a running server, so we return success
  171. return 0
  172. }
  173.  
  174. ## Start the server executable as a service
  175.  
  176. mc_start() {
  177. if server_running
  178. then
  179. echo " * [ERROR] $SERVERNAME was already running (pid $JAVAPID). Not starting!"
  180. exit 1
  181. else
  182. echo " * $SERVERNAME was not already running. Starting..."
  183. echo " * Using map named \"$WORLDNAME\"..."
  184. as_user "cd \"$MCPATH\" && screen -c /dev/null -dmS $SCRNAME $INVOCATION"
  185. sleep 10
  186. echo " * Checking $SERVERNAME is running..."
  187.  
  188. if server_running
  189. then
  190. echo " * [OK] $SERVERNAME is now running (pid $JAVAPID)."
  191. else
  192. echo " * [ERROR] Could not start $SERVERNAME."
  193. exit 1
  194. fi
  195.  
  196. fi
  197. }
  198.  
  199. ## Stop the executable
  200.  
  201. mc_stop() {
  202. if server_running
  203. then
  204. echo " * $SERVERNAME is running (pid $JAVAPID). Commencing shutdown..."
  205. echo " * Notifying users of shutdown..."
  206. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"say SERVER SHUTTING DOWN IN 10 SECONDS. Saving map...\"\015'"
  207. echo " * Saving map named \"$WORLDNAME\" to disk..."
  208. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"save-all\"\015'"
  209. sleep 10
  210. echo " * Stopping $SERVERNAME..."
  211. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"stop\"\015'"
  212. sleep 10
  213. else
  214. echo " * [ERROR] $SERVERNAME was not running. Unable to stop!"
  215. exit 1
  216. fi
  217.  
  218. if server_running
  219. then
  220. echo " * [ERROR] $SERVERNAME is still running (pid $JAVAPID). Could not be shutdown!"
  221. exit 1
  222. else
  223. echo " * [OK] $SERVERNAME is shut down."
  224. fi
  225. }
  226.  
  227. ## Set the server read-only, save the map, and have Linux sync filesystem buffers to disk
  228.  
  229. mc_saveoff() {
  230. if server_running
  231. then
  232. echo " * $SERVERNAME is running. Commencing save..."
  233. echo " * Notifying users of save..."
  234. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"say SERVER BACKUP STARTING. Server going read-only...\"\015'"
  235. echo " * Setting server read-only..."
  236. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"save-off\"\015'"
  237. echo " * Saving map named \"$WORLDNAME\" to disk..."
  238. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"save-all\"\015'"
  239. sync
  240. sleep 10
  241. echo " * [OK] Map saved."
  242. else
  243. echo " * [INFO] $SERVERNAME was not running. Not suspending saves."
  244. fi
  245. }
  246.  
  247. ## Set the server read-write
  248.  
  249. mc_saveon() {
  250. if server_running
  251. then
  252. echo " * $SERVERNAME is running. Re-enabling saves..."
  253. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"say SERVER BACKUP ENDED. Server going read-write...\"\015'"
  254. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"save-on\"\015'"
  255. else
  256. echo " * [INFO] $SERVERNAME was not running. Not resuming saves."
  257. fi
  258. }
  259.  
  260. ## Checks for update, exits if update not required, updates if the server is not running
  261.  
  262. mc_updatecheck() {
  263. echo " * Downloading latest $SERVERNAME executable..."
  264. as_user "cd \"$MCPATH\" && curl -# -L -o \"$MCPATH/$SERVICE.update\" \"$SERVER_URL\""
  265.  
  266. if [ -f "$MCPATH/$SERVICE.update" ]
  267. then
  268. echo " * Checking downloaded update against existing server..."
  269.  
  270. if $(diff "$MCPATH/$SERVICE" "$MCPATH/$SERVICE.update" >/dev/null)
  271. then
  272. echo " * You are already running the latest version of $SERVERNAME!"
  273. exit 0; # keep this exit in as we don't need to do anything
  274. fi
  275.  
  276. else
  277. echo " * [ERROR] $SERVERNAME update could not be downloaded."
  278. exit 1
  279. fi
  280.  
  281. if server_running
  282. then
  283. echo " * $SERVERNAME is running (pid $JAVAPID). Shutting down for update..."
  284. else
  285. as_user "/bin/cp \"$MCPATH/$SERVICE.update\" \"$MCPATH/$SERVICE\""
  286. echo " * [OK] $SERVERNAME successfully updated."
  287. fi
  288. }
  289.  
  290. ## Actually do the executable update
  291.  
  292. mc_updatedo() {
  293. if server_running
  294. then
  295. echo " * [ERROR] $SERVICE is still running (pid $JAVAPID). Cannot update!"
  296. exit 1
  297. else
  298. as_user "/bin/cp \"$MCPATH/$SERVICE.update\" \"$MCPATH/$SERVICE\""
  299. echo " * [OK] $SERVERNAME successfully updated."
  300. fi
  301. }
  302.  
  303. ## Check and see if a worldname was given to the backup command. Use the default world, or check the optional world exists and exit if it doesn't.
  304.  
  305. mc_checkbackup() {
  306. if [ -n "$1" ]
  307. then
  308. WORLDNAME="$1"
  309. if [ -d "$MCPATH/$WORLDNAME" ]
  310. then
  311. echo " * Found world named \"$MCPATH/$WORLDNAME\""
  312. else
  313. echo " * Could not find world named \"$MCPATH/$WORLDNAME\""
  314. exit 1
  315. fi
  316. fi
  317. }
  318.  
  319. ## Backs up map by rsyncing current world to backup location, creates tar.gz with datestamp
  320.  
  321. mc_backupmap() {
  322. echo " * Backing up $SERVERNAME map named \"$WORLDNAME\"..."
  323. echo " * Syncing \"$MCPATH/$WORLDNAME\" to \"$BACKUPPATH/$WORLDNAME\""
  324. as_user "rsync --checksum --group --human-readable --copy-links --owner --perms --recursive --times --update --delete \"$MCPATH/$WORLDNAME\" \"$BACKUPPATH\""
  325. # if the nether exists, back it up
  326. WORLDNETHER="$WORLDNAME""_nether"
  327. if [ -d "$MCPATH/$WORLDNETHER" ]
  328. then
  329. echo " * Syncing \"$MCPATH/$WORLDNETHER\" to \"$BACKUPPATH/$WORLDNETHER\""
  330. as_user "rsync --checksum --group --human-readable --copy-links --owner --perms --recursive --times --update --delete \"$MCPATH/$WORLDNETHER\" \"$BACKUPPATH\""
  331. else
  332. echo " * \"$MCPATH/$WORLDNETHER\" doesn't exist, skipping."
  333. fi
  334. # if the end exists, back it up
  335. WORLDTHEEND="$WORLDNAME""_the_end"
  336. if [ -d "$MCPATH/$WORLDTHEEND" ]
  337. then
  338. echo " * Syncing \"$MCPATH/$WORLDTHEEND\" to \"$BACKUPPATH/$WORLDTHEEND\""
  339. as_user "rsync --checksum --group --human-readable --copy-links --owner --perms --recursive --times --update --delete \"$MCPATH/$WORLDTHEEND\" \"$BACKUPPATH\""
  340. else
  341. echo " * \"$MCPATH/$WORLDTHEEND\" doesn't exist, skipping."
  342. fi
  343. sleep 10
  344. echo " * Creating compressed backup..."
  345. NOW="$(date +%Y-%m-%d.%H-%M-%S)"
  346. # Create a compressed backup file and background it so we can get back to restarting the server
  347. # You can tell when the compression is done as it makes an md5sum file of the backup
  348. as_user "cd "$BACKUPPATH" && tar cfz \""$WORLDNAME"_backup_"$NOW".tar.gz\" \"$WORLDNAME\" && md5sum \""$WORLDNAME"_backup_"$NOW".tar.gz\" > \""$WORLDNAME"_backup_"$NOW".tar.gz.md5\" &"
  349. echo " * [OK] Backed up map \"$WORLDNAME\"."
  350. # if we backed up the nether, create a backup of that too
  351. if [ -d "$BACKUPPATH/$WORLDNETHER" ]
  352. then
  353. as_user "cd "$BACKUPPATH" && tar cfz \""$WORLDNETHER"_backup_"$NOW".tar.gz\" \"$WORLDNETHER\" && md5sum \""$WORLDNETHER"_backup_"$NOW".tar.gz\" > \""$WORLDNETHER"_backup_"$NOW".tar.gz.md5\" &"
  354. echo " * [OK] Backed up map \"$WORLDNETHER\"."
  355. fi
  356. # if we backed up the end, create a backup of that too
  357. if [ -d "$BACKUPPATH/$WORLDTHEEND" ]
  358. then
  359. as_user "cd "$BACKUPPATH" && tar cfz \""$WORLDTHEEND"_backup_"$NOW".tar.gz\" \"$WORLDTHEEND\" && md5sum \""$WORLDTHEEND"_backup_"$NOW".tar.gz\" > \""$WORLDTHEEND"_backup_"$NOW".tar.gz.md5\" &"
  360. echo " * [OK] Backed up map \"$WORLDTHEEND\"."
  361. fi
  362. # we can safely background the above commands and get back to restarting the server
  363. }
  364.  
  365. ## Backs up executable by copying it to backup location
  366.  
  367. mc_backupexe() {
  368. echo " * Backing up the $SERVERNAME server executable..."
  369. NOW="$(date +%Y-%m-%d.%H-%M-%S)"
  370. as_user "cp \""$MCPATH"/"$SERVICE"\" \""$BACKUPPATH"/"$SERVICE"_backup_"$NOW".jar\""
  371. echo " * [OK] Backed up executable."
  372. }
  373.  
  374. ## Removes any backups older than $BACKUPS_TO_KEEP days, designed to be called by daily cron job
  375.  
  376. mc_removeoldbackups() {
  377. echo " * Removing backups older than $BACKUPS_TO_KEEP days..."
  378. as_user "cd \"$BACKUPPATH\" && find . -name \"*backup*\" -type f -mtime +$BACKUPS_TO_KEEP | xargs rm -fv"
  379. echo " * Removed old backups."
  380. }
  381.  
  382. ## Rotates logfile to server.1 through server.7, designed to be called by daily cron job
  383.  
  384. mc_logrotate() {
  385. # Define a function to copy the old logfile to the new
  386. mc_copylog() {
  387. as_user "/bin/cp $logfile $MCPATH/$LOGNEW"
  388. }
  389.  
  390. # Server logfiles in chronological order
  391. LOGLIST="$(ls -r $MCPATH/server.log* | grep -v lck)"
  392. # How many logs to keep
  393. COUNT="6"
  394. # Look at all the logfiles
  395. for logfile in $LOGLIST; do
  396. LOGTMP="$(basename $logfile | cut -d '.' -f 3)"
  397. # If we're working with server.log then append .1
  398. if [ -z "$LOGTMP" ]
  399. then
  400. LOGNEW="server.log.1"
  401. mc_copylog
  402. # Otherwise, check if the file number is under $COUNT
  403. elif [ "$LOGTMP" -gt "$COUNT" ]
  404. then
  405. # If so, delete it
  406. as_user "rm -f $logfile"
  407. else
  408. # Otherwise, add one to the number
  409. LOGBASE="$(basename $logfile | cut -d '.' -f 1-2)"
  410. LOGNEW="$LOGBASE.$(($LOGTMP+1))"
  411. mc_copylog
  412. fi
  413. done
  414. # Blank the existing logfile to renew it
  415. as_user "echo -n \"\" > $MCPATH/server.log"
  416. }
  417.  
  418. ## Check if server is running and display PID
  419.  
  420. mc_status() {
  421. if server_running
  422. then
  423. echo " * $SERVERNAME status: Running (pid $JAVAPID)."
  424. else
  425. echo " * $SERVERNAME status: Not running."
  426. exit 1
  427. fi
  428. }
  429.  
  430. ## Display some extra environment informaton
  431.  
  432. mc_info() {
  433. if server_running
  434. then
  435. RSS="$(ps --pid $JAVAPID --format rss | grep -v RSS)"
  436. echo " - Java Path : $(readlink -f $(which java))"
  437. echo " - Start Command : $INVOCATION"
  438. echo " - Server Path : $MCPATH"
  439. echo " - World Name : $WORLDNAME"
  440. echo " - Process ID : $JAVAPID"
  441. echo " - Screen Session : $SCRNAME"
  442. echo " - Memory Usage : $[$RSS/1024] Mb ($RSS kb)"
  443. # Check for HugePages support in kernel, display statistics if HugePages are available, otherwise skip
  444. if [ -n "$(cat /proc/meminfo | grep HugePages_Total | awk '{print $2}')" -a "$(cat /proc/meminfo | grep HugePages_Total | awk '{print $2}')" ]
  445. then
  446. HP_SIZE="$(cat /proc/meminfo | grep Hugepagesize | awk '{print $2}')"
  447. HP_TOTAL="$(cat /proc/meminfo | grep HugePages_Total | awk '{print $2}')"
  448. HP_FREE="$(cat /proc/meminfo | grep HugePages_Free | awk '{print $2}')"
  449. HP_RSVD="$(cat /proc/meminfo | grep HugePages_Rsvd | awk '{print $2}')"
  450. HP_USED="$[$HP_TOTAL-$HP_FREE+$HP_RSVD]"
  451. TOTALMEM="$[$RSS+$[$HP_USED*$HP_SIZE]]"
  452. echo " - HugePage Usage : $[$HP_USED*$[$HP_SIZE/1024]] Mb ($HP_USED HugePages)"
  453. echo " - Total Memory Usage : $[$TOTALMEM/1024] Mb ($TOTALMEM kb)"
  454. fi
  455. echo " - Active Connections : "
  456. netstat --inet -tna | grep -E "Proto|$SERVERPORT"
  457. else
  458. echo " * $SERVERNAME is not running. Unable to give info."
  459. exit 1
  460. fi
  461. }
  462.  
  463. ## Connect to the active Screen session, disconnect with Ctrl+a then d
  464.  
  465. mc_console() {
  466. if server_running
  467. then
  468. as_user "screen -S $SCRNAME -dr"
  469. else
  470. echo " * [ERROR] $SERVERNAME was not running! Unable to console."
  471. exit 1
  472. fi
  473. }
  474.  
  475. ## Broadcasts a message
  476.  
  477. mc_say() {
  478. say_string="${@:1}"
  479. if [[ -z "$say_string" ]]
  480. then
  481. echo " * You need to enter your message. Usage; \"minecraft say message\""
  482. elif server_running
  483. then
  484. echo " * Broadcasting \"$say_string\""
  485. as_user "screen -p 0 -S $SCRNAME -X eval 'stuff \"say $say_string\"\015'"
  486. else
  487. echo " * [ERROR] $SERVERNAME was not running!"
  488. exit 1
  489. fi
  490. }
  491.  
  492. ## These are the parameters passed to the script
  493.  
  494. case "$1" in
  495. start)
  496. mc_start
  497. ;;
  498. stop)
  499. mc_stop
  500. ;;
  501. restart)
  502. mc_stop
  503. sleep 1
  504. mc_start
  505. ;;
  506. update)
  507. mc_updatecheck
  508. mc_stop
  509. mc_backupmap
  510. mc_backupexe
  511. mc_updatedo
  512. mc_start
  513. ;;
  514. backup)
  515. mc_checkbackup "$2"
  516. mc_saveoff
  517. mc_backupmap
  518. mc_backupexe
  519. mc_saveon
  520. ;;
  521. status)
  522. mc_status
  523. ;;
  524. info)
  525. mc_info
  526. ;;
  527. console)
  528. mc_console
  529. ;;
  530. # These are intended for cron usage, not regular users.
  531. removeoldbackups)
  532. mc_removeoldbackups
  533. ;;
  534. logrotate)
  535. mc_logrotate
  536. ;;
  537. # Debug usage only
  538. justbackup) # don't use this while the server is running!!!
  539. mc_checkbackup
  540. mc_backupmap
  541. mc_backupexe
  542. ;;
  543. say)
  544. mc_say "${@:2}"
  545. ;;
  546. *)
  547. echo " * Usage: minecraft {start|stop|restart|backup (worldname)|update|status|info|console|say}"
  548. exit 1
  549. ;;
  550. esac
  551.  
  552. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement