#! /usr/bin/python3
import os
class ServiceReport:
def __init__(self):
self.services = []
self.all_services = []
self.stopped_services = []
self.running_services = []
self.srvc_cmd = "service --status-all &> /dev/null"
self.set_services()
self.extract_services()
def set_services(self):
self.services = os.popen(self.srvc_cmd)
def get_all_services(self):
return self.all_services
def get_running_services(self):
return self.running_services
def get_stopped_services(self):
return self.stopped_services
def running_services_count(self):
return len(self.running_services)
def stopped_services_count(self):
return len(self.stopped_services)
def all_services_count(self):
return len(self.all_services)
def extract_services(self):
for service in sorted(self.services):
self.all_services.append(service[8:-1])
if "+" in service:
self.running_services.append(service[8:-1])
else:
self.stopped_services.append(service[8:-1])
if __name__ == "__main__":
sr = ServiceReport()
print("\n" + str(sr.all_services_count()) + " services are available")
for x in sr.get_all_services():
print(x)
print("\n" + str(sr.running_services_count()) + " services are running")
for y in sr.get_running_services():
print(y)
print("\n" + str(sr.stopped_services_count()) + " services are stopped")
for z in sr.get_stopped_services():
print(z)
I would rather return a sequence of small Service objects for such a program, because Python is very strong at manipulating collections and I think it opens more flexible possibilities. Here is a proposal
from collections import namedtuple
import os
class Service(namedtuple('Service', 'name status')):
__slots__ = ()
def is_running(self):
return self.status == '+'
def is_stopped(self):
return self.status == '-'
def has_no_status(self):
return self.status == '?'
def service_status_all():
for line in os.popen("service --status-all &> /dev/null"):
_, status, _, name = line.strip().split()
yield Service(name, status)
if __name__ == '__main__':
services = list(service_status_all())
print("{} services are available".format(len(services)))
for x in services:
print(x.name)
running = [s for s in services if s.is_running()]
print()
print("{} services are running".format(len(running)))
for y in running:
print(y.name)
stopped = [s for s in services if s.is_stopped()]
print()
print("{} services are stopped".format(len(stopped)))
for y in stopped:
print(y.name)
Ah I like the yield keyword. I actually attempted to use that as the service command seems to gradually output the services. I couldn’t get it to work. I’m glad you posted that to see how to return an iterator correctly
Just out of curiosity... I noticed that you used the "?" in case of no status... does the output of service --status-all on your machine give a service/status that does not have a [+] or a [-]?
(Aug-26-2018, 01:32 AM)rootVIII Wrote: [ -> ]does the output of service --status-all on your machine give a service/status that does not have a [+] or a [-]?
They all have
[ + ]
or
[ - ]
, however
man service
indicates
Quote: service --status-all runs all init scripts, in alphabetical order, with the status
command. The status is [ + ] for running services, [ - ] for stopped services and
[ ? ] for services without a 'status' command. This option only calls status for
sysvinit jobs; upstart jobs can be queried in a similar manner with initctl list.
It could be a good idea to parse more seriously the lines of output in case the syntax of
service --status-all
changes. The re module can be used for this. Also the command can be made a classmethod of the Service class, which would allow further code to subclass the Service class
from collections import namedtuple
import os
import re
class Service(namedtuple('Service', 'name status')):
__slots__ = ()
def is_running(self):
return self.status == '+'
def is_stopped(self):
return self.status == '-'
def has_no_status(self):
return self.status == '?'
@classmethod
def iterate_all(cls):
for line in os.popen("service --status-all &> /dev/null"):
match = re.match(
r"\[\s*(?P<status>[-+?])\s*\]\s*(?P<name>[^\s].+)", line.strip())
if not match:
raise ValueError(('Unknown service status syntax:', line))
yield cls(match.group('name'), match.group('status'))
if __name__ == '__main__':
for service in Service.iterate_all():
print(service)