Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- #
- # Starbinder: A StarBound game server control system.
- # v20140208.2214
- #
- PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
- AVAIL_ACTIONS="start|stop|restart|status|list|update|update-validate|console|install|relink|delink|lockdown-master|unlock-master|bootstrap"
- AVAIL_ACTIONS1="list|update|update-validate|lockdown-master|unlock-master|bootstrap"
- AVAIL_ACTIONS2="start|stop|restart|status|console|install|relink|delink"
- MYNAME=$(basename $0)
- RUNUSER=$(whoami)
- IN_ACTION="$1"
- IN_SERVNAME="$2"
- # INSTALL_PREFIX=""
- INSTALL_PREFIX="starbound-"
- #
- # If IN_SERVNAME has any trailing slashes, due to shell autocompletion, remove it
- if (echo "$IN_SERVNAME" | egrep "*/$" &> /dev/null) ; then
- echo "NOTE: Trimming target trailing slash on input."
- IN_SERVNAME=$(echo "$IN_SERVNAME" | tr -d /)
- fi
- # If an INSTALL_PREFIX has been set, preprend it to input if not included, for user convinience.
- if [[ -n "$INSTALL_PREFIX" ]] ; then
- if ! ( echo "$IN_SERVNAME" | egrep "^$INSTALL_PREFIX" ) ; then
- SERVNAME=${INSTALL_PREFIX}${IN_SERVNAME}
- else
- SERVNAME=$IN_SERVNAME
- fi
- fi
- MAILER=/usr/bin/mail
- MAILTO=asdf@asdf.com
- MAILNOTIFY=no
- STEAMCMD_DIR=~/bin/steamcmd
- STEAMCMD_BIN=$STEAMCMD_DIR/steamcmd.sh
- STEAMCMD_SERVER_APPID=211820
- STEAMCMD_USER=""
- STEAMCMD_PASSWD=""
- APPDIR=~/starbinder
- # APPDIR=/srv/starbinder
- MASTER_INSTALLID=starbound-MASTER
- APPBIN=starbound_server
- BINDIR=$APPDIR/$SERVNAME/linux64
- SBCFGFILE=$APPDIR/$SERVNAME/starbound.config
- LOCKFILE=$APPDIR/$MASTER_INSTALLID/lockfile.lock
- PIDFILE=$APPDIR/$SERVNAME/running.pid # Also set in f_getpid
- NICECMD="nice -n 11 ionice -c 2 -n 6"
- # --
- f_cleanuptrap() {
- # Cleanup trap.
- echo ""
- echo "Cleaning up..."
- # Remove the update lock file, if we need to, and if it is there.
- if [[ "$UPDATING" == 1 ]] ; then
- [[ -f "$LOCKFILE" ]] && rm -f "$LOCKFILE"
- fi
- echo "Done."
- echo ""
- exit 90
- }
- f_getpid() {
- # Get the current PID of the running server.
- PIDFILE=$APPDIR/$SERVNAME/running.pid # required for loops.
- if [[ -r "$PIDFILE" ]] ; then
- SERVPID=$(cat $PIDFILE)
- SERVSTATUS="running"
- # Test for crashed/broken servers by checking for a valid running process.
- if [[ -n "$SERVPID" ]] && [[ -z "$(ps --no-headers -p $SERVPID -o pid)" ]] ; then
- echo ""
- echo "ERROR: Found server PIDFILE with PID $SERVPID, but process is missing."
- echo "The server may have crashed or was shut down improperly, without reaping the PIDFILE."
- echo "We will now stop the server, which will prevent any further damage and clean up this mess."
- rm -f "$PIDFILE" || { echo "PANIC!" ; exit 1 ; } #The PIDFILE is junk, so delete it. If this wasn't here, infinite loop.
- f_stop ; exit 1
- fi
- else
- SERVPID=""
- SERVSTATUS="stopped"
- fi
- }
- f_bootstrap() {
- # First-time installation of the master install, checking for dependancies, and other basic setup.
- echo ""
- echo "We will now attempt to do the basic setup needed to get $MYNAME up and running."
- echo ""
- #
- # Dependancy checks.
- echo "$MYNAME requires a number of dependancies to run. We will check for them now..."
- echo "NOTE: We do not bother to check for certain core utilities, such as shell built-ins, mkdir, et-cetera."
- echo ""
- echo "VERIFICATION: Shall we continue?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- fi
- for EACH in lns symlinks sudo tmux renice kill lsof egrep mail chown chmod ; do
- DEP_FILE=$(which $EACH)
- if [[ -z "$DEP_FILE" ]] ; then
- DEP_FAIL=1
- DEP_FILE="Not found."
- DEP_STATUS="FAILURE!"
- else
- DEP_STATUS="Success!"
- fi
- echo "Checking dependancy tool: $EACH ... Status: $DEP_STATUS : Path: $DEP_FILE"
- done
- echo ""
- if [[ "$DEP_FAIL" == 1 ]] ; then
- echo "ERROR: At least one dependancy check failed. You will need to fix this or this script will not work."
- echo "Quitting."
- echo ""
- exit 1
- else
- echo "All dependancies found successfully."
- echo ""
- fi
- #
- # Verify that SteamCMD is installed where it should be.
- echo "We will now verify that SteamCMD is installed where it should be."
- echo ""
- echo "VERIFICATION: Shall we continue?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- fi
- echo ""
- if [[ -x "$STEAMCMD_BIN" ]] ; then
- echo "SteamCMD found successfully!"
- else
- echo "ERROR: SteamCMD not found. Install SteamCMD or fix the path to the executable/script."
- echo "Qutting."
- echo ""
- exit 1
- fi
- echo ""
- #
- # APPDIR check and creation.
- echo "Now we will check if the configured APPDIR exists, and create it if necessary."
- echo "This is where the server installation directories will reside."
- echo ""
- # Test to see if APPDIR already exists.
- if [[ -d "$APPDIR" ]] ; then
- echo "NOTICE: APPDIR $APPDIR already seems to exist."
- echo "VERIFICATION: Shall we continue anyway?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- fi
- else
- echo -n "Creating the APPDIR directory at: $APPDIR ..."
- mkdir "$APPDIR" ; X_MKDIR_APPDIR=$?
- if [[ "$X_MKDIR_APPDIR" == 0 ]] ; then
- echo "Successful."
- # Quietly set perms.
- # chmod u=wrx,g=rx,o-wrx "$APPDIR"
- else
- echo "Failure."
- echo ""
- echo "The attempt to create the APPDIR failed. This is probably because you don't have filesystem permission to do so."
- echo "This is not unexpected if you were trying to install into /srv."
- echo ""
- echo "We will try again with sudo..."
- sudo -E mkdir "$APPDIR" ; X_SUDO_MKDIR_APPDIR=$?
- if [[ "$X_SUDO_MKDIR_APPDIR" == 0 ]] ; then
- # Quietly set ownership and perms.
- sudo -E chown $RUNUSER:$RUNUSER "$APPDIR"
- sudo -E chmod u=wrx,g=rx,o-wrx "$APPDIR"
- echo "Success. We have created the APPDIR where new Starbound installations will reside."
- else
- echo "Failure."
- echo ""
- echo "ERROR: We failed to create the APPDIR with sudo. Either change the APPDIR location, or manually create it."
- echo "Quitting."
- echo ""
- exit 1
- fi
- fi
- fi
- echo ""
- echo "The next step is to install a Starbound master installation."
- echo "This is the real installation from which all other installations will be linked to."
- echo "Note that if an installation already exists in this location, we will try to update it."
- echo ""
- echo "VERIFICATION: Shall we continue?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- fi
- if [[ -d "$APPDIR/$MASTER_INSTALLID" ]] ; then
- echo ""
- echo "NOTICE: A directory already exists at $APPDIR/$MASTER_INSTALLID."
- else
- # Try to create the master installation directory.
- mkdir $APPDIR/$MASTER_INSTALLID ; X_MKDIR_MASTER_INSTALLID=$?
- echo ""
- if [[ "$X_MKDIR_MASTER_INSTALLID" == 0 ]] ; then
- echo "New installation directory created successfully."
- else
- echo "ERROR: New master installation directory creation failed."
- echo "Quitting."
- echo ""
- exit 1
- fi
- fi
- f_update
- echo "Bootstrap process completed!"
- echo "You should now be able to install new Starbound linked servers. Use the \"install\" argument to do so."
- echo ""
- exit 0
- }
- f_start() {
- # Find out if server is already running, and error out if true.
- f_getpid
- if [[ -n "$SERVPID" ]] ; then
- echo ""
- echo "ERROR: Server already running? PID: $SERVPID."
- echo "Quitting."
- echo ""
- exit 1
- fi
- # Make sure we have a binary or link to run. This will prevent a bad installation from trying to start.
- # NOTE: Due to the bug with starbound_server needing to be a real file, this isn't a good test.
- if [[ ! -x "$BINDIR/$APPBIN" ]] ; then
- echo ""
- echo "ERROR: Server executable not found: $BINDIR/$APPBIN"
- echo "Quitting."
- echo ""
- exit 1
- fi
- # Test for conflicting tmux session.
- tmux has-session -t "$SERVNAME" 2> /dev/null
- TMUXCONFLICT=$?
- if [[ ! "$TMUXCONFLICT" -eq 1 ]] ; then
- echo ""
- echo "ERROR: A tmux session named \"$SERVNAME\" already exists, or tmux is broken."
- echo "Quitting."
- echo ""
- exit 1
- fi
- # Check for an update lock.
- f_lockcheck
- #
- # Continue if sane.
- #
- # If this is the first time a server is starting, we will automatically shut it down and warn the user.
- if [[ ! -f "$SBCFGFILE" ]] ; then
- NEWSERVER=1
- echo ""
- echo "WARNING: The default configuration file was not found."
- echo "This is probably a new server being started for the first time."
- echo "A default starbound.config file, universe, and other files will be automatically created."
- echo "The server will automatically be shut down so that you may customize it's config file."
- echo "Note that there may be errors encountered on shutdown; this is normal."
- fi
- #
- # The server overwrites the log file, so rotate it on start if it is there.
- if [[ -f "$APPDIR/$SERVNAME/starbound_server.log" ]] ; then
- mv $APPDIR/$SERVNAME/starbound_server.log $APPDIR/$SERVNAME/starbound_server_$(date +%Y%m%d%H%M%S)-$$.log
- fi
- #
- echo ""
- echo "Starting $SERVNAME..."
- cd "$APPDIR/$SERVNAME"
- # tmux new-session -d -s "$SERVNAME" "$BINDIR/$APPBIN ; rm -f $PIDFILE"
- tmux new-session -d -s "$SERVNAME" "$BINDIR/$APPBIN"
- TMUXEXIT=$?
- #
- # Check the tmux exit code for errors.
- if [[ $TMUXEXIT -ne 0 ]] ; then
- echo "ERROR: tmux failed to run or experienced an error."
- echo "TMUXEXIT was $TMUXEXIT."
- echo "Server may not have started. Check status."
- fi
- # Need to wait for the PID to be obtained, but tmux returns immediately.
- #
- # Since the app itself can not yet write a PID file, we need to get it via tmux, but we must wait for the process to start.
- # WARNING: Do not add any other commands to the tmux new-session command or this won't work correctly. Arguments are okay.
- until [[ -n "$GETPID_TMUX" ]] ; do
- GETPID_TMUX=$(tmux list-panes -t "$SERVNAME" -F '#{pane_pid}')
- sleep 1
- done
- #
- echo "$GETPID_TMUX" >> $PIDFILE || { echo "" ; echo "ERROR: Unable to write PIDFILE: $PIDFILE !" ; f_stop ; exit 1 ; }
- # Note that this waiting here does not currently make sense due to getting the PID from tmux.
- # When the application has a -pidfile option, this will be needed. Keep this.
- #
- echo -n "Waiting for server to start..."
- STARTWAITCOUNT=0
- until [[ -n "$SERVPID" ]] ; do
- f_getpid
- STARTWAITCOUNT=$(( $STARTWAITCOUNT + 1))
- if [[ "$STARTWAITCOUNT" -gt 9 ]] ; then
- echo ""
- echo "ERROR: Done waiting. Startup may have failed. Check status."
- echo ""
- break
- fi
- sleep 1
- echo -n "."
- done
- echo ""
- # Now that the PIDFILE should be readable, get the PID.
- f_getpid
- #
- if [[ -n "$SERVPID" ]] ; then
- echo "Server started at PID $SERVPID."
- else
- echo "ERROR: Unable to get the PID."
- fi
- #
- # Renice the process to make sure it runs as smooth as possible.
- # This requires pam_limits configation via "/etc/security/limits.conf".
- # Test if this is configured properly, and try to use it if so.
- if [[ -n "$SERVPID" ]] && (egrep "$RUNUSER.*nice" /etc/security/limits.conf &> /dev/null) ; then
- echo "Renicing process..."
- bash -c "renice -10 $SERVPID 1> /dev/null"
- RENICEEXIT=$?
- if [[ ! "$RENICEEXIT" = 0 ]] ; then
- echo "Raising the priority of the game server process failed."
- echo "This might be due to pam_limits not being configured corrently."
- echo ""
- fi
- fi
- echo ""
- #
- # If this is a new server, we will want to automatically shut it down, assuming it doesn't shut itself down first, which is likely.
- if [[ "$NEWSERVER" == 1 ]] ; then
- STOPWAITFOR=30
- echo -n "Waiting for new server to stop (max $STOPWAITFOR seconds)..."
- STOPWAITCOUNT=0
- # while [[ -f "$PIDFILE" ]] ; do
- while [[ -n "$(ps --no-headers -p $SERVPID -o pid)" ]] ; do
- STOPWAITCOUNT=$(( $STOPWAITCOUNT + 1))
- if [[ "$STOPWAITCOUNT" -gt "$STOPWAITFOR" ]] ; then
- echo "Forcefully stopping server."
- f_stop
- break
- fi
- sleep 1
- echo -n "."
- done
- if [[ -f "$PIDFILE" ]] ; then
- rm -f "$PIDFILE"
- fi
- echo ""
- echo "New server shutdown completed. After you have configured it, you may start it normally."
- echo ""
- else
- echo "Server startup completed."
- echo ""
- fi
- }
- f_stop() {
- STOPFAIL=0
- f_getpid
- echo ""
- echo "Stopping $SERVNAME ..."
- if [[ -n "$SERVPID" ]] ; then
- kill -SIGINT $SERVPID
- # Now verify that the process is actually gone via the PID.
- STOPWAITFOR=30
- if [[ -n "$(ps --no-headers -p $SERVPID -o pid)" ]] ; then
- echo -n "Waiting for server to stop..."
- STOPWAITCOUNT=0
- while [[ -n "$(ps --no-headers -p $SERVPID -o pid)" ]] ; do
- STOPWAITCOUNT=$(( $STOPWAITCOUNT + 1))
- if [[ "$STOPWAITCOUNT" -gt "$STOPWAITFOR" ]] ; then
- echo ""
- echo "Giving up waiting after $STOPWAITFOR seconds. Stop may have failed."
- echo ""
- echo "Here's the process info:"
- ps uw -p $SERVPID
- echo ""
- echo "Sending kill SIGQUIT to the process..."
- kill -SIGQUIT $SERVPID
- echo "Done."
- STOPFAIL=1
- break
- fi
- sleep 1
- echo -n "."
- done
- echo ""
- fi
- # Delete the PID file if necessary.
- if [[ -f "$PIDFILE" ]] ; then
- rm -f "$PIDFILE"
- fi
- else
- STOPFAIL=1
- echo ""
- echo "PID not found. Is the server not running?"
- echo ""
- fi
- # Kill the tmux session too, if it doesn't exit naturally.
- #
- # FIXME: Do not attempt to redirect stderr here. See tmux bug 3199205. Redirect tmux is broke.
- # verify with; "tmux info > outfile", which will probably hang your terminal.
- # As a result, you will see "session not found:" when stopping servers. Can't fix this.
- #
- #if tmux has-session -t $SERVNAME 2> /dev/null ; then
- #
- # echo "Ignore any \"session not found:\" messages here..."
- if tmux has-session -t "$SERVNAME" 2> /dev/null ; then
- echo -n "Waiting for tmux session to die..."
- TMUXDIEWAITCOUNT=0
- while tmux has-session -t "$SERVNAME" 2> /dev/null ; do
- # while tmux has-session -t "$SERVNAME" ; do
- TMUXDIEWAITCOUNT=$(( $TMUXDIEWAITCOUNT + 1))
- if [[ "$TMUXDIEWAITCOUNT" -gt 3 ]] ; then
- echo ""
- echo "Giving up waiting for tmux session to die."
- echo ""
- echo "Killing the tmux session, which should kill everything..."
- tmux kill-session -t "$SERVNAME"
- echo "Done."
- STOPFAIL=1
- break
- fi
- sleep 1
- echo -n "."
- done
- echo ""
- fi
- if [[ "$STOPFAIL" == 0 ]] ; then
- echo "Game server $SERVNAME was stopped successfully."
- else
- echo "Game server $SERVNAME stop request encountered errors."
- fi
- echo ""
- }
- f_status() {
- echo ""
- f_getpid
- if [[ -n "$SERVPID" ]] ; then
- echo "Showing status for $SERVNAME..."
- echo ""
- echo "tmux session:"
- tmux list-sessions | egrep "^ *${SERVNAME}:"
- echo ""
- echo "Game server PID: $SERVPID"
- echo ""
- PROCINFO_ARGS=$(ps --no-headers -p $SERVPID -o args)
- echo "Process command arguments:"
- echo "$PROCINFO_ARGS"
- echo ""
- echo "Various ps stats:"
- PROCINFO_PCPU=$(ps --no-headers -p $SERVPID -o pcpu)
- echo "CPU usage percent per-core is: $PROCINFO_PCPU%"
- PROCINFO_PPRIO=$(ps --no-headers -p $SERVPID -o pri | sed -e "s/ \{1,\}//g")
- echo "Process priority (normal=19, higher=better): $PROCINFO_PPRIO"
- PROCINFO_PSR=$(ps --no-headers -p $SERVPID -o psr | sed -e "s/ \{1,\}//g")
- echo "Running on processor core: $PROCINFO_PSR"
- PROCINFO_EUSER=$(ps --no-headers -p $SERVPID -o euser)
- echo "Running as effective user: $PROCINFO_EUSER"
- PROCINFO_RSS=$(ps --no-headers -p $SERVPID -o rss)
- echo "RSS/Real memory usage: $PROCINFO_RSS KB"
- PROCINFO_VSZ=$(ps --no-headers -p $SERVPID -o vsz)
- echo "VSZ/Virtual memory usage: $PROCINFO_VSZ KB"
- PROCINFO_LSTART=$(ps --no-headers -p $SERVPID -o lstart)
- echo "Process started at: $PROCINFO_LSTART"
- PROCINFO_ETIME=$(ps --no-headers -p $SERVPID -o etime | sed -e "s/ \{1,\}//g")
- echo "Process started elapsed-time ago: $PROCINFO_ETIME"
- PROCINFO_CPUTIME=$(ps --no-headers -p $SERVPID -o cputime)
- echo "Process CPU in-use time: $PROCINFO_CPUTIME"
- echo ""
- echo "lsof says the following network sockets are in use by PID $SERVPID:"
- lsof -i -n -a -p $SERVPID
- echo ""
- #
- echo "Done."
- else
- echo "ERROR: PID not found. Not running?"
- fi
- echo ""
- }
- f_list() {
- # List all valid server installations and show some basic info about each.
- f_listinstalls
- # $LIST_INSTALLS
- echo ""
- if [[ -z "$LIST_INSTALLS" ]] ; then
- echo "No valid server installations to list."
- else
- echo "Listing all valid server installations..."
- for EACH in $LIST_INSTALLS ; do
- SERVNAME="$EACH"
- # Discover if the server is running.
- f_getpid
- echo "Server: $EACH Status: $SERVSTATUS"
- done
- fi
- echo ""
- }
- f_lockcheck() {
- # Check if a lock has been placed on the master installation to prevent a train wreck, quit if found.
- if [[ -r "$LOCKFILE" ]] ; then
- echo "ERROR: lockfile active. Is an update already in progress?"
- echo "Lockfile: $LOCKFILE"
- echo "Quitting."
- echo ""
- exit 1
- fi
- }
- f_update() {
- # Update with SteamCMD.
- #
- # Make sure SteamCMD is properly configured.
- if [[ -z "$STEAMCMD_DIR" ]] || [[ ! -d "$STEAMCMD_DIR" ]] ; then
- echo ""
- echo "ERROR: The STEAMCMD_DIR is invalid or unset."
- echo "Quitting."
- echo "" ; exit 1
- elif [[ -z "$STEAMCMD_BIN" ]] || [[ ! -x "$STEAMCMD_BIN" ]] ; then
- echo ""
- echo "ERROR: The STEAMCMD_BIN is invalid, unset, or not executable."
- echo "Qutting."
- echo "" ; exit 1
- elif [[ -z "$STEAMCMD_SERVER_APPID" ]] ; then
- echo ""
- echo "ERROR: STEAMCMD_SERVER_APPID is blank or invalid."
- echo "Quitting."
- echo "" ; exit 1
- elif [[ -z "$STEAMCMD_USER" ]] || [[ -z "$STEAMCMD_PASSWD" ]] ; then
- echo ""
- echo "ERROR: The STEAMCMD_USER and or STEAMCMD_PASSWORD is invalid or unset."
- echo "Quitting."
- echo "" ; exit 1
- fi
- #
- # Unlock directory for writing. Normally it should be read-only.
- f_unlockmaster
- # Lockfile check and set.
- f_lockcheck
- echo $$ >> $LOCKFILE || { echo "ERROR: Unable to lock server. Is an update already in progress?" ; echo "" ; exit 1 ; }
- UPDATING=1
- f_listinstalls
- #
- echo ""
- echo "Updating with SteamCMD..."
- echo ""
- declare -i UPDATECOUNTER="0"
- if [[ "$VERIFYUPDATE" == "1" ]] ; then
- echo "Updating with -verify_all/Validate."
- UPDATEARG="+app_update $STEAMCMD_SERVER_APPID validate"
- else
- UPDATEARG="+app_update $STEAMCMD_SERVER_APPID"
- fi
- #
- echo "Any linked server installations will automatically be stopped..."
- if [[ -z "$LIST_INSTALLS" ]] ; then
- echo ""
- echo "No linked server installations found."
- echo ""
- else
- for EACH in $LIST_INSTALLS ; do
- SERVNAME=$EACH
- f_getpid
- # echo "DEBUG: SERVNAME: $SERVNAME EACH: $EACH SERVPID: $SERVPID"
- if [[ -n "$SERVPID" ]] ; then
- echo "Server $EACH needs to be stopped."
- f_stop
- else
- echo "Server $EACH is not running."
- fi
- done
- echo "All servers stopped."
- echo ""
- fi
- #
- # cd to the SteamCMD dir so steamcmd doesn't litter crap tmp dirs wherever $PWD happens to be, which it does often.
- cd $STEAMCMD_DIR
- while true ; do
- $NICECMD $STEAMCMD_BIN +@ShutdownOnFailedCommand 1 +login "$STEAMCMD_USER" "$STEAMCMD_PASSWD" +force_install_dir $APPDIR/$MASTER_INSTALLID/ $UPDATEARG +exit
- UPDATEEXIT=$?
- UPDATECOUNTER=$(( $UPDATECOUNTER + 1)) # Increment the counter
- echo ""
- echo "Updater exit code was $UPDATEEXIT"
- if [[ "$UPDATEEXIT" = 0 ]] ; then
- echo ""
- echo "Update completed."
- break
- else
- echo ""
- echo "Update did not succeed."
- if [[ "$UPDATECOUNTER" -lt "3" ]] ; then
- echo "Try $UPDATECOUNTER failed, will try again..."
- sleep 1
- continue
- fi
- if [[ "$UPDATECOUNTER" -eq "3" ]] ; then
- echo "ERROR: Tried $UPDATECOUNTER times already. Will not try again. Quitting."
- break
- fi
- fi
- done
- #
- # Remove lockfile.
- rm -f $LOCKFILE
- #
- # Lock down the master installation to make it read-only.
- f_lockdownmaster
- #
- # We must relink all linked server installations.
- echo "Relinking all linked server installations..."
- if [[ -z "$LIST_INSTALLS" ]] ; then
- echo ""
- echo "No linked server installations found."
- echo ""
- else
- for EACH in $LIST_INSTALLS ; do
- SERVNAME=$EACH
- f_relink
- done
- echo "All server installations relinked."
- echo ""
- fi
- echo ""
- echo "Update completed."
- echo ""
- }
- f_relink() {
- # Refresh the links on a linked server installation to it's master installation.
- # This is basically the upgrade procedure for a linked installation.
- #
- # Test that a master exists. This is unlikely to be a problem, but it is possible.
- if [[ -z "$MASTER_INSTALLID" ]] ; then
- echo ""
- echo "ERROR: No master installation specified."
- echo "Quitting."
- echo ""
- exit 1
- fi
- # Verify that the master installation directory exists, and err out if there is a problem.
- if [[ ! -d "$APPDIR/$MASTER_INSTALLID" ]] ; then
- echo ""
- echo "ERROR: No Master installation directory found at: $APPDIR/$MASTER_INSTALLID"
- echo "Quitting."
- exit 1
- fi
- echo ""
- echo "Relinking $SERVNAME ..."
- $NICECMD lns -q -r "$APPDIR/$MASTER_INSTALLID/"* "$APPDIR/$SERVNAME" ; X_LNS_RELINK=$?
- if [[ ! "$X_LNS_RELINK" == 0 ]] ; then
- echo ""
- echo "ERROR: The linking process failed."
- echo "Quitting."
- exit 1
- fi
- # Remove old dangling symlinks.
- echo "Looking for old dangling symlinks and removing them..."
- $NICECMD symlinks -d -r "$APPDIR/$SERVNAME"
- # NOTE: We don't delete old empty directories, because we have no way to identify them. Could use "find -type d -empty" though.
- #
- # Delete the SteamCMD temp crap directories from linked installs. These are the 40-character 0-9a-f directories.
- for EACH in $(find $APPDIR/$MASTER_INSTALLID -maxdepth 1 -mindepth 1 -type d) ; do
- EACHN=$(basename $EACH | egrep "^[0-9a-f]{40}$")
- if [[ -n "$EACHN" ]] ; then
- # echo "DEBUG: would delete SteamCMD tempdir: $EACHN"
- # rm -rf "$APPDIR/$SERVNAME/$EACHN"
- # The following commands are much safer than rm -rf.
- $NICECMD find "$APPDIR/$SERVNAME/$EACHN" -type l -lname "*../$MASTER_INSTALLID/*" -exec rm -f '{}' +
- $NICECMD find "$APPDIR/$SERVNAME/$EACHN" -type d -empty -delete
- fi
- done
- # Due to bugs in the starbound_server binary being incompatible with symlinks, we need to make a real copy of it.
- # starbound_server will not work as a symlink because it will try and set it's $PWD to the master install instead of the linked install.
- # Hopefully this bug will be fixed in the future and we won't have to do this.
- $NICECMD rm -f "$APPDIR/$SERVNAME/linux32/$APPBIN"
- $NICECMD rm -f "$APPDIR/$SERVNAME/linux64/$APPBIN"
- $NICECMD cp "$APPDIR/$MASTER_INSTALLID/linux32/$APPBIN" "$APPDIR/$SERVNAME/linux32/$APPBIN"
- $NICECMD cp "$APPDIR/$MASTER_INSTALLID/linux64/$APPBIN" "$APPDIR/$SERVNAME/linux64/$APPBIN"
- #
- echo ""
- echo "Relinking complete."
- echo ""
- }
- f_delink() {
- # Delete the links from a linked installation to it's master installation.
- # NOTE: This should not touch other links which are not related to the master.
- #
- echo ""
- echo "This will delete all symbolic links in the \"$SERVNAME\" installation directory which refer to the Master install."
- echo "This will NOT delete symbolic links which refer to other locations."
- echo ""
- echo "Are you sure you want to do this?"
- echo ""
- echo "VERIFICATION: Delink $SERVNAME ?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- fi
- echo ""
- #
- # Due to the starbound_server needing to be a real file bug, we should go ahead and delete those files here.
- # Hopefully we can stop doing this in the future.
- $NICECMD rm -f "$APPDIR/$SERVNAME/linux64/$APPBIN"
- $NICECMD rm -f "$APPDIR/$SERVNAME/linux32/$APPBIN"
- #
- # NOTE: This is not completely safe. We are depending upon the -lname pattern matching, but it's close enough.
- $NICECMD find "$APPDIR/$SERVNAME" -type l -lname "*../$MASTER_INSTALLID/*" -exec rm -f '{}' +
- echo "Delinking completed with exit code $?."
- echo ""
- # Also offer to delete worthless empty directories that lns created during the linking process.
- echo "Would you also like to delete all empty directories in the $SERVNAME installation directory?"
- echo "This includes ALL directories which are empty of anything other than additionally nested empty directories."
- echo ""
- echo "VERIFICATION: Delete empty directories in \"$SERVNAME\"?"
- read -e -r -p "y/N: " -i "" REPLY
- if [[ ! "$REPLY" == [yY] ]]; then
- echo ""
- echo "Quitting."
- echo ""
- exit 0
- else
- find "$APPDIR/$SERVNAME" -type d -empty -delete
- echo ""
- echo "Done deleting empty directories."
- echo ""
- fi
- }
- f_install() {
- # Create a new linked server installation. For the master install, see f_update.
- echo ""
- echo "This process will install a new Starbound server installation."
- echo ""
- echo "Choose a unique name for this installation."
- echo "Valid characters are a-z, A-Z, and 0-9. No other characters allowed."
- if [[ -n "$INSTALL_PREFIX" ]] ; then
- echo "NOTE: The installation prefix \"$INSTALL_PREFIX\" will automatically be prepended to the installation name. Do not include it here."
- fi
- echo ""
- while read -e -r -p "Name: " -i "$IN_SERVNAME" SERVNAME_NEW ; do
- # Validate the input.
- if [[ -z "$SERVNAME_NEW" ]] || (echo "$SERVNAME_NEW" | egrep "[[:cntrl:]]|[[:punct:]]|[[:space:]]" &> /dev/null ) ; then
- echo ""
- echo "Invalid input detected. Try again."
- else
- # Prepend the installation prefix.
- SERVNAME_NEW=${INSTALL_PREFIX}${SERVNAME_NEW}
- echo ""
- echo "Please confirm: New installation name will be \"${SERVNAME_NEW}\" ?"
- # echo -n "y/N:"
- read -e -r -p "y/N: " -i "" SERVNAME_NEW_CONFIRM
- if [[ "$SERVNAME_NEW_CONFIRM" == [yY] ]]; then
- break
- else
- echo ""
- echo "Okay then, we will try again. What name do you want?"
- fi
- fi
- done
- SERVNAME=$SERVNAME_NEW
- # Verify that such an installation does not already exist.
- if [[ -d "$APPDIR/$SERVNAME" ]] ; then
- echo ""
- echo "ERROR: A directory already exists at \"$APPDIR/$SERVNAME\"."
- echo "Quitting."
- echo ""
- exit 1
- fi
- mkdir $APPDIR/$SERVNAME_NEW ; X_MKDIR_INSTALLID_NEW=$?
- echo ""
- if [[ "$X_MKDIR_INSTALLID_NEW" == 0 ]] ; then
- echo "New installation directory created successfully."
- else
- echo "ERROR: New installation directory creation failed."
- echo "Quitting."
- exit 1
- fi
- # Now that we have our installation directory, link it up.
- f_relink
- echo "New server installation created. Be sure to configure it before attempting to start."
- echo ""
- }
- f_lockdownmaster() {
- # Lock down the master installation from writing. This will prevent accidents.
- echo -n "Locking down the master installation... "
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type f -exec chmod ugo-x '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID/linux[63][42] -type f -exec chmod ugo+x '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type f -exec chmod ugo+r '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type d -exec chmod ugo+rx '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type f -exec chmod ugo-w '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type d -exec chmod ugo-w '{}' +
- echo "Done."
- }
- f_unlockmaster() {
- # Unlock the master installation for writing. The only time this should be needed is for manual work or updating.
- echo -n "Unlocking the master installation ... "
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type d -exec chmod ug+w '{}' +
- $NICECMD find $APPDIR/$MASTER_INSTALLID -type f -exec chmod ug+w '{}' +
- echo "Done."
- }
- f_listinstalls() {
- # Get a list of all linked installations. This excludes the master installation. Store in LIST_INSTALLS.
- # We will also omit any directory with a "." in it's name.
- for EACH in $(find $APPDIR -mindepth 1 -maxdepth 1 -type d | egrep -v "$MASTER_INSTALLID|.*\..*") ; do
- EACHN=$(basename $EACH)
- if [[ -z "$LIST_INSTALLS" ]] ; then
- LIST_INSTALLS="$EACHN"
- else
- LIST_INSTALLS="$LIST_INSTALLS $EACHN"
- fi
- done
- }
- f_console() {
- # Attach to the tmux session for a given steam server.
- # FIXME: Could use some test for the pidfile, warning if not found, etc.
- echo ""
- echo "Attaching to tmux session $SERVNAME..."
- echo ""
- tmux attach-session -t "$SERVNAME"
- echo "Session detached or closed."
- echo ""
- exit 0
- }
- f_mailnotify() {
- # Mail notifications.
- # Only send mail if MAILNOTIFY is set corretly.
- if (echo "$MAILNOTIFY" | egrep -i "yes|true|1" &> /dev/null) ; then
- $MAILER -s "STARBINDER: $SERVNAME $IN_ACTION" $MAILTO <<-ENDMESSAGE
- Date: $(date)
- Server: $SERVNAME
- Action: $IN_ACTION
- ENDMESSAGE
- fi
- }
- f_commandhelper() {
- # Print this if input is nonsense.
- echo ""
- echo "I was expecting something like:"
- echo " $(basename $0) ($AVAIL_ACTIONS1)"
- echo "OR"
- echo " $(basename $0) ($AVAIL_ACTIONS2) myserver"
- echo ""
- echo "For example:"
- echo " $(basename $0) start myserver"
- echo ""
- echo "Quitting."
- echo ""
- exit 1
- }
- #--
- # Verify sanity before we start doing anything.
- trap f_cleanuptrap SIGHUP SIGINT SIGQUIT SIGABRT
- # Validate arguments.
- if [[ "$#" -eq 1 ]] ; then
- # Validate single arguments.
- if [[ "$IN_ACTION" != bootstrap ]] ; then
- # For anything other than intial bootstrapping, the APPDIR must exist.
- if [[ ! -d "$APPDIR" ]] ; then
- echo ""
- echo "ERROR: APPDIR \"$APPDIR\" not found!"
- echo ""
- echo "If you want to perform setup for the first time, use the \"bootstrap\" argument."
- echo "Be sure you have read the ${MYNAME}_README.txt file first!"
- echo ""
- f_commandhelper
- fi
- fi
- if ! (echo "$IN_ACTION" | egrep "$AVAIL_ACTIONS1" &> /dev/null) ; then
- echo ""
- echo "Action argument \"$IN_ACTION\" is not valid."
- f_commandhelper
- fi
- elif [[ "$#" -eq 2 ]] ; then
- # Validate dual arguments.
- if ! (echo "$IN_ACTION" | egrep "$AVAIL_ACTIONS2" &> /dev/null) ; then
- echo ""
- echo "Action argument \"$IN_ACTION\" is not valid."
- f_commandhelper
- fi
- # Validate $SERVNAME, unless we are installing as new.
- if [[ "$IN_ACTION" != install ]] ; then
- if [[ ! -d "$APPDIR/$SERVNAME" ]] ; then
- echo ""
- echo "Installation argument \"$SERVNAME\" not found."
- f_commandhelper
- fi
- fi
- elif [[ "$#" -gt 2 ]] ; then
- # More than two arguments is an error.
- echo ""
- echo "Too many arguments."
- f_commandhelper
- fi
- # If we are not updating, immediately unset STEAMCMD_USER and STEAMCMD_PASSWD for security reasons.
- if ( echo "$IN_ACTION" | egrep -v "^update$|^update-validate$" &> /dev/null ) ;then
- # echo "DEBUG: Unsetting auth info."
- unset STEAMCMD_USER STEAMCMD_PASSWD
- fi
- case "$IN_ACTION" in
- 'start')
- f_mailnotify
- f_start
- ;;
- 'stop')
- f_mailnotify
- f_stop
- ;;
- 'restart')
- f_mailnotify
- f_stop
- sleep 1
- f_start
- ;;
- 'list')
- f_list
- ;;
- 'status')
- f_status
- ;;
- 'update')
- f_mailnotify
- f_update
- ;;
- 'update-validate')
- VERIFYUPDATE=1
- f_mailnotify
- f_update
- ;;
- 'console')
- f_console
- ;;
- 'bootstrap')
- f_bootstrap
- ;;
- 'install')
- f_install
- ;;
- 'relink')
- f_relink
- ;;
- 'delink')
- f_delink
- ;;
- 'lockdown-master')
- f_lockdownmaster
- ;;
- 'unlock-master')
- f_unlockmaster
- ;;
- *)
- echo ""
- echo "Missing arguments."
- f_commandhelper
- esac
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement