From 44581289e808a7b02e68e74e9520b309a13edacf Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Wed, 5 Oct 2022 12:19:40 -0500 Subject: [PATCH] Use python re to parse service output instead of grep (#79015) * Use python re to parse service output instead of grep. Fixes #78541 * Add clog frag * Add an extra guard to abort if rc is 4, and /etc/init.d is missing --- .../fragments/78541-service-facts-re.yml | 3 +++ lib/ansible/modules/service_facts.py | 20 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/78541-service-facts-re.yml diff --git a/changelogs/fragments/78541-service-facts-re.yml b/changelogs/fragments/78541-service-facts-re.yml new file mode 100644 index 00000000000..b96d5842466 --- /dev/null +++ b/changelogs/fragments/78541-service-facts-re.yml @@ -0,0 +1,3 @@ +bugfixes: +- service_facts - Use python re to parse service output instead of grep + (https://github.com/ansible/ansible/issues/78541) diff --git a/lib/ansible/modules/service_facts.py b/lib/ansible/modules/service_facts.py index 362e3b1d560..d2fbfad3cfe 100644 --- a/lib/ansible/modules/service_facts.py +++ b/lib/ansible/modules/service_facts.py @@ -89,6 +89,7 @@ ansible_facts: ''' +import os import platform import re from ansible.module_utils.basic import AnsibleModule @@ -104,16 +105,19 @@ class BaseService(object): class ServiceScanService(BaseService): def _list_sysvinit(self, services): - - rc, stdout, stderr = self.module.run_command("%s --status-all 2>&1 | grep -E \"\\[ (\\+|\\-) \\]\"" % self.service_path, use_unsafe_shell=True) + rc, stdout, stderr = self.module.run_command("%s --status-all" % self.service_path) + if rc == 4 and not os.path.exists('/etc/init.d'): + # This function is not intended to run on Red Hat but it could happen + # if `chkconfig` is not installed. `service` on RHEL9 returns rc 4 + # when /etc/init.d is missing, add the extra guard of checking /etc/init.d + # instead of solely relying on rc == 4 + return if rc != 0: self.module.warn("Unable to query 'service' tool (%s): %s" % (rc, stderr)) - for line in stdout.split("\n"): - line_data = line.split() - if len(line_data) < 4: - continue # Skipping because we expected more data - service_name = " ".join(line_data[3:]) - if line_data[1] == "+": + p = re.compile(r'^\s*\[ (?P\+|\-) \]\s+(?P.+)$', flags=re.M) + for match in p.finditer(stdout): + service_name = match.group('name') + if match.group('state') == "+": service_state = "running" else: service_state = "stopped"