Skip to content

Instantly share code, notes, and snippets.

@zekroTJA
Last active October 18, 2017 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zekroTJA/384d56e19f2118ec94bcbea3875c0e54 to your computer and use it in GitHub Desktop.
Save zekroTJA/384d56e19f2118ec94bcbea3875c0e54 to your computer and use it in GitHub Desktop.
Python script for managing multiple minecraft servers on an VPS
# # # # # # # # # # # # # # # # # # # # # # # # #
# #
# © 2017 Ringo Hoffmann (zekro Development) #
# #
# If you want to use this code, please read #
# this first: http://s.zekro.de/codepolicy #
# #
# With usage of this code or parts of it in #
# any way, you agree to the terms above. #
# #
# # # # # # # # # # # # # # # # # # # # # # # # #
import sys
import os
import subprocess
import json
import psutil # 'pip install psutil'
args = sys.argv
dirs = os.listdir(".")
servers = []
inp = ""
VERSION = "1.3.0"
class Color:
W = '\033[0m' # white (normal)
R = '\033[31m' # red
G = '\033[32m' # green
O = '\033[33m' # orange
B = '\033[34m' # blue
P = '\033[35m' # purple
C = '\033[36m' # cyan
def clr(content, color):
"""
Returns colored text
<color> -> type of class Color
"""
return color + content + Color.W
def error(content):
"""
Displays red colored error message with button press pause
"""
print(clr("[ERROR] "+ content, Color.R))
input()
def isRunning(name):
"""
Returns boolean if current screen is running by checking
if 'screen -ls' contains server name
"""
proc = subprocess.Popen(["screen", "-ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return name in str(proc.stdout.read())
def clear():
subprocess.call("clear")
def getSys():
"""
Retuns system status string from psutil data
"""
cpulaod = psutil.cpu_percent() # CPU-Load in %
mem = psutil.virtual_memory() # Memory data container
memtotal = mem.total / 1024 / 1024 # Total memory in MiByte
memused = mem.used / 1024 / 1024 # Used memory in MiByte
memload = mem.percent # Used memory in % of total
disk = psutil.disk_usage(".") # disk usage data container
disktotal = disk.total / 1024 / 1024 / 1024 # total disk space in GiByte
diskused = disk.used / 1024 / 1024 / 1024 # used disk space in GiByte
diskload = disk.percent # used disk space in % of total
return str("CPU load: %d %%\n"
"Memory (used): %d MiB / %d MiB (%d %%)\n"
"Space (used): %d GiB / %d GiB (%d %%)"
% (cpulaod, memused, memtotal, memload, diskused, disktotal, diskload))
def printMenu():
"""
Printing the main menu and returning the input command
"""
global servers
clear()
print(clr("Server Management System v." + VERSION + " - (c) 2017 zekro\n", Color.C))
# Print system stats from getSys()
print("SYSTEM STATS: \n" + getSys() + "\n")
# collecting local directory names which dont start with '.'
servers = [d for d in dirs if os.path.isdir(d) and not d.startswith('.')]
# Printing server table '[STATE] [#] DIRNAME'
for i, d in enumerate(servers):
# getting status of server with isRunning(<servername>)
running = clr("[RUNNING]", Color.G) if isRunning(d) else clr("[STOPPED]", Color.O)
print("%s [%d] %s" % (running, i + 1, d))
# waiting for console input and retun it
return input("\nPlease enter a command\nType 'help' for command list\n\n> ")
def getStart(name):
"""
Getting the start command from <servername>/STARTCMD.txt file
"""
setfile = name + "/STARTCMD.txt"
if not os.path.isfile(setfile):
error("'STARTCMD.txt' was not found!")
exit()
else:
with open(setfile, "r") as f:
out = f.readline()
if not out:
error("No start command was found in 'STARTCMD.txt'!")
exit()
return out
def runMain():
"""
Saving returned console input of printMenu() in global inp var
This is essential for menu input loop later
"""
global inp
inp = printMenu()
# <--------------==[ MAIN PROGRAM ]==-------------->
runMain()
# While 'exit' command was not executed or exception
# was thrown redraw menue and collect input
while not "exit" in inp:
invoke = inp.split()[0].lower()
args = inp.split()[1:]
if len(args) > 0:
# COMMAND: 'start <index>'
# Starting a server by index
if invoke == "start":
index = int(args[0]) - 1
# if index is out of range return error
if index >= len(servers) or index < 0:
error("Please enter a valid number!")
else:
server = servers[index]
if isRunning(server):
error("This server is currently still running!")
else:
# splitting start command of 'STARTCMD.txt' into arguments
command = getStart(server).split()
# default start arguments for screen
# '-S <servername>' -> setting screen name
# '-L' logging cmd output in 'screenlog.0' file
start = ["screen", "-S", server, "-L"]
os.chdir(server)
# injecting start command into screen command arguments
for arg in command:
start.append(arg)
# calling screen process
subprocess.call(start)
exit()
# COMMAND: 'stop <index>'
# Stopping a running server by index
if invoke == "stop":
index = int(args[0]) - 1
if index >= len(servers) or index < 0:
error("Please enter a valid number!")
else:
server = servers[index]
if not isRunning(server):
error("This server is not running!")
else:
# calling 'screen -X -S <screenname> quit' to stop the screen
subprocess.call(["screen", "-X", "-S", server, "quit"])
# COMMAND: 'resume <index>'
# Resuming a screen of server by index
if invoke == "resume":
index = int(args[0]) - 1
if index >= len(servers) or index < 0:
error("Please enter a valid number!")
else:
server = servers[index]
if not isRunning(server):
error("This server is not running!")
else:
# resuming screen by command 'screen -r <screenname>'
subprocess.call(["screen", "-r", server])
exit()
elif invoke == "help":
print(
"\n"
"start <index> - Start a stopped server\n"
"stop <index> - Stop a running server\n"
"resume <index> - Resuming a running screen session\n"
"exit - Exit this tool"
)
print("[Press any key to continue...]")
input()
else:
error("Please enter a valid command or type 'help' for all commands!")
runMain()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment