Skip to content

Instantly share code, notes, and snippets.

@mhoofman
Created August 4, 2011 01:08
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mhoofman/1124293 to your computer and use it in GitHub Desktop.
Save mhoofman/1124293 to your computer and use it in GitHub Desktop.
Minecraft Server Shell Script
#!/bin/bash
# original author : Relliktsohg
# Huge thanks to Maine for his incremental backup
# Thanks to endofzero for his improved update routine
#
# Installation:
# - Copy script into you minecraft server folder.
# - Allow the script to be executed (chmod +x minecraft.sh)
# - Check the rights of the script user. Every folder specified in config has to be available.
# - Edit the script to configure it (see configure section)
# - More details: http://www.minecraftforum.net/topic/37290-another-shell-script/
#
# Usage:
# ./minecraft.sh
# - Without arguments, the script will resume the server screen. (If you want to close
# the screen without shutting down the server, use CTRL+A then press D to detach screen)
#
# ./minecraft.sh status
# - Tells you if the server is running or not.
#
# ./minecraft.sh start [force]
# - Starts the server. If you know your server is not running, but the script believes it is, use the
# force options.
#
# ./minecraft.sh stop [force]
# - Explains itself.
#
# ./minecraft.sh restart [warn]
# - If the warn option is specified, it will display a warning 30s & 10s before the restart happens.
#
# ./minecraft.sh logs [clean]
# - Parses logs into several files, grouped into a folder named with the date of the logging.
# If the clean option is specified, it will move the older folders into the backup folder.
# Again, this command should be issues before a server restart.
#
# ./minecraft.sh backup [clean]
# - Displays a message to the players if the server is online, stops the writing of chunks, create a
# dated archive and backs up the world folder. If the clean option is specified, it will delete the
# older archives.
#
# ./minecraft.sh cartography
# - Displays a message to the players if the server is online, stops the writing of chunks, initiates
# c10t's cartography script. I strongly recommend the MAPS_PATH to be a internet public folder.
#
# ./minecraft.sh update
# - Stops the server if it is online, backs up the old binairies, downloads the last binaries from
# mincraft.net and restarts the server.
# Configuration
MC_PATH=/home/minecraft
SERVERMOD=0
RUNECRAFT=0
SCREEN_NAME="minecraft"
MEMALOC=512
DISPLAY_ON_LAUNCH=1
WORLD_NAME="world"
BKUP_PATH=$MC_PATH/backup
BKUP_DAYS_INCR=2
BKUP_DAYS_FULL=5
BACKUP_FULL_LINK=${BKUP_PATH}/${WORLD_NAME}_full.tgz
BACKUP_INCR_LINK=${BKUP_PATH}/${WORLD_NAME}_incr.tgz
CARTO_PATH=$MC_PATH/carto
MAPS_PATH=/var/www/minecraftMaps
LOG_TDIR=/var/www/minecraftLogs
LOGS_DAYS=7
# End of configuration
if [ $SERVERMOD -eq 1 ]
then
if [ -e $MC_PATH/logs/*.log.lck ]
then
ONLINE=1
else
ONLINE=0
fi
else
if [ -e $MC_PATH/server.log.lck ]
then
# ps -e | grep java | wc -l
ONLINE=1
else
ONLINE=0
fi
fi
display() {
screen -R $SCREEN_NAME
}
server_launch() {
echo "Launching minecraft server..."
if [ $SERVERMOD -eq 1 ]
then
cd $MC_PATH; screen -m -d -S $SCREEN_NAME java -Xmx${MEMALOC}M -Xms${MEMALOC}M -Djava.net.preferIPv4Stack=true -jar Minecraft_Mod.jar nogui; sleep 1
else
cd $MC_PATH; screen -m -d -S $SCREEN_NAME java -Xmx${MEMALOC}M -Xms${MEMALOC}M -Djava.net.preferIPv4Stack=true -jar minecraft_server.jar nogui; sleep 1
fi
}
server_stop() {
echo "Stopping minecraft server..."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "stop.\r"`"; sleep 5
}
if [ $# -gt 0 ]
then
case $1 in
#################################################################
"status")
if [ $ONLINE -eq 1 ]
then
echo "Minecraft server seems ONLINE."
else
echo "Minecraft server seems OFFLINE."
fi;;
#################################################################
"start")
if [ $ONLINE -eq 1 ]
then
echo "Server seems to be already running !"
case $2 in
"force")
kill `ps -e | grep java | cut -d " " -f 1`
rm -fr $MC_PATH/*.log.lck 2> /dev/null/;;
esac
else
server_launch
if [ $DISPLAY_ON_LAUNCH -eq 1 ]
then
display
fi
fi;;
#################################################################
"stop")
if [ $ONLINE -eq 1 ]
then
server_stop
else
case $2 in
"force")
kill `ps -e | grep java | cut -d " " -f 1`
rm -fr $MC_PATH/*.log.lck 2> /dev/null/;;
*)
echo "Server seems to be offline...";;
esac
fi;;
#################################################################
"restart")
if [ $ONLINE -eq 1 ]
then
case $2 in
"warn")
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Server will restart in 30s !\r"`"; sleep 20
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Server will restart in 10s !\r"`"; sleep 10;;
esac
server_stop
fi
server_launch
if [ $DISPLAY_ON_LAUNCH -eq 1 ]
then
display
fi;;
#################################################################
"logs")
mkdir -p $LOG_TDIR
cd $LOG_TDIR
case $2 in
"clean")
DATE=$(date +%d-%m --date "$LOGS_DAYS day ago")
if [ -e logs-$DATE ]
then
mkdir -p $BKUP_PATH/logs
mv logs-$DATE $BKUP_PATH/logs/
fi
;;
esac
DATE=$(date +%d-%m)
LOG_NEWDIR=logs-$DATE
if [ -e $LOG_TDIR/$LOG_NEWDIR ]
then
rm $LOG_TDIR/$LOG_NEWDIR/*
else
mkdir $LOG_TDIR/$LOG_NEWDIR
fi
DATE=$(date +%d-%m-%Hh%M)
LOG_TFILE=logs-$DATE.log
if [ $SERVERMOD -eq 1 ]
then
if [ $ONLINE -eq 1 ]
then
LOG_LCK=$(basename $MC_PATH/logs/*.log.lck .log.lck)
echo "Found a log lock : $LOG_LCK"
else
LOG_LCK=""
fi
cd $MC_PATH/logs/
for i in *
do
if [ $i != $LOG_LCK.log.lck ] # skip du fichier lck
then
cat $i >> $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE
if [ $i != $LOG_LCK.log ] # On ne supprime pas le fichier log courant, si le serv est en route
then
rm $i
fi
fi
done
else
cd $MC_PATH
cat server.log >> $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE
fi
if [ -e $LOG_TDIR/ip-list.log ]
then
cat $LOG_TDIR/ip-list.log | sort | uniq > $LOG_TDIR/templist.log
fi
cat $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE | egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+.+logged in' | sed -e 's/.*\[INFO\]\s//g' -e 's/\[\//\t/g' -e 's/:.*//g' >> $LOG_TDIR/templist.log
cat $LOG_TDIR/templist.log | sort | uniq -w 4 > $LOG_TDIR/ip-list.log
rm $LOG_TDIR/templist.log
cat $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE | egrep 'logged in|lost connection' | sed -e 's/.*\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\).\[INFO\].\([a-zA-Z0-9_]\{1,\}\).\{1,\}logged in/\1\t\2 : connected/g' -e 's/.*\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\).\[INFO\].\([a-zA-Z0-9_]\{1,\}\).lost connection.*/\1\t\2 : disconnected/g' >> $LOG_TDIR/$LOG_NEWDIR/connexions-$DATE.log
cat $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE | egrep '<[a-zA-Z0-9_]+>|\[CONSOLE\]' | sed -e 's/.*\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\).\[INFO\]./\1 /g' >> $LOG_TDIR/$LOG_NEWDIR/chat-$DATE.log
cat $LOG_TDIR/$LOG_NEWDIR/$LOG_TFILE | egrep 'Internal exception|error' | sed -e 's/.*\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\).\[INFO\]./\1\t/g' >> $LOG_TDIR/$LOG_NEWDIR/errors-$DATE.log
;;
#################################################################
"backup")
mkdir -p $BKUP_PATH
if [ -e $MC_PATH/$WORLD_NAME ]
then
if [ $ONLINE -eq 1 ]
then
echo "Server running, warning players : backup in 10s."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Backing up the map in 10s\r"`"; sleep 10
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Now backing up the map...\r"`"
echo "Issuing save-all command, wait 5s..."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-all\r"`"; sleep 5
echo "Issuing save-off command..."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-off\r"`"; sleep 1
fi
cd $BKUP_PATH
DATE=$(date +%Y-%m-%d-%Hh%M)
FILENAME=$WORLD_NAME-$DATE
BACKUP_FILES=$BKUP_PATH/list.$DATE
if test `date +%H` -eq 0 -o ! -f $BACKUP_FULL_LINK
then
# Make full backup, and remove old incrementals
FILENAME=$FILENAME-full.tgz
# Remove incrementals older than $BKUP_DAYS_INCR
# Remove full archives older than $BKUP_DAYS_FULL
find ./$WORLD_NAME-*-incr.tgz -type f -mtime +$BKUP_DAYS_INCR -print > purgelist
find ./$WORLD_NAME-*-full.tgz -type f -mtime +$BKUP_DAYS_FULL -print >> purgelist
rm -f `cat purgelist`
rm -f purgelist
# Now make our full backup
pushd $MC_PATH
find $WORLD_NAME -type f -print > $BACKUP_FILES
tar -zcvf $BKUP_PATH/$FILENAME --files-from=$BACKUP_FILES
popd
rm -f $BACKUP_FULL_LINK $BACKUP_INCR_LINK
ln -s $FILENAME $BACKUP_FULL_LINK
else
# Make incremental backup
FILENAME=$FILENAME-incr.tgz
pushd $MC_PATH
find $WORLD_NAME -newer $BACKUP_FULL_LINK -type f -print > $BACKUP_FILES
tar -zcvf $BKUP_PATH/$FILENAME --files-from=$BACKUP_FILES
popd
rm -f $BACKUP_INCR_LINK
ln -s $FILENAME $BACKUP_INCR_LINK
fi
rm -f $BACKUP_FILES
if [ $ONLINE -eq 1 ]
then
echo "Issuing save-on command..."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-on\r"`"; sleep 1
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Backup is done, have fun !\r"`"
fi
echo "Backup process is over."
else
echo "The world \"$WORLD_NAME\" does not exist.";
fi;;
#################################################################
"cartography")
if [ -e $CARTO_PATH ]
then
if [ -e $MC_PATH/$WORLD_NAME ]
then
if [ $ONLINE -eq 1 ]
then
echo "Issuing save-all command, wait 5s...";
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-all\r"`"; sleep 5
echo "Issuing save-off command...";
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-off\r"`"; sleep 1
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Map cartography has begun.\r"`"
fi
mkdir -p $MAPS_PATH
DATE=$(date +%d-%m-%Y-%Hh%M)
FILENAME=$WORLD_NAME-map-$DATE
cd $CARTO_PATH
echo "Cartography in progress..."
./c10t -w $MC_PATH/$WORLD_NAME/ -o $FILENAME.png -q -s
mv *.png $MAPS_PATH
cd $MC_PATH
echo "Cartography is done."
if [ $ONLINE -eq 1 ]
then
echo "Issuing save-on command..."
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "save-on\r"`"; sleep 1
screen -S $SCREEN_NAME -p 0 -X stuff "`printf "say Map cartography is done.\r"`"
fi
else
echo "The world \"$WORLD_NAME\" does not exist.";
fi
else
echo "The path to cartographier seems to be wrong."
fi;;
#################################################################
"update")
if [ $ONLINE -eq 1 ]
then
server_stop
fi
mkdir -p $BKUP_PATH
echo "Backing up current binaries..."
DATE=$(date +%d-%m-%Y)
cd $MC_PATH
if [ $SERVERMOD -eq 1 ]
then
tar -czf minecraft_server-$DATE.tar.gz minecraft_server.jar Minecraft_Mod.jar
rm Minecraft_Mod.jar
else
tar -czf minecraft_server-$DATE.tar.gz minecraft_server.jar
fi
mv minecraft_server-$DATE.tar.gz $BKUP_PATH
echo "Downloading new binaries..."
wget -N http://www.minecraft.net/download/minecraft_server.jar
if [ $SERVERMOD -eq 1 ]
then
"Downloading hey0's serverMod..."
mkdir -p ModTmp; cd ModTmp/
wget -O Minecraft_Mod.zip http://hey0.net/get.php?dl=serverbeta
unzip Minecraft_Mod.zip
cp bin/Minecraft_Mod.jar $MC_PATH/Minecraft_Mod.jar
cd $MC_PATH; rm -rf ModTmp
fi
if [ $RUNECRAFT -eq 1 ]
then
echo "Downloading Runecraft..."
mkdir -p ModTmp; cd ModTmp/
wget http://llama.cerberusstudios.net/runecraft_latest.zip
unzip runecraft_latest.zip
jar uvf $MC_PATH/minecraft_server.jar in.class o.class mm.class rm.class rn.class rt.class
cd $MC_PATH; rm -rf ModTmp
fi
server_launch
if [ $DISPLAY_ON_LAUNCH -eq 1 ]
then
display
fi;;
#################################################################
*)
echo "Usage : minecraft <status | start [force] | stop | restart [warn] | logs [clean] | backup [clean] | cartography | update>";
esac
else
if [ $ONLINE -eq 1 ]
then
display
else
echo "Minecraft server seems to be offline..."
fi
fi
exit 0
@Jekyllz
Copy link

Jekyllz commented Mar 5, 2022

Nice script, well written with plenty of features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment