changed the way of getting data out of windows to make it faster

This commit is contained in:
alejandro 2023-03-09 13:16:28 +01:00
parent c977188e75
commit e3f606530a

View File

@ -6,21 +6,22 @@
# #
# (c) A. Kevin Rojas <kevin.rojas@pandorafms.com> # (c) A. Kevin Rojas <kevin.rojas@pandorafms.com>
# #
# Edited in 2023 by Alejandro Sánchez <alejandro.sanchez@pandorafms.com>
#
# TO DO LIST: # TO DO LIST:
# - Enable child services detection (Windows) # - Enable child services detection (Windows)
# - Make CPU/Memory usage available for child services (Windows) # - Make CPU/Memory usage available for child services (Windows)
# #
################################################### ###################################################
try: try:
from sys import argv from sys import argv
from sys import stderr from sys import stderr
from sys import exit from sys import exit
import psutil
from subprocess import Popen from subprocess import Popen
from subprocess import PIPE from subprocess import PIPE
from subprocess import DEVNULL from subprocess import DEVNULL
from subprocess import getstatusoutput from subprocess import getstatusoutput
import psutil
except ModuleNotFoundError as err: except ModuleNotFoundError as err:
print("{} error: {}. Exiting...".format(argv[0], err), file=stderr) print("{} error: {}. Exiting...".format(argv[0], err), file=stderr)
exit(1) exit(1)
@ -28,99 +29,100 @@ except ModuleNotFoundError as err:
module_list = [] module_list = []
VERSION = "1.2" VERSION = "1.2"
def win_service(servicelist, option=False, memcpu=False):
######################################################################################### modules_default = []
# Powershell class modules_percentage=[]
######################################################################################### ## take all services
class PSCheck: services=psutil.win_service_iter()
@staticmethod for service in services:
def check_service(servicename, option=False, memcpu=False): if service.name() in servicelist:
"""Check services with powershell by parsing their DisplayName. Returns a dict\ serv=service.as_dict()
list with the name of the service and a boolean with its status.\n if serv['status']=='running':
Requires service name (case insensitive).""" value=1
pscall = Popen(["powershell", "Get-Service", "-Name", "'*"+ str(servicename) + "*'",
"|", "Select-Object", "-ExpandProperty", "Name"],
stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
result = pscall.communicate()
result = str(result[0]).strip().split("\n")
procname = ''
if result != '':
output = []
for element in result:
if element != '':
# Get process name
procname = PSCheck.get_serviceprocess(element)
# Get process status
parstatus = PSCheck.getstatus(element)
if memcpu and parstatus == 1:
usage = get_memcpu(str(procname), str(element))
output += usage
# Generate module with name and status
parent = service_module(str(element), parstatus)
output += parent
if option:
children = PSCheck.getchildren(element, memcpu)
if isinstance(children, list) and len(children) > 1:
for child in children:
output += child
else:
output += children
else:
next
if output and element and procname:
return ({"name" : element, "process" : procname, "modules": output})
else: else:
return (None) value=0
@staticmethod ## create module for each service
def getchildren(servicename, memcpu=False): parent = build_module("Service " + str(serv['name']) + " - Status", value,"generic_proc")
"""Gets Dependent services of a given Windows service""" modules_default +=parent
pschild = Popen(["powershell", "Get-Service", "-Name '" + str(servicename) +
"' -DS", "|", "Select-Object", "-ExpandProperty", "Name"], # memory and cpu percentage
stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True) if memcpu:
children = pschild.communicate()[0].strip() ## process
kids = [] srv_pid = service.pid()
for child in (children.split("\n") if children != "" else []): process = psutil.Process(srv_pid)
status = PSCheck.getstatus(child) proc_name = process.name()
kids += service_module(str(child), status, "Service " + str(servicename) + " - Status") ##cpu
if status: value_cpu=process.cpu_percent(interval=0.5)
if memcpu: parent = build_module("Service " + str(proc_name) + " - CPU usage", value_cpu,"generic_data")
kidsusage = get_memcpu(str(child)) parent[0].update([("unit","%"),("module_parent",str(serv['name']))])
for usage in kidsusage: modules_percentage +=parent
kids += usage ##mem
value_mem=process.memory_percent()
parent = build_module("Service " + str(proc_name) + " - Memory usage", value_mem,"generic_data")
parent[0].update([("unit","%"),("module_parent",str(serv['name']))])
modules_percentage +=parent
for module in modules_default:
print_module(module, 1)
if memcpu:
for module in modules_percentage:
print_module(module, 1)
def lnx_service(services_list, memcpu=False):
"""Creates modules for Linux servers"""
modules = []
sysctl = getstatusoutput("command -v systemctl")[0]
servic = getstatusoutput("command -v service")[0]
for srvc in services_list:
status = None
if sysctl == 0:
### Systemd available
syscall = Popen(["systemctl", "show", "-pLoadState", "-pActiveState", srvc], stdout=PIPE,
stdin=DEVNULL, universal_newlines=True)
result = syscall.communicate()
srvstatus = result[0].strip().lower().split("\n")
if srvstatus[0] == "loadstate=not-found":
next
else:
if srvstatus[1] == "activestate=active":
modules += build_module("Service " + srvc + " - Status", 1, "generic_proc")
status = 1
elif srvstatus[1] == "activestate=inactive":
modules += build_module("Service " +srvc+ " - Status", 0, "generic_proc")
status = 0
elif sysctl != 0 and servic == 0:
### Systemd not available, switch to service command
syscall = Popen(["service", srvc, "status"], stdout=PIPE,
stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
result = syscall.communicate()[0].lower()
if "is running" in result:
modules += build_module("Service " + srvc + " - Status", 1, "generic_proc")
status = 1
elif "is stopped" in result:
modules += build_module("Service " +srvc+ " - Status", 0, "generic_proc")
status = 0
else: else:
next next
return kids else:
print("No systemd or service commands available. Exiting...", file=stderr)
@staticmethod exit()
def getstatus(servicename): if status:
"""Gets the status of a given Windows service""" module_list.append(srvc)
running = Popen(["powershell", "Get-Service", "-Name '" + str(servicename) + if memcpu:
"' |", "Select-Object", "-ExpandProperty", "Status"], modules += get_memcpu(srvc, None)
stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
status = running.communicate()[0].strip() for m in modules:
return int(status == "Running") print_module(m, 1)
@staticmethod
def get_serviceprocess(servicename):
"""Gets name of the process of the service"""
service = psutil.win_service_get(servicename)
srv_pid = service.pid()
process = psutil.Process(srv_pid)
proc_name = process.name()
return proc_name
######################################################################################### def build_module(name, value, module_type, parent=None):
# Services creation
#########################################################################################
def service_module(name, value, parent=None):
#print ("service_module BEGIN "+str(now(0,1))) #print ("service_module BEGIN "+str(now(0,1)))
module = [{ module = [{
"name" : "Service "+ name + " - Status", "name" : name ,
"type" : "generic_proc", "type" : module_type,
"value" : value, "value" : value,
"module_parent" : parent, "module_parent" : parent,
}] }]
@ -167,74 +169,6 @@ def proc_percentbyname(procname): ############# 03/03/2020
next next
#print ("proc_percentbyname END "+str(now(0,1))) #print ("proc_percentbyname END "+str(now(0,1)))
return [sum(memory),sum(cpu)] return [sum(memory),sum(cpu)]
def win_service(servicelist, option=False, memcpu=False):
"""Creates modules for Windows servers."""
modules = []
for srvc in servicelist:
if srvc and len(srvc) > 2:
output = PSCheck.check_service(srvc, option, memcpu)
if output is not None and output["modules"]:
modules += PSCheck.check_service(srvc.strip(), option, memcpu)["modules"]
module_list.append(srvc)
#winprocess = output["name"]
#if memcpu == True:
# modules += get_memcpu(winprocess) ## Only available for parent service ATM.
else:
next
else:
next
for module in modules:
print_module(module, 1)
def lnx_service(services_list, memcpu=False):
"""Creates modules for Linux servers"""
modules = []
sysctl = getstatusoutput("command -v systemctl")[0]
servic = getstatusoutput("command -v service")[0]
for srvc in services_list:
status = None
if sysctl == 0:
### Systemd available
syscall = Popen(["systemctl", "show", "-pLoadState", "-pActiveState", srvc], stdout=PIPE,
stdin=DEVNULL, universal_newlines=True)
result = syscall.communicate()
srvstatus = result[0].strip().lower().split("\n")
if srvstatus[0] == "loadstate=not-found":
next
else:
if srvstatus[1] == "activestate=active":
modules += service_module(srvc, 1)
status = 1
elif srvstatus[1] == "activestate=inactive":
modules += service_module(srvc, 0)
status = 0
elif sysctl != 0 and servic == 0:
### Systemd not available, switch to service command
syscall = Popen(["service", srvc, "status"], stdout=PIPE,
stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
result = syscall.communicate()[0].lower()
if "is running" in result:
modules += service_module(srvc, 1)
status = 1
elif "is stopped" in result:
modules += service_module(srvc, 0)
status = 0
else:
next
else:
print("No systemd or service commands available. Exiting...", file=stderr)
exit()
if status:
module_list.append(srvc)
if memcpu:
modules += get_memcpu(srvc, None)
for m in modules:
print_module(m, 1)
######################################################################################### #########################################################################################
# print_module function # print_module function
######################################################################################### #########################################################################################
@ -356,6 +290,7 @@ def main():
service_list = ["MySQL", "postgresql", "pgsql", "oracle", "MSSQL", "IISADMIN", service_list = ["MySQL", "postgresql", "pgsql", "oracle", "MSSQL", "IISADMIN",
"apache", "nginx", "W3svc", "NTDS", "Netlogon", "DNS", "MSExchangeADTopology", "apache", "nginx", "W3svc", "NTDS", "Netlogon", "DNS", "MSExchangeADTopology",
"MSExchangeServiceHost", "MSExchangeSA", "MSExchangeTransport"] "MSExchangeServiceHost", "MSExchangeSA", "MSExchangeTransport"]
discover(OS, service_list) discover(OS, service_list)
elif psutil.LINUX: elif psutil.LINUX:
OS = "Linux" OS = "Linux"