(Linux) Basic Backend Shell Mangement Script

Discussion in 'Bukkit Tools' started by ryunp, Mar 28, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    ryunp

    I have modified a shell script I discovered, created by Piffey (Backup Script Link). It covers all the basics of running a single minecraft server isntance in an intelligent, easy manner. I use SSH along with tmux to run my craftbukkit minecraft; this script is geared towards this scenario.

    UPDATE [06/19/11]: I am done adding rdiff-backup option into the script, and a force update option. I will update this post when the testing is complete.

    Requires: tmux or screen, craftbukkit
    Script name: minecraft.sh
    Arguments: status|start|stop|restart|update|backup|friendlystop
    Current Version: 1.4
    MD5: 2684417ac4dacad4cb1f8c2b0a7b8a59

    About This Script:
    This will manage a single instance of your craftbukkit minecraft server; no multi-server capabilities. This tool is not to replace general knowledge of running said server (or linux). As with most any script: adjust the pathing and configuration settings in the initial area of the script.

    Terminal Multiplexers: If you do not have either Screen or Tmux packages installed the script will exit. In case you have both installed, you can choose which one the script will use.

    Note: There is a bug with screen I need to smooth out (if even possible?) relating to multiple windows in the minecraft session, see bugs section at the bottom.

    Status - Checks the process status. Displays process activity & information (top/ps captures) if running
    Start - Starts the server
    Stop - Stops the server
    Restart - Restarts the server
    Update - Updates bukkit jar to latest recommended build only if needed.
    Backup - Backs up level data + bukkit jar file. Ability to archive in targz/zip if defined.
    Friendlystop - Will give 5 minutes before shutdown, alterting players every so often

    All these commands give console/ingame alerting and are fairly robust. Example output below:
    Command Examples (open)
    Code:
    <[email protected]>:$ minecraft.sh status
    Bukkit server currently OFFLINE
    #
    #
    <[email protected]>:$ minecraft.sh start
    Starting Bukkit server...
    screen: no session deteceted; create new session
    Bukkit server successfully started!
    #
    #
    <[email protected]>:$ minecraft.sh status
    Bukkit server currently ONLINE:
    19191 <user>      20  0 2440m 297m 9.8m S  4.0 11.8  0:36.76 java
    19191 pts/2    Sl+    0:36 java -Xmx2048M -Xms2048M -jar <path>/craftbukkit.jar nogui
    #
    #
    <[email protected]>:$ minecraft.sh backup
    Starting multiworld backup...
    Copying 'world' + 'craftbukkit.jar' to '<path>/backups/world_110408-180021'...
    Creating zip archive file of 'world_110408-180021'...
    Backup complete.
    #
    #
    <[email protected]>:$ minecraft.sh backup
    Starting multiworld backup...
    Starting incremental backup of 'world' to '<path>/backups/world'...
    Starting incremental backup of 'world2' to '<path>/backups/world2'...
    Backup complete.
    
    <[email protected]>:$ minecraft.sh update
    Bukkit server successfully stopped!
    [Omitted HTTP download sequence]
    2011-04-08 18:01:53 (1.27 MB/s) - `<path>/craftbukkit-updater.jar' saved [7453149/7453149]
    `<path>/craftbukkit.jar' -> `<path>/craftbukkit.jar.old'
    `<path>/craftbukkit-updater.jar' -> `<path>/craftbukkit.jar'
    You must now manually start the Bukkit server.
    #
    #
    <[email protected]>:$ minecraft.sh update
    No need, local/release jar files are 7624904 bytes; to force update: forceupdate
    #
    #
    <[email protected]>:$ minecraft.sh stop
    Process failed to stop!
    Attempting to kill rogue craftbukkit.jar process...
    craftbukkit.jar process terminated!
    


    Entire Script (open)
    Code:
    #!/bin/bash
    
    ##
    # Title:    Minecraft - Bukkit server management script
    # Version:    1.4
    # Date:        06/02/11
    # Author:    ryunp* (www.ryunp.com)
    # URL:        http://forums.bukkit.org/threads/linux-basic-backend-shell-mangement-script.10249/
    #
    # *Startup script originated by Piffey (Piffey DOT com),
    # who adapted from ragon's script (frederik.engels24 AT gmail DOT com),
    # now upgraded by ryunp (ryunp DOT com).
    ##
    
    ## Change Log
    
    ## 03/27/11 Updates (ryunp)
    #    Modified for tmux
    #    Altered $dateformat into `_yymmdd-hhmmss` so you get: <world>_yymmdd-hhmmss
    #    This allows unique inter-minute backups
    #    Invocation variable ($bukkitinvoaction) instead of just RAM allocation
    #    Added bukkitstatus() to check offline/online status
    #        If online shows process activity/information
    #    Updated startbukkit() & stopbukkit() to check java process status after invoked/stopped
    #        Added friendlystop timing sequence to the stopbukkit() itself; checks for arg given in case statement
    #     updatebukkit() will save current JAR as <JAR>.old and rename newly downloaded file
    #    bukkitbackup() added zip + targz support by choosing, added customizable messaged for before/after
    #        Added a second backupmsg and completion var, tar & zip integration (if zip is installed; checks before attempting)
    #    Added status to argument case statement and catchall display, updated friendlystop
    ##
    
    ## 06/05/11 Updates (ryunp)
    #    Added screen support; script only runs with at screen or/and tmux installed
    #        Toggle tmux/screen usage in config area if you have both
    #    checkmultiplexers() checks for the installation of tmux/screen before beginning, exiting if none
    #    sendtomultiplexer() now handles all calls to the server for tmux/screen
    #    Update Sequence upgraded; checks for the need of an update first
    #        Tries to download the update first, in case of problems shutdown sequence aborted
    #    isrunning() function added to reduce redundancy in checking running status
    #    Beefed up bukkitstart() so that it can handle mulitple situations
    #        Checks for sessions in tmux or screen before taking action
    #    Renamed the temporary update file variable to be more obvious
    #    Cleaned up the script: added comments, corrected lines not tabbed (were spaces), aesthetics improved.
    ##
    
    ################################
    ### BEGIN CONFIGURATION AREA ###
    ################################
    
    # Pathing information
    bukkitdir=~/"Minecraft/Server/craftbukkit/"
    backupdir=~/"Minecraft/Server/craftbukkit/backups/"
    bukkitfilename="craftbukkit.jar"
    
    # Will omit backup messages if quotes left empty
    backupmsg="Backup in progress. Saving disabled for a moment."
    backupmsg2="-Senior Admin Engineer"
    backupmsgdone="Level data successfully backed up!"
    dateformat="_$(date '+%y%m%d-%H%M%S')"
    
    # Determine additional archived level backups
    # Note: `zip` format is not native to (all?) linux distro's, must install to work.
    backuplevelgz="true"
    backuplevelzip="false"
    #backupincremental="true" #IN PROGRESS
    
    # multiplexer Overrides; set an active multiplexer (just comment [#] the other out)
    activemultiplexer="tmux"
    #activemultiplexer="screen"
    
    # Custom java binary location. Do not change unless custom installation was done, ex: `/opt/java/bin/java`.
    # This assumes java is in the default location: /usr/bin/java.
    javaloc="java"
    
    # Invocation parameters. Set the amount of RAM you want to allocate, Java heap max and initial size.
    # Good practice is to have the numbers match.
    bukkitinvocation="$javaloc -Xmx2048M -Xms2048M -jar $bukkitdir$bukkitfilename nogui"
    
    # Make sure you change this to the name of your world folder!
    # Add additional worlds by separating them with a white space. (world nether pvp chaos blackmesa).
    declare -a worlds=(world)
    numworlds=${#worlds[@]}
    
    # This currently points to the "preferred" release for bukkit which is kind of like a stable version.
    bukkiturl="http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar"
    # bukkitupdatetempfile is the temporary filename used in the downloading sequence, no use changing this.
    bukkitupdatetempfile="craftbukkit-updated.jar"
    
    ##############################
    ### END CONFIGURATION AREA ###
    ##############################
    
    ## Inital multiplexer checking logic, quit if none detected before continuing with script
    checkmultiplexers() {
        multiplexers=0
    
        # tmux
        if dpkg -l | grep ^ii | grep tmux | grep -i 'terminal multi' > /dev/null; then
            multiplexers=$((multiplexers+1))
        else
            activemultiplexer="screen"
        fi
    
        # screen (note: Screen's description has a spelling mistake: 'terminal multiplexor'... heh)
        if dpkg -l | grep ^ii | grep screen | grep -i 'terminal multi' > /dev/null; then
            multiplexers=$((multiplexers+1))
        else
            activemultiplexer="tmux"
        fi
    
        # Final Check
        if [ "$multiplexers" -lt 1 ]; then
            echo "No 'screen' or 'tmux' detected... script only runs on these recommended multiplexers!"
            exit 1
        fi
    
        # Return an OK signal if passes scrutiny (why, I do not know)
        return 0
    }
    checkmultiplexers
    
    ##
    #MISC FUNCTIONS
    ##
    
    # multiplexer interaction requests go through here, testing which is active
    sendtomultiplexer() {
        # tmux 'send'
        if [ "$activemultiplexer" = "tmux" ]; then
            tmux -q send -t minecraft:bukkit "$1" C-m > /dev/null
        fi
        # screen 'stuff'
        if [ "$activemultiplexer" = "screen" ]; then
            screen -q -S minecraft -p bukkit -X stuff "$1$(echo -ne '\r')" > /dev/null
        fi
    }
    
    # Check process status
    isrunning() {
        #echo "\$activemultiplexer: $activemultiplexer"
        # tmux process check
        if [ "$activemultiplexer" = "tmux" ]; then
            ps ax | grep -v grep | grep -v tmux | grep "$bukkitfilename" > /dev/null
            return $?
        fi
        # screen process check
        if [ "$activemultiplexer" = "screen" ]; then
            ps ax | grep -v grep | grep -v screen | grep "$bukkitfilename" > /dev/null
            return $?
        fi
    }
    
    ##
    #Script Argument Commands
    ##
    
    bukkitstatus() {
        if isrunning; then
            echo "Bukkit server currently ONLINE:"
            # Get the Process ID of running JAR file
            bukkitPID=`ps ax | grep -v grep | grep -v sh | grep -v -i 'tmux' | grep -v -i 'screen' | grep "$bukkitfilename"`
    
            # Display process activity information of bukkit (5 character length pID)
            top -n 1 -p ${bukkitPID:0:5} | grep ${bukkitPID:0:5}
    
            # Display prcoess infomation of bukkit
            echo "$bukkitPID"
        else
            echo "Bukkit server currently OFFLINE"
            exit 0
        fi
    }
    startbukkit() {
        if isrunning; then
            echo "Bukkit server is already running."
            exit 0
        else
            echo "Starting Bukkit server..."
            cd $bukkitdir
    
            # Check for a tmux minecraft session
            if [[ "$activemultiplexer" = "tmux" ]]; then
                if tmux ls | grep minecraft > /dev/null; then
                    # Session deteceted; create new window
                    echo "tmux: session detected; create new window"
                    tmux new-window -d -t minecraft -n bukkit "$bukkitinvocation"
                else
                    # No session deteceted; create new session
                    echo "tmux: no session detected; create new session"
                    tmux new-session -d -n bukkit -s minecraft "$bukkitinvocation"
                fi
            fi
    
            # Check for a screen minecraft session
            if [ "$activemultiplexer" = "screen" ]; then
                if screen -ls | grep minecraft > /dev/null; then
                    # Session deteceted; create new window
                    echo "screen: session detected; create new window"
                    screen -S minecraft -X screen -t bukkit
                    screen -S minecraft -p bukkit -X stuff $bukkitinvocation$(echo -ne '\r')
                else
                    # No session deteceted; create new session
                    echo "screen: no session detected; create new session"
                    screen -S minecraft -t bukkit -dm $bukkitinvocation
                fi
            fi
    
            # Check for process status, wait 5 seconds for plugin initialization
            sleep 5
            if isrunning; then
                echo "Bukkit server successfully started!"
            else
                echo "Bukkit server failed to start!"
            fi
        fi
    }
    
    stopbukkit() {
        if isrunning; then
            # Check for friendlystop trigger; wait if so
            if [ "$1" = "friendly" ]; then
                echo "Sending 5 minute shutown warning"
                sendtomultiplexer "say Going down for an update in 5 minutes."
                sleep 240
                echo "Sending 1 minute shutdown warning"
                sendtomultiplexer "say Going down for an update in 60 seconds."
                sleep 30
                echo "Sending 30 second shutdown warning"
                sendtomultiplexer "say Going down for an update in 30 seconds."
                sleep 20
                echo "Sending 10 second shutdown warning"
                sendtomultiplexer "say Going down for an update in 10 seconds."
                sleep 10
            fi
    
            # Stop Server
            sendtomultiplexer "stop"
            # Screen's 'bukkit' window will persist after server stop,
            # this will exit the window. Should not affect tmux as
            # it's window 'bukkit' is already gone.
            sleep 1
            sendtomultiplexer "exit"
    
            # Check for process status, waiting 5 seconds for shutdown procedure to finish
            sleep 5
            if isrunning; then
                # Uh-oh!
                echo "Process failed to stop!"
    
                # Take more aggresive action against pID
                echo "Attempting to kill rogue $bukkitfilename process..."
    
                # Get the Process ID of running JAR file
                bukkitPID=`ps ax | grep -v grep | grep -v -i tmux | grep -v sh | grep "$bukkitfilename"`
                kill ${bukkitPID:0:5}
                sleep 1
    
                # Check for process status after pkill attempt
                if isrunning; then
                    echo "$bukkitfilename could not be killed!"
                    exit 1
                else
                    echo "$bukkitfilename process terminated!"
            fi
            else
                echo "Bukkit server successfully stopped!"
            fi
        else
            echo "Bukkit server is not running."
            exit 0
        fi
    }
    
    updatebukkit() {
        # Get bytes of official release jar, and local jar
        remotejarsize=`wget --spider $bukkiturl 2>&1 | grep -i length | awk '{print $2}'`
        localjarsize=`ls -l $bukkitdir$bukkitfilename | awk '{print $5}'`
    
        # Compare jar filesizes, check need for update
        if [ $remotejarsize -eq $localjarsize ]; then
            echo "No need; Local and recommended release jar file sizes are $localjarsize bytes."
            #echo "To force update: add '-f' switch"
        else
            # Download new JAR quietly and echo when done, error if failure and exit
            wget -q -O "$bukkitdir$bukkitupdatetempfile" "$bukkiturl"
            if [ "$?" -eq 0 ]; then
                echo "${bukkitupdatetempfile##*/} Download Complete."
            else
                echo "Error downloading file."
                exit 1
            fi
    
            sleep 1
    
            # Alert players Bukkit server going down for repairs
            if isrunning; then
                echo "Sending 60 second shutdown warning"
                sendtomultiplexer "say Going down for an update in 60 seconds."
                sleep 50
                echo "Sending 10 second shutdown warning"
                sendtomultiplexer "say Going down for an update in 10 seconds."
                sleep 10
                stopbukkit
            fi
    
            # Backup old JAR file and rename newly downloaded
            mv -v "$bukkitdir$bukkitfilename" "$bukkitdir$bukkitfilename.old"
            mv -v "$bukkitdir$bukkitupdatetempfile" "$bukkitdir$bukkitfilename"
            echo "You must now manually start the Bukkit server."
        fi
    }
    
    backupbukkit() {
        echo "Starting multiworld backup..."
    
        if isrunning; then
            # Alert players (if $backupmsg is blank, dont bother with $backupmsg2)
            if [ "$backupmsg" != "" ]; then
                sendtomultiplexer "say $backupmsg"
                if [ "$backupmsg2" != "" ]; then
                    sendtomultiplexer "say $backupmsg2"
            fi
            fi
    
            # Last save before backup
            sendtomultiplexer "save-all"
            sleep 5
    
            # Turn chunk saving off
            sendtomultiplexer "save-off"
        fi
    
        # Check for backup directory
        if ! [ -d $backupdir ];then mkdir -p $backupdir; fi
    
        # Determine if zip package is installed on host
        if ! dpkg-query -W 'zip' > /dev/null; then backuplevelzip="false"; fi
    
        # Iterate through level backups
        cd $backupdir
        for ((i=0;i<$numworlds;i++)); do
            echo "Copying '${worlds[$i]}' + '$bukkitfilename' to '$backupdir${worlds[$i]}$dateformat'..."
    
            # Explicitly create backup world directory
            mkdir $backupdir${worlds[$i]}$dateformat
    
            # Copy required files
            cp -R $bukkitdir${worlds[$i]} $backupdir${worlds[$i]}$dateformat
            cp $bukkitdir$bukkitfilename $backupdir${worlds[$i]}$dateformat
    
            # TARgz backup sequence
            if [ "$backuplevelgz" == "true" ]; then
                echo "Creating tar archive file of '${worlds[$i]}$dateformat'..."
                tar zcf ${worlds[$i]}$dateformat.tar.gz ${worlds[$i]}$dateformat/
            fi
    
            # ZIP backup sequence
            if [ "$backuplevelzip" == "true" ]; then
                echo "Creating zip archive file of '${worlds[$i]}$dateformat'..."
                zip -rq ${worlds[$i]}$dateformat ${worlds[$i]}$dateformat
            fi
        done
        sleep 1
    
        # Alert players backup is finished
        if isrunning; then
            # Turn saving back on
            sendtomultiplexer "save-on"
            if [ "$backupmsgdone" != "" ]; then
            # Alert players backup finished
            sendtomultiplexer "say $backupmsgdone"
            fi
        fi
        echo "Backup complete."
    }
    
    ##
    #Script Arguements
    ##
    
    case $1 in
        status)
            bukkitstatus
            ;;
        start)
            startbukkit
            ;;
        stop)
            stopbukkit
            ;;
        restart)
            stopbukkit
            sleep 5
            startbukkit
            ;;
        update)
            updatebukkit
            ;;
        backup)
            backupbukkit
            ;;
        friendlystop)
            stopbukkit friendly
            ;;
        *)
            echo "Usage: $0 {status|start|stop|restart|update|backup|friendlystop}"
    esac
    
    exit 0
    


    If you have anything to add or find any bugs please let me know! I did my best to cover user-error and system dependencies intelligently, do let me know if you have some more advanced tricks up your sleeve.

    TODO [updated 06/09/11]
    -Add Screen support [DONE 06/06/11]
    -Incremental backup method [IN PROG]
    -Make sure server has sufficient time for saving/closing between actions (for large worlds)
    -Add force update option (rework argument handling)

    BUGS [updated 06/06/11]:
    -Screen: Multiwindow Session vs Script
    If you create windows within the screen's minecraft session it will confuse the script; when trying to stop the server it will fail to send the stop command and kill the process instead. Do not multitask inside of the script's session; need to figure out why the window targeting command is not functioning like it should. (most likely a layer 8 issue)
     
  2. Offline

    ryunp

    Updated a few logistic quarks and spelling mistakes. Rogue process' will now be properly terminated. Although I doubt anyone really uses this :)
     
  3. Offline

    Birdie

    Why'd you use tmux, could you create one with screen?

    Nice work btw :)
     
  4. Offline

    ryunp

    Tmux is essentially screen with more features. I sugget installing the package and checking it out!

    I doubt I'll add screen support, but who knows I may get bored enough in the future. :)
     
  5. Offline

    Birdie

    Any word on that screen support?
     
  6. Offline

    Terry Tibbs

    It's really not all that difficult - simply replace all references and params to tmux with screen equivalents.

    Now, onto a more challenging question. Would it be possible to implement rdiff backups?
    I run a server that's just passed the 200mb mark for our current world, i really can't keep up with removing backups, especially since the only changes being made between backups are minimal. Anyone?

    UPDATE: I'll try implementing this tomorrow.
     
  7. Offline

    Birdie

    Our world is 1.8GB and we use BackupPlugin, works just fine, no lag at all!
     
  8. Offline

    Terry Tibbs

    Awesome! But does it do differential backups? How big are your backups?
    I'd really prefer to make use of the great flexibility of shell scripts and cron tabs, all while minimizing running plugins on the server for redundancy.
     
  9. Offline

    Birdie

    Does full backups of 1.7/1.8GB
     
  10. Offline

    ryunp

    Initially I was thinking of doing 'tmux command || screen command', or possibly a sequence in the beginning that looks to see if tmux is installed to set a certain var. But just wanted something working at the time. I didn't think too much about world size and the logistics that ensue.

    We can beefcake the script up. I'll mess around with adding screen support, I'll try the 'or' method and see how stable it is. Otherwise just a package detection line in the beginning.

    I can add a T/F var in the config area for differential style backups with the rdiff-backup. I believe you can do something similar with zip/tar compression. That way you could have either timestamped individual backups (optional w/compression), or just a single backup file (optional w/compression) with a simple filename.

    I am fairly busy this weekend, I may be messing with it Sunday. My buddies barely use my server now a days, so I have a great testing environment. I'll increase my world size to something larger than a few hundred megs and have at it.

    Another issue I foresee is the time it takes to shutdown/start/backup depending on filesize. I currently have around 5 second grace period for most of the commands. I'll see if I can come up with a better way to allow a better implementation of the 'grace period' before the script gets angry/misinterprets uncomplete processing.
     
  11. Offline

    Birdie

    Updates? :D
     
  12. Offline

    ryunp

    Sorry about the stagnant thread, I have been in a bit of a depressive funk lately. I have gained motivation once again and am getting back on the script. I have also decided to make all the BASH calls that sleep into background processes so you don't have to wait for the script to finish before gaining control of the terminal again.

    I am fairly new to unix scene, so bare with me. I will keep you guys updated :)

    Edit: I have already begun adding screen to the script. I have it setup so that you can enable/disable either of them. Initially I was going to go with an OR on the multiplexer call, but had to rework it due to the chances of someone having both screen and tmux installed. Hmm I'll deal with this later.

    Edit2: I believe minecraft has a differential style world save, where it only writes chunks that have changed. Worlds over 1GB, does it take a considerable amount of time to save, or is it just a few seconds? I assume the latter, but just to be sure.

    Edit3: After swinging by the local bar I had some great ideas for the script. It is coming along nicely. It is not done yet, but on it's way. Here is a sneak peak:
    Show Spoiler

    Code:
    ## 06/01/11 Updates (ryunp)
    #    Added screen support; script only runs with either Screen or Tmux installed
    #        Toggle tmux/screen usage in config area, new function sendtomultiplexer()
    #    Update Sequence upgraded; checks for the need of an update first
    #        Tries to download the update first, in case of problems shutdown sequence aborted
    #    isrunning() function added to reduce redundancy in checking running status
    #    Cleaned up a bit of logic. Added more comments.
    ##
    
    # Multiplexer interaction requests go through here, testing which is active
    sendtomultiplexer() {
        # tmux
        if [ "$activemultiplexer" = "tmux" ]; then
            tmux send -t minecraft:bukkit "$1" C-m
        # screen
        else if [ "$activemultiplexer" = "screen" ]; then
            screen -S bukkit -p 0 -X stuff "$1$(echo -ne '\r')"
        fi
    }
    
    # Check process status
    isrunning() {
        # This seems so fucking retarded. And so far untested. hurrgt.
        if ps ax | grep -v grep | grep -v -i tmux | grep "$bukkitfilename" > /dev/null || \
            ps ax | grep -v grep | grep -v -i screen | grep "$bukkitfilename" > /dev/null; then
            return "true"
        else
            return "false"
        fi
    }
    ...
    updatebukkit() {
        # Get bytes of official release jar, and local jar
        hostedjarsize=(wget --spider $bukkiturl 2>&1 | grep -i length | awk '{print $2}')
        localjarsize=(ls -l $bukkitdir$bukkitfilename | awk '{print $5}')
    
        # Compare jar filesizes, check need for update
        if ( "$hostedjarsize" = "localjarsize" ); then
            echo "No need for update. Both local and latest official jar filesizes are $localjarsize bytes."
        else
            # Download new JAR quietly and echo when done, error if failure and exit
            wget -q -O "$bukkitdir$bukkitupdate" "$bukkiturl" && \
            echo "${bukkitupdate##*/} Download Complete." || \
            echo "Error downloading file. Upgrade stopped." && exit 1
            
            sleep 1
            ... <stop server>
    

    So a call like: 'sendtomultiplexer "say LOLOLHAYGUISE"' would work regardless of the multiplexer active (the main hurdle adding screen support). Nifty. And an update to updatebukkit() makes things more intelligent :).
     
  13. Offline

    Birdie

    Nice, waiting :p
     
  14. Offline

    etskinner

    I'm having some troubles getting the script to work, most likely stemming from the fact that I've just started with linux. This may not even be a problem with the script, but instead with my inferior skills.

    I'm running ubuntu 11.04 with tmux, and I store my bukkit files in ~/bukkit. I've only modified the script as you see in this pastebin (I only changed the parts that said they should be changed).

    When I try to run the script by typing "./bukkit/minecraft.sh" into the terminal, it seems to work, giving me the list of arguments. However, when I then try to use one of those arguments (e.g. "./bukkit/minecraft.sh start"), it simply answers back "bash: .bukkit/minecraft.sh: No such file or directory"

    I thought maybe I have to use "sh" to execute the script. When I try that, the terminal answers back "./bukkit/minecraft.sh: 53: Syntax error: "(" unexpected" . I've gotten this same error when using Piffey's backup script with similar configuration.

    Also, do I need a specific craftbukkit-updater.jar file, or is that just some sort of placeholder?

    Any help would be much appreciated.
     
  15. Offline

    ryunp

    Script has been updated! Screen and tmux now work. I have been testing this all day and have only found one scenario that is unsatisfactory for me relating to Screen:
    When there is a screen session open with minecraft running, and you create a new window inside of this. Even if you change the new window title to something besides 'bukkit' the script doesn't seem to target the window correctly. So if you are an avid screen user on the system, let the minecraft server have it's own session.

    Added more 'intelligence' into the script. You can select which multiplexer to use and if you choose one that is not installed the script will automagically switch to the installed package for use. That being said: if you have both installed make sure to select the one you want in the config area, it defaults to tmux.

    Overall the code is more organized and more stable. Like I said above, I've been running through 'apt-get install <tmux/screen>' + 'apt-get remove <tmux/screen>' making sure each one works in most scenarios I can think of.

    Try changing the "~/bukkit/" to ~/"bukkit/". The ~/ isn't getting a chance to be parsed into /home/<user> since it is in string quotes.

    Code:
    bukkitdir="~/bukkit/"
    backupdir="~/bukkit/backups/"
    
    should be
    
    bukkitdir=~/"bukkit/"
    backupdir=~/"bukkit/backups/"
    
    Or maybe I am over-doing the strings, I am sure that just
    
    bukkitdir=~/bukkit/
    backupdir=~/bukkit/backups/
    
    would suffice.
    And yes, 'bukkitupdate' is just a temp file to which it downloads to. I may just erase this from the config area as it really doesn't need to be configured :)
    edit: changed the variable name and comment to better document
     
  16. Offline

    etskinner

    Thanks for the reply. It turns out, for me, that no quotes at all works, and the alternate way you suggested with quotes (~/"bukkit/", etc.) actually makes it return the same syntax error as before.

    I've tried going into tmux to try to see the console of the server, to no avail. How can I do this so that I can see what's going on with the server (besides using the status argument with your script, of course)?
     
  17. Offline

    ryunp

    Check the help or man pages.
    Although the commands: 'tmux -help', 'tmux a -help' should get you in the right direction.

    I usually just use 'tmux a' to get into the last active session, than from there use the 'ctrl b + s' to show a list of other sessions. But if you just want to attach directly into the minecraft session do 'tmux a -t minecraft'. While in a tmux session you can see a list of tmux shortcut commands with 'ctrl b + ?'. Oh, and disconnecting from the session is 'ctrl b + d'. Otherwise google, or 'man tmux' as always for particular uses.

    On that note, it took me a solid few hours to scour over the tmux/screen man pages along with tweaking to finally get of the external calls working correctly. Still doesn't quite target certain windows correctly on screen; kind of pissin' me off.

    Oh and to make life easier, place a symbolic link (ln -s ~/yourMinecraftScriptLocationHere) in the /bin directory to allow easy access to the script; 'minecraft.sh -command-' without having to declare the pathing to the script each time saves the fingers.
     
  18. Offline

    etskinner

    Thanks a lot, it's stuff like this that makes the Linux community great.
     
  19. Offline

    ryunp

    I am willing to help out regardless of the OS, but yes the unix world is quite intriguing. ;)
     
  20. Offline

    Dan

    I'm using Ubuntu 11.04 and keep getting an error
    Code:
    minecraft.sh: 81: Syntax error: "(" unexpected
    Line 81 turns out to be the line where the declaration is made for the world name list. Any ideas?
     
  21. Offline

    etskinner

    Dan, I get a similar error, but only when I launch it in a certain way. In order to replicate your problem, I have to use "sh ./bukkit/bukkit.sh" (my stuff is stored in ~/bukkit/). I'm not sure what about that does it, but I get the exact same error you're getting.

    As ryunp described before, a good way to easily launch the script is to put a symbolic link in the /bin directory. (ln -s ~/yourMinecraftScriptLocationHere while in the /bin directory). After I've done that, I can simply run it from my home directory by typing "bukkit.sh start". This seems to fix that problem for whatever reason.
     
  22. Offline

    ryunp

    Yeah by running it through the shell I get the same error ('sh <script>'). Any particular reason why you are invoking the older shell before the command? You are already in the BASH and I see no reason to explicitly declare SH beforehand. I think it may have to do with compatibility, as if arrays were declared differently in Bourne Shell.

    EDIT: A bit of research later reveals:
    AKA stop using the old shell :). You'll have to excuse my lack of unix knowledge; Feb 13 2011 was the first day I even touched a unix shell (getting a minecraft server going).

    also...
    note that the ~/"<path>" method works fine, 'sh xxxx' was causing the issue. If your path to the minecraft dir's has spaces for some reason, '~/"minecraft server/bukkit/craftbukkit.jar"', than the quotes will be needed. A simple '~/minecraft/bukkit/craftbukkit.jar' will work without quotes.
     
  23. Offline

    Dan

    I'm fairly new to Linux as well so that is how I had been launching some other scripts which were very basic. I'll take a look!

    ** edit: I did make the script executable and everything works as advertised now. Thank you for bringing that to my attention. I had been trying to find information on what could have been causing the trouble, but hadn't had any luck.​

    I did notice, however, that if I try to start a server using the script, it will not start the server stating that it is already running. I run two different servers on the same machine for my friends and myself. Is there any way to have the script to only look for an instance of the screen session defined in the script rather than looking for the process? I could get around it by renaming the craftbukkit.jar file something different for each server, but would rather not if I can avoid it.

    Great script though; thank you for putting it out to the community!
     
  24. Offline

    ryunp

    'chmod +x <file>' is a basic aspect of a file system (permissions, file modes). Linux is very fragile in that you have total control over everything; a small mistake could delete all the files on your disk. Careful.

    There is nothing indicating that functionality (say: 'minecraft.sh [server#] [command]') in the post. So no, this does not manage multiple server services running at the same time. I will add that to the OP just to specifically declare this, which is actually something I should have better documented.

    NOTE: This script is NOT a replacement for knowledge of administering a linux minecraft server (or unix, for that matter). This is just a tool to aid you in the repetitive motions that normally take a few lines of shell.
     
  25. Offline

    fffizzz

    Any chance of making it add a Symbolic Link to the latest backup of each world? makes automation of say "overviewer" a bit easier.
     
  26. Offline

    fffizzz

    bump?
     
  27. Offline

    vYN

    how can i see the console for the server??? with tmux
     
  28. Offline

    etskinner

    Simply type "tmux a" to attach to the virtual terminal
     
  29. Offline

    vYN

    uhm. i did that.. but i can't see the bukkit server console...
     
Thread Status:
Not open for further replies.

Share This Page