Jump to content

  • Curse Sites
Become a Premium Member! Help
Latest News Article

[Multi World] Linux Minecraft server control script

linux multiple shell script minecraft start stop backup update bukkit

  • Please log in to reply
339 replies to this topic

#1

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 09 January 2011 - 01:29 AM

I've been using various versions of the following script on my Debian and Ubuntu servers for the past couple of years, and I am rather satisfied with the way that it works.  I thought I would share it with the community in hopes that it would be found useful by others.


Features
  • Run multiple Minecraft worlds.
  • Start, stop, and restart single or multiple worlds.
  • Create, delete, disable, and enable worlds.
  • Supports CraftBukkit in addition to the standard Mojang server distribution.
  • Users automatically notified of important server events.
  • Uses the Minecraft Query protocol to keep track of current server conditions.
  • LSB-compatible init script, allows for seamless integration with your server's startup and shutdown sequences.
  • Map worlds using the Minecraft Overviewer mapping software.
  • Backup worlds, and remove backups older than X days.
  • Update the server and client software.
  • Send commands to a world server from the command line.
See Usage for a description on how to use these features.


Download
The script can be downloaded from Github:

wget https://raw.github.com/sandain/MinecraftServerControlScript/master/minecraft_server


Installation
To get your server to run the script on startup, and cleanly down the server on shutdown, you need to copy the script to /etc/init.d, set execute permissions on the file, and instruct the system to use the script on startup and shutdown.  The following commands will work in Debian and Ubuntu like environments, ymmv in others.
sudo cp minecraft_server /etc/init.d/minecraft_server
sudo chmod 755 /etc/init.d/minecraft_server
sudo update-rc.d minecraft_server defaults

For security reasons, the script uses a user account named minecraft rather than root.  As such, you need to create the user before using this script:
sudo adduser minecraft

If the Minecraft server software is not located when the server start command is issued, the software will be downloaded to the proper location: /home/minecraft/minecraft_server/minecraft_server.jar


Requirements
I've made an attempt to utilize only features that are normally installed in most Linux and UNIX environments in this script, but there are a few requirements that this script has that may not already be in place:
  • Java JRE - The Minecraft server software requires this.
  • Perl - Most, if not all, Unix and Linux like systems have this preinstalled.
  • Python - Required by the Minecraft Overviewer mapping software.
  • GNU Wget - Allows the script to download software updates via the internet.
  • rdiff-backup - Allows the script to efficiently run backups.
  • Socat - Allows the script to communicate with the query server.
  • Iptables - Although not explicitly required, a good firewall should be installed.
If you are running Debian or Ubuntu, you can make sure that these are installed by running:
sudo apt-get install default-jre perl python wget rdiff-backup socat iptables


Mapping Software
The script now uses the Minecraft Overviewer mapping software to generate maps of your worlds.  You can download premade binaries for supported systems (Debian/Ubuntu, CentOS/RHEL/Fedora), or build your own binary from source if needed.


Firewall / NAT
If you have a firewall installed on your computer, or a router using NAT installed in your network, you will need to route some ports to your server.  Instructions on how to accomplish this are beyond the scope of this post, but here are some things you will need to know:
  • The default port for the Minecraft server is: 25565.
  • If you wish to run multiple world servers using this script, you will want to open a range of ports (for example 25565 - 25575).
See the iptables.rules file for a very basic set of rules that you can use with the Iptables filewall.


Usage

All commands below assume that you are running them as either the minecraft user or as root (through sudo).

Note: If the script is run as the root user, all important server processes will be started using the minecraft user for security purposes.

su minecraft
/etc/init.d/minecraft_server <option>
or
sudo /etc/init.d/minecraft_server <option>

Options
  • start <world>
    Start the Minecraft world server.  Starts all world servers by default.
  • stop <world>
    Stop the Minecraft world server.  Stops all world servers by default.
  • force-stop <world>
    Forcibly stop the Minecraft world server.  Forcibly stops all world servers by default.
  • restart <world>
    Restart the Minecraft world server.  Restarts all world servers by default.
  • force-restart <world>
    Forcibly restart the Minecraft world server.  Forcibly restarts all world servers by default.
  • create <world> <port> <ip>
    Create a Minecraft world server.  The world name and port must be provided, the IP address is usually blank.
  • delete <world>
    Delete a Minecraft world server.
  • disable <world>
    Temporarily disable a world server.
  • enable <world>
    Enable a disabled world server.
  • list <option>
    Display a list of worlds.
    Options:
    • enabled
      Display a list of enabled worlds, default.
    • disabled
      Display a list of disabled worlds.
    • running
      Display a list of running worlds.
    • stopped
      Display a list of stopped worlds.
  • status <world>
    Display the status of the Minecraft world server.  Displays the status of all world servers by default.
  • send <world> <command>
    Send a command to a Minecraft world server.
  • logrotate <world>
    Rotate the server.log file.  Rotate the server.log file for all worlds by default.
  • backup <world>
    Backup the Minecraft world.  Backup all worlds by default.
  • watch <world>
    Watch the log file for the Minecraft world server.
  • map <world>
    Run the Mincraft Overviewer mapping software on the Minecraft world.  Maps all worlds by default.
  • update
    Update the client and server software.
To start all of the world servers, issue the command:
/etc/init.d/minecraft_server start

To create a world named alpha, issue the command:
/etc/init.d/minecraft_server create alpha 25565

To start just the world named alpha, issue the command:
/etc/init.d/minecraft_server start alpha

To send a command to a world server, issue the command:
/etc/init.d/minecraft_server send <world> <command>

ie.
/etc/inid.d/minecraft_server send alpha say Hello world!


Import Existing Worlds

You just need to create a new directory in the worlds folder for the world you wish to import. Suppose the world you wish to import is called alpha, you would create a new folder in /home/minecraft/worlds, then copy the data files over to that directory.

If the directory containing the world alpha you wish to import looks like this:

$ ls
alpha
banned-ips.txt
banned-players.txt
crash-reports
logs
ops.txt
server.properties
white-list.txt

You can just copy your world into the worlds directory:
mkdir /home/minecraft/worlds/alpha
cd /path/to/world/to/import/alpha
cp -R * /home/minecraft/worlds/alpha

Make sure you check server-port and query.port in server.properties to make sure it does not overlap with other servers created by the MSCS script. If you do not have a query.port set, you will not be able to check the status of the world with the script.


Message of the Day (MOTD)
To whisper the message of the day to users as they log into the world, add a file called motd.txt to the /home/minecraft directory.
nano /home/minecraft/motd.txt

Colors
To add colors to your Help or MOTD files, insert the following color codes into your text:
  • §0 - black
  • §1 - blue
  • §2 - deep green
  • §3 - aqua
  • §4 - deep red
  • §5 - purple
  • §6 - gold
  • §7 - gray
  • §8 - dark gray
  • §9 - light blue
  • §a - green
  • §b - teal
  • §c - red
  • §d - magenta
  • §e - yellow
  • §f - white
Example motd.txt:
§fWelcome to Minecraft!
§fToday's theme is §4red§f.
§fLook out for those §2creepers§f!


Server Customization

The server settings for each world can be customized by adding certain
key/value pairs to the world's server.properties file.

The following keys are available:
  • mscs-client-version
    Assign the version of the client software.
  • mscs-client-jar
    Assign the .jar file for the client software.
  • mscs-client-url
    Assign the download URL for the client software.
  • mscs-client-location
    Assign the location of the client .jar file.
  • mscs-server-version
    Assign the version of the server software.
  • mscs-server-jar
    Assign the .jar file for the server software.
  • mscs-server-url
    Assign the download URL for the server software.
  • mscs-server-args
    Assign the arguments to the server.
  • mscs-initial-memory
    Assign the initial amount of memory for the server.
  • mscs-maximum-memory
    Assign the maximum amount of memory for the server.
  • mscs-server-location
    Assign the location of the server .jar file.
  • mscs-server-command
    Assign the command to run for the server.

The following variables may be used in some of the values of the above keys:
  • $JAVA
    The Java virtual machine.
  • $CURRENT_VERSION
    The current Mojang Minecraft release version.
  • $CLIENT_VERSION
    The version of the client software.
  • $SERVER_VERSION
    The version of the server software.
  • $SERVER_JAR
    The .jar file to run for the server.
  • $SERVER_ARGS
    The arguments to the server.
  • $INITIAL_MEMORY
    The initial amount of memory for the server.
  • $MAXIMUM_MEMORY
    The maximum amount of memory for the server.
  • $SERVER_LOCATION
    The location of the server .jar file.

The following example key/value pairs are equivalent to the default values:
mscs-client-version=$CURRENT_VERSION
mscs-client-jar=$CLIENT_VERSION.jar
mscs-client-url=https://s3.amazonaws.com/Minecraft.Download/versions/$CLIENT_VERSION/$CLIENT_VERSION.jar
mscs-client-location=/home/minecraft/.minecraft/versions/$CLIENT_VERSION
mscs-server-version=$CURRENT_VERSION
mscs-server-jar=minecraft_server.$SERVER_VERSION.jar
mscs-server-url=https://s3.amazonaws.com/Minecraft.Download/versions/$SERVER_VERSION/minecraft_server.$SERVER_VERSION.jar
mscs-server-args=nogui
mscs-initial-memory=128M
mscs-maximum-memory=2048M
mscs-server-location=/home/minecraft/minecraft_server
mscs-server-command=$JAVA -Xms$INITIAL_MEMORY -Xmx$MAXIMUM_MEMORY -jar $SERVER_LOCATION/$SERVER_JAR $SERVER_ARGS
The following example key/value pairs will run a Minecraft version 1.6.4 server:
mscs-client-version=1.6.4
mscs-server-version=1.6.4
The following example key/value pairs will use the latest CraftBukkit recommended build:
mscs-server-jar=craftbukkit.jar
mscs-server-url=http://dl.bukkit.org/latest-rb/craftbukkit.jar
mscs-server-args=
mscs-initial-memory=128M
mscs-maximum-memory=2048M


Lib Notify
On systems that support lib notify, you can modify the script to print a message on your desktop of important server events.

First, you need to know the name of the display you want to route the messages to.  This is usually ":0.0", but it may be something different on your system.
glxinfo | grep "name of display"

If your username is different than the user used for the Minecraft server, replace $USER_NAME in LIBNOTIFY_USER_NAME=$USER_NAME with the correct username.

Modify the following lines of code in the script.
## Lib-notify configuration

# To use lib-notify to print a message on your desktop of important server events, change the following to a 1.
USE_LIBNOTIFY=0

# The username and display that notifications will be routed to.
LIBNOTIFY_USER_NAME=$USER_NAME
LIBNOTIFY_DISPLAY=":0.0"


License
Copyright (c) 2011-2014, Jason M. Wood <[email protected]>

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.


Issues
I have only tested this code in a Debian/Ubuntu environment, but there is no reason that it shouldn't work in any appropriately configured UNIX-like environment, including Apple Mac OSX and the other BSD variants, with only minor modifications.  If you experience errors running this script, please post a copy of the error message and a note detailing the operating environment where the error occurs, and I'll try to work out a solution with you.

Enjoy,

Sandain

Register or log in to remove.

#2

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 13 January 2011 - 12:28 AM

I had to register to say thank you for this excellent script.  I was really excited to find it and have been really enjoying using it.

I have a few quick bits of feedback:

* The date_time variable is slightly wrong.  You've used a capital M for minutes in the date string where you should have a small m for month:

line 188:
- DATE_TIME=$(date +%Y-%M-%d-%H:%M:%S)
+ DATE_TIME=$(date +%Y-%m-%d-%H:%M:%S)
Obviously this isn't critical, but is an easy enough fix to be worthwhile.

* The map function fails silently if the required folders don't already exist.  The "maps" folder is made, but if the underlying "WORLDNAME" folders aren't already there, nothing happens.  I manually made the folders and it's fine now; not sure if this is a quirk on my system or an oversight....

* Would you consider adding a function to the backup routine that purges existing backups that are x days old, or only keeping the most recent x number of backups?  I know this is a really non-trivial change, but would be super convenient....

Also, I wrote a quick and dirty command that uses Ubuntu's native notification system to alert me when players log in or send messages (my server is just for myself and two RL friends, so it's not overwhelming to plug into all this activity and there's utility in knowing when my friends sign in).  I'd love to be able to incorporate this into your service so it starts (and stops) with the server itself, but I've had no luck at all.  I apologize that this is more of a vanity request, but it's possible someone else might find it useful (and I banged my head against getting it work for entirely too long):

tail -n0 -f $WORLDS_LOCATION/$1/server.log | grep --line-buffered -v "" | while read line; do notify-send "Minecraft Server:" "${line:20}" -i $LOCATION/osd-icon.png; done
You will instantly see how this works because you are a genius, but for anyone (like me) following along at home, I'll explain what happens there:

"tail -f" follows the server log, which gets you easy access to login/logout and all chat console messages
"grep -v """ will filter out lines from the log that you type into the chat console (becomes overwhelming without this and the messages are not important to see in the notification area)
"while read line" simple loop to send the notification for each line as it comes in
"notify-send" is the Ubuntu notification bubbles (see here for details)
"${line:20}" this just trims the line in question of the first 20 characters to remove the timestamps when popping up the notification.  Fancier sed regexps could net you more or less information, but this works well for me.
"osd-icon.png" is whatever you want the icon to be inside the bubble.  I used the 32px one from here and it's an excellent fit.

Curiously, this works when pasted into the terminal directly (with hardcoded values for the paths, natch), but fails when called as a bash script.  Apparently I am full of fail.

I'm sure this isn't useful widely enough to warrant inclusion in your script, but if you could provide some guidance on how to hack it in, I'd be super grateful.... I've tried a number of ways, but each of them broke the service.

Anyway, thanks so much for posting this in the first place.  I'm really surprised there aren't more comments here; you did a great job.

#3

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 13 January 2011 - 02:08 AM

rad_ said:

I had to register to say thank you for this excellent script.  I was really excited to find it and have been really enjoying using it.

I have a few quick bits of feedback:
Nice, I'm really glad that someone else is finding this script useful.  And thank you for the feedback, I really appreciate it.

rad_ said:

* The date_time variable is slightly wrong.  You've used a capital M for minutes in the date string where you should have a small m for month:

line 188:
- DATE_TIME=$(date +%Y-%M-%d-%H:%M:%S)
+ DATE_TIME=$(date +%Y-%m-%d-%H:%M:%S)
Obviously this isn't critical, but is an easy enough fix to be worthwhile.
I noticed this myself yesterday and quietly fixed it. I also added in a %s (seconds since 01/01/1970) in front of the year to make cleaning up old backups easier.  The rest of the filename is purely to make the user's life easier in case they need to restore a backup.

edit: I'm removing the %s, and I'm renaming backup files so that I can easily support incremental backups in addition to full backups in the future.  I figured out a cleaner way to remove old files than trying to calculate how old files are using a difference in seconds from an epoch method.  I'll update the main post here in a few minutes with your suggested change.  I'll work on incremental backups as I have time.  This code is a work in progress, and is mostly untested so for the next few days we'll just have to rely on my interpretation of the man pages being correct (my tests worked, but I only had one backup to play with).  I really need to figure out how to use cron so that I can a) get it to do all the hard work (remembering to do shit) for me, and :P integrate it with the script to make it easy for you guys.



rad_ said:

* The map function fails silently if the required folders don't already exist.  The "maps" folder is made, but if the underlying "WORLDNAME" folders aren't already there, nothing happens.  I manually made the folders and it's fine now; not sure if this is a quirk on my system or an oversight....
Hmm, I'll look into fixing this.  I want this script to build up its environment properly if it isn't already, including building the appropriate directory structure.

edit: You are completely right, total oversight here. Fixed, directories are now created when needed.  The version of c10t that I was originally running wouldn't shut-up when I told it to (-s option), so I had its output routed to /dev/null, explaining the lack of error message when you first ran the map function.  I checked today's version of c10t (the script can now auto update), and it no longer has that problem, so I removed the output routing to allow any errors to flow through.


rad_ said:

* Would you consider adding a function to the backup routine that purges existing backups that are x days old, or only keeping the most recent x number of backups?  I know this is a really non-trivial change, but would be super convenient....

Definitely planned, in fact it is next on my list of features to add in.  I'm also looking at auto-injecting the script into a crontab so that you can schedule backups, but I've never played around with it before so it will be a fun learning experience.

edit: backup files now have a duration until they expire that can be changed in the beginning of the script.  See above.

rad_ said:

Also, I wrote a quick and dirty command that uses Ubuntu's native notification system to alert me when players log in or send messages (my server is just for myself and two RL friends, so it's not overwhelming to plug into all this activity and there's utility in knowing when my friends sign in).  I'd love to be able to incorporate this into your service so it starts (and stops) with the server itself, but I've had no luck at all.  I apologize that this is more of a vanity request, but it's possible someone else might find it useful (and I banged my head against getting it work for entirely too long):

tail -n0 -f $WORLDS_LOCATION/$1/server.log | grep --line-buffered -v "" | while read line; do notify-send "Minecraft Server:" "${line:20}" -i $LOCATION/osd-icon.png; done
You will instantly see how this works because you are a genius, but for anyone (like me) following along at home, I'll explain what happens there:

"tail -f" follows the server log, which gets you easy access to login/logout and all chat console messages
"grep -v """ will filter out lines from the log that you type into the chat console (becomes overwhelming without this and the messages are not important to see in the notification area)
"while read line" simple loop to send the notification for each line as it comes in
"notify-send" is the Ubuntu notification bubbles (see here for details)
"${line:20}" this just trims the line in question of the first 20 characters to remove the timestamps when popping up the notification.  Fancier sed regexps could net you more or less information, but this works well for me.
"osd-icon.png" is whatever you want the icon to be inside the bubble.  I used the 32px one from here and it's an excellent fit.

Curiously, this works when pasted into the terminal directly (with hardcoded values for the paths, natch), but fails when called as a bash script.  Apparently I am full of fail.

I'm sure this isn't useful widely enough to warrant inclusion in your script, but if you could provide some guidance on how to hack it in, I'd be super grateful.... I've tried a number of ways, but each of them broke the service.

This is cool.  I've been thinking of adding in some log parsing.  Being able to tie into libnotify would be a cool option, I'll see what it would take to add it in.

rad_ said:

Anyway, thanks so much for posting this in the first place.  I'm really surprised there aren't more comments here; you did a great job.

Thank you for the feedback!  I'm really happy to see that it is working for other people.

#4

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 14 January 2011 - 04:45 AM

Your recent changes are all really wonderful.  Great work.

I like the new send command, too.  Coupled with the new "list" server command, there's some potentially really useful information to be had here.  From what I can tell, though, the server only outputs the connected players to the log, so log parsing is still needed to really make sense of the info.

I added a quick couple lines to the "status" case in your script since I've got my hacky log notifications anyway, so I can see the results of the list at least.  Doesn't seem to be an elegant way to pull this off for real, though.  You'd have to parse the log completely and have a test case for when no one is connected (the console just returns nothing rather than a message about no one being connected), and then do heavy lifting on the log to output the names into the terminal into a list of their own where the "status" command was likely run.  So close, and yet....

#5

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 14 January 2011 - 10:22 PM

Ran into a new bug today.  I ran "update" through your script, but something failed silently.  Server said it restarted (I think.... If there was an error, it didn't stick out), so I left it alone.  Tried to log in a few hours later and nothing was connecting.

Turns out the server.jar was 0b.  Ran "update" again and it actually pulled the new file and now everything is great again.

Two things, then:

* Update routine should check for http errors and/or make sure the server software isn't 0 bytes.  If an error like that occurs, print a message and don't attempt to restart the server (maybe?).

* Server "start" routine could either have a quick error case for problems with the file itself and then try to update it (like on first run, but for errors like this), or at least print a message.  With my 0 byte server.jar it would just say "starting the server" and then nothing else would happen.  It wasn't too hard to find the problem, so this isn't a big deal, but it occurred to me that calling out the file as the problem would be somewhat helpful (though maybe not worth the extra weight in the code?), and that in doing so, the redownload could actually be cleverly automated....

#6

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 14 January 2011 - 11:43 PM

rad_ said:

Your recent changes are all really wonderful.  Great work.
Thanks!

rad_ said:

I like the new send command, too.  Coupled with the new "list" server command, there's some potentially really useful information to be had here.  From what I can tell, though, the server only outputs the connected players to the log, so log parsing is still needed to really make sense of the info.

I've been looking at the logs, and what I could do to them to make the information more available.  First off, I think I'm going to separate the logs into daily files, then have a cleanup routine similar to backup that will remove old logs.  I also plan on having a separate file in the world directory that will keep track of logged in users, that will be updated by catching the login and logout statements from the server (and if available and wanted, notify the desktop user of these events with libnotify as you requested).  I'm also thinking of tracking user issued server commands, in particular the give command.  I think it might be kind of neat to see a) who is using the command, and :Glass: what they are using it for.

rad_ said:

Ran into a new bug today.  I ran "update" through your script, but something failed silently.  Server said it restarted (I think.... If there was an error, it didn't stick out), so I left it alone.  Tried to log in a few hours later and nothing was connecting.

Turns out the server.jar was 0b.  Ran "update" again and it actually pulled the new file and now everything is great again.

I've put some effort into handling user errors correctly, but I haven't even thought of dealing with other sources of errors, such as you just ran into.  I'll take a closer look at the program and make sure that it catches more of these kind of errors.  Right now the script is deleting the old server.jar before trying to download the new one, I should probably keep it around until after the download finishes in case there is such an error.

If I don't spend too much time playing Minecraft over the weekend, I'll try to get some of the logging stuff coded up.  At the very least I'll take a look at error checking and get a new release out soon.  I've also been reading some rsync tutorials, and it seems like a more logical way to do incremental backups than tar.  I think I'll leave tar in the full backup routine, and set up some kind of rotating rsync for the incremental backups.

edit: The most recent version has some simple error detection on the wget and screen commands, if they fail it will now print an error message.  When updating the server it will restore a backup if available then stop execution, when updating c10t it will just print its message then stop execution.  If this method fails to detect the 0kb file issue that you saw, I might be able to add in some form of md5sum checking of the server jar or something (does Notch post this info??).

#7

deMangler

Posted 15 January 2011 - 02:35 PM

sandain said:

Download
Save the file as "minecraft_server", without the quotes.

Pastebin: http://pastebin.com/Bs4fxg77


Last Update

Excellent - Thank yoe very much for sharing this.


dM

#8

CFCParadox
    CFCParadox

    Nether Resident

  • Curse Premium
  • Curse Premium
  • 2159 posts
  • Location: United States
  • Minecraft: ProvisionHost

Posted 15 January 2011 - 03:57 PM

Interesting script I may try this our later and good luck with this project!

Posted Image

I am a representative of Provision Host


#9

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 15 January 2011 - 10:15 PM

I don't know why I didn't think of this sooner:
## Line 387
	  # Show the status of each world requested.
	  for WORLD in $WORLDS; do
		 printf "  $WORLD > status: "
		 if [ $(serverRunning $WORLD) = 1 ]; then
			printf "running.\n"
			sendCommand $WORLD "list"
			printf "  $WORLD > connected players: "
			PLAYERLIST=`eval tail -n1 $WORLDS_LOCATION/$WORLD/server.log | grep --line-buffered "players:"`
			if [ ${#PLAYERLIST} == "46" ]; then
			  printf "none\n"
			else
			  printf "${PLAYERLIST:46}\n"
			fi
		 else
			printf "not running.\n"
		 fi
	  done
Instead of writing the log in/out states to a file, you can just send the list command and immediately tail the log for the connected players.  (This will report "none" if something else is concurrently logged and the last line isn't the connected players list.  Not sure how likely this is.  Tried implementing a check for zero length on $PLAYERLIST and running the list/tail again if it was, but didn't want to structure that into a loop, so just pulled the check out....)

One benefit from doing it the way you wanted (current list of logged in players in a separate file), though, is that having that info handy would make listening for chats in the log easier (grep "<$1>|<$2>|..." -> though I'm not sure how best to structure that code on account of ther ebeing a variable number of usernames)....  But it sounds a lot more complicated.

The above works great on my end, but I had to change your script to execute as BASH instead of just SH in line 1.  Apparently SH doesn't support the substring syntax and I couldn't find a reference anywhere for relevant operations.  No noticeable impact elsewhere for the change, but I'm a little wary.  Did you use SH for any explicit reasons?

Also, this means I can probably put the libnotify stuff from before in the script proper (inelegant though it is), since the trim function was the likely cause of the errors there, too.  Will have to roll up my sleeves and more properly parse the log to keep notifications down....

As ever: thank you and you rock.

#10

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 15 January 2011 - 10:38 PM

Strike that about the chats.  Potentially better idea:

1. Parse log for "<*>" lines, strip timestamp, write to chat.log file as they come in
2. Follow chat.log and grep -v yourself (hardcoded variable in script? read from admin file?)
3. libnotify the lines that are left

No need to follow log in/out, and seems like much simpler logic to structure.  What do you think?

#11

deMangler

Posted 16 January 2011 - 01:28 AM

For some reason I couldn't get the script from pastebin without having ^M's at the end of each line. So the script would not run. Maybe I don't understand pastebin.

So, just in case anyone else is having this problem, running (for example if you call your download file pesky-ctrl-m-bah ):

sed 's/'"$(printf '\015')"'$//g' pesky-ctrl-m-bah >>minecraft_server

produces the file minecraft_server with no pesky ^M's

dM

#12

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 16 January 2011 - 06:56 AM

deMangler said:

For some reason I couldn't get the script from pastebin without having ^M's at the end of each line. So the script would not run. Maybe I don't understand pastebin.

So, just in case anyone else is having this problem, running (for example if you call your download file pesky-ctrl-m-bah ):

sed 's/'"$(printf '\015')"'$//g' pesky-ctrl-m-bah >>minecraft_server

produces the file minecraft_server with no pesky ^M's

dM


I've never had a problem with ^M getting inserted into things with Pastebin, but I've been thinking of changing hosts anyway.  I would like to include in the update routine a method to update the script, but the address for Pastebin changes with every update.  Does Sourceforge sound reasonable?  I'm using it for a couple of other projects, it might work here too.

BTW: Pastebin has a download link on the upper right hand side of the page.  I'm not sure if that is what is giving you the problem or not, but it seems to work for me.

#13

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 16 January 2011 - 07:21 AM

rad_ said:

Apparently SH doesn't support the substring syntax and I couldn't find a reference anywhere for relevant operations.  No noticeable impact elsewhere for the change, but I'm a little wary.  Did you use SH for any explicit reasons?

SH is just a soft link to your default shell environment.  User shells are often Bash by default, but on Debian and Ubuntu based distros, they are switching over to using Dash as the default shell for root.  Since I want this script to be as portable as possible, I've used only the subset of the shell language that is supported by almost all shell environments, and Dash is as limited as they come.  You can do pretty much anything you want to do in Dash without resorting to using a Bash specific extension with very little effort as I've so far found.  Feel free to change the shabang line to Bash if you want, it will make little difference.

rad_ said:

Strike that about the chats.  Potentially better idea:

1. Parse log for "<*>" lines, strip timestamp, write to chat.log file as they come in
2. Follow chat.log and grep -v yourself (hardcoded variable in script? read from admin file?)
3. libnotify the lines that are left

No need to follow log in/out, and seems like much simpler logic to structure.  What do you think?

I'm still working on the code, but I should be able to track users logging in and out by searching for the following patterns:
Logins:
 

I also plan on capturing any command response data issued by the send command, and returning the text to the console that issued the command.  This might be tricky, but if I can get it to work, I'll be looking for the following pattern:
 

I'm still quite a ways off from having anything usable, I'll try to get something posted this weekend.  I've been working on my minecart station quite a bit lately, and in fact hit a major milestone with it today:  the minecart request button finally works.  Four holding bays, two levels of tracks, and two levels of logic circuits... I never thought I would ever use my logic circuit classes in college, but they are surprisingly coming in handy at playing this game. Ha.  Programming in a high level language like Perl, Java, or even shell script is light-years easier than dealing with 1's, 0's, and some NOR gates.  Debugging this stuff is hell!  I've gained some new respect for the world's Electrical Engineers, seriously.

#14

rad_
    rad_

    Tree Puncher

  • Members
  • 11 posts

Posted 16 January 2011 - 08:40 AM

sandain said:

You can do pretty much anything you want to do in Dash without resorting to using a Bash specific extension with very little effort as I've so far found.
According to this, the replacement for my simple Bash substring operation is to use sed or awk, which I couldn't make work for the life of me the first time around.  I will bow out and just wait to see what you come up with....

Congrats on the minecart station!

#15

kroimon
    kroimon

    Out of the Water

  • Members
  • 3 posts

Posted 16 January 2011 - 04:22 PM

Great script, thank you!

The only problem I have is that the c10t function only works for worlds called "world", as this is hardcoded:
su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/surface.png" $USER_NAME
For a world called "beta" for example, the world files actually are in $WORLDS_LOCATION/beta/beta, not $WORLDS_LOCATION/beta/world. Therefore the lines should be as follows:
su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface.png" $USER_NAME

An updated version can be found here.

#16

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 17 January 2011 - 01:30 AM

kroimon said:

Great script, thank you!

The only problem I have is that the c10t function only works for worlds called "world", as this is hardcoded:
su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/surface.png" $USER_NAME
For a world called "beta" for example, the world files actually are in $WORLDS_LOCATION/beta/beta, not $WORLDS_LOCATION/beta/world. Therefore the lines should be as follows:
su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface.png" $USER_NAME

An updated version can be found here.

I've thought of changing the code so that Minecraft and the script are using the same name for the world (right now Minecraft only sees the world name 'world' regardless of what the script thinks the world name is), but the change needs to happen in a few places.  For instance, when first starting the server, it checks to make sure that the server.properties file exists, and it defaults to using a world name of 'world' if it doesn't.  As far as I know, the only reason you should actually hit an issue here is if you started using this script with a previously running server, and in that case you would have to modify your config anyway.  At this point, I'm a bit loathe to change it, but it is a probably a good idea in the long run.  The problem is, this script has an existing user-base, so I'll either have to add code to update the old way to the new way of doing things, or break old configurations.  Neither option is ideal, hence my reluctance to do this right now.  =/

Edit:  I went ahead and made this change.  The script should hopefully update any old configurations.

#17

thedrock
    thedrock

    Out of the Water

  • Members
  • 5 posts

Posted 18 January 2011 - 01:51 AM

Hi,

Thanks for the great script. I have it running (mainly).. but I had a few issues.

My system: Ubuntu 9.10. I had the other script running with dated backups as a bash script if that makes a difference.

1. wont' download new c10t bin. (can't find an error)
But I just placed the bin in the correct dir

2. Backup places a oddly named .gz file into the correct dir. I take it that my system doesn't like the date code you use.

Also it looks like i have my working dirs a bit different. I tried to edit it but maybe there is something missing.  (ie. It seems to me that your worlds are in /minecraft_server/worlds/world/world

Any suggestions would be greatly appreciated.
Cheers,
d

#18

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 18 January 2011 - 10:10 PM

thedrock said:

Hi,

Thanks for the great script. I have it running (mainly).. but I had a few issues.

My system: Ubuntu 9.10. I had the other script running with dated backups as a bash script if that makes a difference.

1. wont' download new c10t bin. (can't find an error)
But I just placed the bin in the correct dir

2. Backup places a oddly named .gz file into the correct dir. I take it that my system doesn't like the date code you use.

Also it looks like i have my working dirs a bit different. I tried to edit it but maybe there is something missing.  (ie. It seems to me that your worlds are in /minecraft_server/worlds/world/world

Any suggestions would be greatly appreciated.
Cheers,
d

Try the most recent version of the script and let me know if you are still having the same problems.  I've made a few changes that might clean things up for you.

If you are still having issues, let me know what the output from the following commands are:
uname -m
date +%Y-%m-%d-%H:%M:%S

The current code tells Minecraft to load the world files located in /home/minecraft/worlds/alpha/alpha if the world's name is 'alpha'.  The first alpha denotes the world name that the script sees, the second is actually the level-name in the server.properties file.  Old versions of the script told Minecraft that the level-name was 'world', regardless of what the script thought the world name was (ie /home/minecraft/worlds/alpha/world), but I found this slightly confusing myself and was not surprised to see issues in this thread.  I just changed it so that the world name that the script sees is the same as the level-name that Minecraft sees.  The double alpha in the directory name is still required to keep the Minecraft server files for each world separate from one another easily (and keep the server itself happy).  I hope this explains your last question.

#19

thedrock
    thedrock

    Out of the Water

  • Members
  • 5 posts

Posted 19 January 2011 - 04:32 AM

Hey,

Thanks for replying. It didn't make a difference.  I am not sure what I am doing wrong here. The only change I have made is the folders. I found that kept everything in a slightly different structure. (If you think that is an issue I can explain it)

uname -m
i686
date +%Y-%m-%d-%H:%M:%S
2011-01-18-20:30:39

Anything else I can try? I guess there will be a web interface for this sort of thing soon. (bukket? or something). But I like the ability to SSH in and make these simple changes...

Thanks again,
d

#20

sandain
    sandain

    Zombie Killer

  • Members
  • 221 posts

Posted 19 January 2011 - 05:12 AM

thedrock said:

Hey,

Thanks for replying. It didn't make a difference.  I am not sure what I am doing wrong here. The only change I have made is the folders. I found that kept everything in a slightly different structure. (If you think that is an issue I can explain it)

uname -m
i686
date +%Y-%m-%d-%H:%M:%S
2011-01-18-20:30:39

Anything else I can try? I guess there will be a web interface for this sort of thing soon. (bukket? or something). But I like the ability to SSH in and make these simple changes...

Thanks again,
d

Ok, that explains the issue with updating c10t.  My box returns 'x86_64' with the uname command, and I assumed that 32 bit boxes returned 'x86'.  I'll make some changes to fix this one.

As far as the issue with the backups, give me a directory listing or an example of the failed backup names.  It should look like 'fullBackup-alpha-2011-01-12-21:41:55.tar.gz'.  Your date command appears to function the same as mine, so I'm not sure what's going on here.  Maybe I should simplify the names by removing the time stamp, although I like being able to have multiple backups in a single day.  I'll try to think of a possible work around while I wait for your reply on this one.