예제 #1
0
def main(args):
    qryr = SourceQuery(args[0], int(args[1]))
    
    sinfo = qryr.info()
    splayer = sorted(qryr.player(), key=lambda p: p['kills'], reverse=True)
    srules = qryr.rules()
    
    print sinfo['hostname']
    print '*' * len(sinfo['hostname'])
    print
    
    print "(" + ("Linux" if sinfo['os'] == 'l' else "Windows") + " server, version " + str(sinfo['version']) + (", passworded" if sinfo['passworded'] == 1 else ', unpassworded') + ")"
    print
    
    print str(sinfo['numplayers']) + " of " + str(sinfo['maxplayers']) + " players mooching about:"
    
    for p in splayer:
        pname = "<unnamed>" if p['name'] == "" else p['name']
        print " - " + pname + " (" + str(p['kills']) + " kills" + (" as they suck at this game" if p['kills'] == 0 else "") + ", connected for " + str(int(p['time'])) + "s)"
	
    print
    
    print "Current map is " + sinfo['map'] + ". Next is currently " + srules['sm_nextmap'] + "." + ("Learning through repetition!" if sinfo['map'] == srules['sm_nextmap'] else "")
    print
    
    print "Gravity is currently " + srules['sv_gravity']
    print
예제 #2
0
def ezq(adr, port):
    """
    ez-query, put in an ip/port, get out
    info, players, rules dictionaries.
    """
    srcquery = SQ(adr, int(port))
    players = srcquery.player()
    info = srcquery.info()
    rules = srcquery.rules()

    return info, players, rules
예제 #3
0
	def __init__(self, logger, UpdateToolPath, serverDirectory, serverArgs):
		self.logger = logger
		self.serverDir = serverDirectory
		self.serverArgs = serverArgs
		self.serverConfig = NS2Config(serverArgs,serverDirectory)
		self.serverRcon = NS2Rcon(self,serverDirectory)

		self.restartWhenEmpty = False
		self.noUpdateCheck = False

		argParser = argparse.ArgumentParser(prog='NS2')
		argParser.add_argument('--restartwhenempty',action='store_true')
		argParser.add_argument('--noupdatecheck',action='store_true')
		try:
			parsed,otherargs = argParser.parse_known_args(serverArgs.split(' '))
			self.restartWhenEmpty = parsed.restartwhenempty
			self.noUpdateCheck = parsed.noupdatecheck
		except:
			pass

		# have to do this after we parse the command line
		self.findUpdateTool(UpdateToolPath)

		# NS2 doesn't like extra command line args (and will die if they are present)
		self.serverArgs = self.serverArgs.replace('--restartwhenempty','').replace('--noupdatecheck','')

		# Query is one port higher then join
		self.serverPort = int(self.serverConfig['port'])+1

		self.logger.info("Detected server IP as %s:%i" % (self.serverConfig['address'],self.serverPort))
		self.queryObject = SourceQuery(self.serverConfig['address'],self.serverPort)

		if self.restartWhenEmpty:
			self.logger.info("Server will be automatically restarted when empty")
		else:
			self.logger.info("Server will *NOT* be automatically restarted when empty")

		if self.serverConfig['game'].lower().find("ns2gmovrmind") != -1:
			self.getTickrate = True
			self.logger.info("NSGmOvermind detected, tickrate stats are available")
			self.logger.debug("NS2GmOvermind query: %s:%i" % (self.serverConfig['address'],self.serverPort+1))
			self.overmindQueryObject = SourceQuery(self.serverConfig['address'],self.serverPort+1)
		else:
			self.getTickrate = False
			self.logger.info("NS2GmOvermind *NOT* detected, tickrate stats unavailable")
예제 #4
0
def checkRestart() :
  status, home = getstatusoutput("echo $HOME")
  
  server = "confusedherring.com"
  
  dir = home + "/tmp/"
  files = os.listdir(dir)
  runningServers = getRunningServerNames()

  for file in files:
    print "file: %s" % file
    f = open(dir + file, 'r');
    cmd = f.readline().strip();
    matchobj = re.search('([a-zA-Z0-9\-]+)-(\d+)\.server', file)
    if matchobj == None:
      continue;  
    servername = matchobj.group(1);

    server_running = 0
    #except: wasnt working, so do it the long way
    
    for tmp_servername in runningServers:
      if servername == tmp_servername:
        server_running = 1;
        break;
	
    if server_running == 1:
      serverDetails = getConfigDetails(servername)
      query = SourceQuery(server, int(serverDetails['port']))
      sinfo = query.info();
      if int(sinfo['numplayers']) <= 1:
        print "1 or less";
        restartServer([servername])
        os.system("rm " + dir + file);
    else:
      startServer([servername])
      os.system("rm " + dir + file);
예제 #5
0
def check_css(address, port=27015):
    try:
        css = SourceQuery(address, port)
        return css.info()
    except:
        return None
예제 #6
0
#!/usr/bin/python

from SourceQuery import SourceQuery
import sys

server = SourceQuery('91.121.95.23', 27013)
#print server.ping()
print server.info()
print server.player()
print server.rules()
예제 #7
0
class NS2Update:
	# Handle to the process where the server is running
	serverProc = None
	# outputThread will be a seperate thread that is spawned to grab all the output from the server
	# It will push it all into outputQueue, as well as to serverLogFile
	# outputQueue is currently unused, but will ultimately allow actions to be taken based on log events
	outputQueue = None
	chatQueue = None
	outputThread = None
	serverLogFile = None
	# Time of the last update check
	lastCheck = 0
	# How often we should check for updates.  This is set by the update server
	checkDelay = 300
	# What URL to grab the latest version from.  Ideally we would grab this from the CDR on the fly
	# but that's not terribly resource-friendly to do
	versionURL = "http://ns2update.devicenull.org/ns2update/ns2version.txt"
	# What version of the software is the server currently running
	currentVersion = 0
	# What arguments should we pass to the server on startup
	serverArgs = ''
	# Is the server empty or not?
	serverEmptyCount = 0
	# Store the time we last started the server
	lastStart = 0
	# Should we disable update checking?
	noUpdateCheck = False
	# This gets set to true when the server has had players on it
	hasHadPlayers = False
	# Store the last stats values
	lastCPU = 0
	lastMemory = 0
	lastTickrate = 0

	def __init__(self, logger, UpdateToolPath, serverDirectory, serverArgs):
		self.logger = logger
		self.serverDir = serverDirectory
		self.serverArgs = serverArgs
		self.serverConfig = NS2Config(serverArgs,serverDirectory)
		self.serverRcon = NS2Rcon(self,serverDirectory)

		self.restartWhenEmpty = False
		self.noUpdateCheck = False

		argParser = argparse.ArgumentParser(prog='NS2')
		argParser.add_argument('--restartwhenempty',action='store_true')
		argParser.add_argument('--noupdatecheck',action='store_true')
		try:
			parsed,otherargs = argParser.parse_known_args(serverArgs.split(' '))
			self.restartWhenEmpty = parsed.restartwhenempty
			self.noUpdateCheck = parsed.noupdatecheck
		except:
			pass

		# have to do this after we parse the command line
		self.findUpdateTool(UpdateToolPath)

		# NS2 doesn't like extra command line args (and will die if they are present)
		self.serverArgs = self.serverArgs.replace('--restartwhenempty','').replace('--noupdatecheck','')

		# Query is one port higher then join
		self.serverPort = int(self.serverConfig['port'])+1

		self.logger.info("Detected server IP as %s:%i" % (self.serverConfig['address'],self.serverPort))
		self.queryObject = SourceQuery(self.serverConfig['address'],self.serverPort)

		if self.restartWhenEmpty:
			self.logger.info("Server will be automatically restarted when empty")
		else:
			self.logger.info("Server will *NOT* be automatically restarted when empty")

		if self.serverConfig['game'].lower().find("ns2gmovrmind") != -1:
			self.getTickrate = True
			self.logger.info("NSGmOvermind detected, tickrate stats are available")
			self.logger.debug("NS2GmOvermind query: %s:%i" % (self.serverConfig['address'],self.serverPort+1))
			self.overmindQueryObject = SourceQuery(self.serverConfig['address'],self.serverPort+1)
		else:
			self.getTickrate = False
			self.logger.info("NS2GmOvermind *NOT* detected, tickrate stats unavailable")

	def findUpdateTool(self,extraPath):
		if self.noUpdateCheck:
			self.logger.info("Update checking disabled, not looking for hldsupdatetool")
			return

		paths = [ "../hldsupdatetool.exe", "hldsupdatetool.exe" ]

		if extraPath != None and extraPath != '':
			paths.append(extraPath)

		self.updatePath = ""
		for cur in paths:
			if os.path.exists(cur):
				self.updatePath = cur

		if self.updatePath == "":
			self.logger.critical("Unable to find hldsupdatetool.exe, please copy to server directory or see README")
			raise NameError("Unable to find hldsupdatetool.exe")

	def doUpdate(self):
		self.logger.info("Starting server update")

		update = subprocess.Popen("%s -command update -game naturalselection2 -dir %s" % (self.updatePath,self.serverDir))
		if update:
			while update.returncode == None:
				time.sleep(5)
				update.poll()

		self.logger.info("Server update complete!")

	def startServer(self):
		# If we are starting the server, it must be empty
		self.serverEmptyCount = 0
		self.hasHadPlayers = False
		self.lastStart = time.time()

		# Actually start the server process
		self.serverProc = subprocess.Popen("Server.exe %s" % self.serverArgs, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
		self.logger.info("Server started, pid %i version %s" % (self.serverProc.pid,self.currentVersion))

		# Open up the log file
		logName = strftime("%Y.%m.%d.%H%M.log")
		self.logger.debug("Logging to %s" % logName)
		self.serverLogFile = open("serverlogs/%s" % logName,"a")

		# Setup everything we need to capture the server output
		self.outputQueue = Queue()
		self.chatQueue = Queue()
		self.outputThread = Thread(target=enqueue_output, args=(self.serverProc.stdout, self.outputQueue, self.serverLogFile, self.chatQueue))
		self.outputThread.daemon = True
		self.outputThread.start()
		self.outputQueue.put("*** SERVER STARTED ***\n")

	def stopServer(self):
		if self.serverProc != None:
			self.logger.info("Killing server")
			self.serverProc.kill()
			self.cleanupServer()

	def cleanupServer(self):
		if self.outputThread != None:
			self.outputThread.join()
		if self.serverLogFile != None:
			self.serverLogFile.close()
		self.outputThread = None
		self.serverLogFile = None
		self.serverProc = None

	# Tickrate is currently unsupported, but adding it here is easier then modfiying rrd's later
	def recordStats(self,players,tickrate):
		if not os.path.exists("%s/rrdtool.exe" % self.serverDir):
			return

		statsFile = "%s/ns2update.rrd" % (self.serverDir)
		if not os.path.exists(statsFile):
			#os.system("\"%s/rrdtool.exe\" create \"%s\" DS:memory:GAUGE:300:0:U DS:cpu:GAUGE:600:0:U DS:players:GAUGE:600:0:U DS:tickrate:GAUGE:600:0:U RRA:LAST:0.5:1:2016 RRA:AVERAGE:0.5:2:2016" % (self.serverDir,statsFile))
			subprocess.Popen(["%s/rrdtool.exe" % self.serverDir, "create", statsFile, "DS:memory:GAUGE:300:0:U", "DS:cpu:GAUGE:600:0:U", "DS:players:GAUGE:600:0:U", "DS:tickrate:GAUGE:600:0:U", "RRA:LAST:0.5:1:2016", "RRA:AVERAGE:0.5:2:2016"])

		p = psutil.Process(self.serverProc.pid)
		cpu = p.get_cpu_percent(interval=1.0)
		meminfo = p.get_memory_info()
		rss = meminfo[0] / 1024 / 1024

		self.logger.debug("CPU usage: %02i, memory: %04i MB, players: %02i tickrate: %02i" % (cpu, rss, players, int(tickrate)))
		self.lastCPU = cpu
		self.lastMemory = rss
		self.lastTickrate = tickrate

		#os.system("\"%s/rrdtool.exe\" update \"%s\" N:%i:%f:%i:%s" % (self.serverDir, statsFile, rss, cpu, players, tickrate))
		subprocess.Popen(["%s/rrdtool.exe" % self.serverDir, "update", statsFile, "N:%i:%f:%i:%s" % (rss, cpu, players, tickrate)])

		# Escape colons so rrdtool doesn't die
		statsFile = statsFile.replace(":","\\:")
		subprocess.Popen("\"%s/rrdtool.exe\" graph \"%s/ns2server.png\" --height 200 --width 400 --font DEFAULT:0:\"%s\"/rrdfont.ttf  DEF:memory=\"%s\":memory:LAST CDEF:memorydisp=memory,10,/ DEF:cpu=\"%s\":cpu:LAST DEF:players=\"%s\":players:LAST DEF:tickrate=\"%s\":tickrate:LAST AREA:cpu#00FF00:\"%% CPU Usage\"  LINE:memorydisp#FF0000:\"Memory usage (MB/10)\" LINE1:players#0000FF:\"Players\" LINE1:tickrate#000000:\"Tickrate\"" % (self.serverDir, self.serverDir, self.serverDir, statsFile, statsFile, statsFile, statsFile),stdout=subprocess.PIPE).wait()

	def think(self):
		if not self.noUpdateCheck and time.time() - self.lastCheck > self.checkDelay:
			self.logger.debug("Checking for server update...")
			data = urllib2.urlopen(self.versionURL)

			temp = data.read(100).split(",")
			if temp[0] > 0 and temp[1] > 60:
				desiredVersion = temp[0]
				if self.checkDelay != int(temp[1]):
					self.checkDelay = int(temp[1])
					self.logger.debug("Setting update check delay to %i" % self.checkDelay)

			if desiredVersion > self.currentVersion:
				self.logger.info("Server is out of date: current: %s desired: %s" % (self.currentVersion,desiredVersion))
				if self.serverProc != None:
					self.stopServer()

				if self.currentVersion == 0:
					self.logger.info("Performing inital server update")
					self.doUpdate()
				else:
					self.doUpdate()

				self.currentVersion = desiredVersion
				self.startServer()
			self.lastCheck = time.time()

		if self.serverProc == None:
			self.startServer()

		self.serverProc.poll()
		if self.serverProc.returncode != None:
			self.logger.critical("Server has died, restarting!")
			self.cleanupServer()
			self.startServer()

		currentPlayers = 0
		tickrate = 0
		# Don't check the server for 10s after it started (avoids issues with query not responding during startup)
		if time.time()-self.lastStart > 10:
			# If we are going to attempt to restart the server when it's empty, we need to query it..
			try:
				details = self.queryObject.info()
				currentPlayers = details['numplayers']

				if self.restartWhenEmpty:

					if details['numplayers'] == 0:
						self.serverEmptyCount += 1
					else:
						self.serverEmptyCount = 0
						self.hasHadPlayers = True

					if self.serverEmptyCount > 5 and self.hasHadPlayers:
						self.logger.info("Server now empty, restarting")
						self.stopServer()
						time.sleep(1)
						self.startServer()
			except IOError:
				pass

			try:
				if self.getTickrate:
					rules = self.overmindQueryObject.rules()
					tickrate = rules['netstat_tickrate']
			except IOError:
				pass

		self.recordStats(currentPlayers,tickrate)

		# Use this to read console output without blocking
		#try:
		#	while 1==1:
		#		line = outQueue.get_nowait()
		#except Empty:
		#	pass

	def sendCommand(self,command):
		print "Sending command: %s" % command
		self.serverProc.stdin.write("%s\r\n" % command)
예제 #8
0
 def save(self):
     server = SQ(self.address, int(self.port))
     self.name = server.info()['hostname']
     self.slug = "{0}-{1}".format(self.address, self.port)
     super(Server, self).save()
예제 #9
0
def check_css(address, port=27015):
    try:
        css = SourceQuery(address, port)
        return css.info()
    except:
        return None