Skip to content

Instantly share code, notes, and snippets.

@paulc
Last active April 8, 2021 22:16
Show Gist options
  • Save paulc/67bba5a153b549f8f3f8c8318ddbff3b to your computer and use it in GitHub Desktop.
Save paulc/67bba5a153b549f8f3f8c8318ddbff3b to your computer and use it in GitHub Desktop.
Simple 'launchctl list' parser
#!/usr/bin/env python3
import pprint,re,subprocess,sys
#
# Simple parser for 'launchctl list <service>' output
#
# This works for simple outputs (which is true in most cases) but will fail for
# complex outputs - in particular nested arrays/dicts
#
LAUNCHCTL_RE = re.compile(r'''
"(\S*?)"\s+=\s+"(.*?)";$ # "key" = "<string>";
|
"(\S*?)"\s+=\s+(\d+?);$ # "key" = <int>;
|
"(\S*?)"\s+=\s+(true|false);$ # "key" = <bool>;
|
"(\S*?)"\s+=\s+(\S+);$ # "key" = <literal>;
|
"(\S*?)"\s+=\s+\((.*?)\);$ # "key" = ( <array>... );
|
"(\S*?)"\s+=\s+\{(.*?)\};$ # "key" = { <dict>... };
''',
re.MULTILINE|re.DOTALL|re.VERBOSE)
def parse_launchctl_re(m):
(s_key,s_val,i_key,i_val,b_key,b_val,l_key,l_val,a_key,a_val,d_key,d_val) = m
if s_key:
return (s_key,s_val)
elif i_key:
return (i_key,int(i_val))
elif b_key:
return (b_key,b_val == 'true')
elif l_key:
return (l_key,l_val)
elif a_key:
return (a_key,re.findall(r'"(.*?)";',a_val))
elif d_key:
return (d_key,dict([parse_launchctl_re(m) for m in re.findall(LAUNCHCTL_RE,d_val)]))
def launchctl_status(service):
status = subprocess.run(("/bin/launchctl","list",service),capture_output=True)
if status.returncode != 0:
raise ValueError(status.stderr.decode().strip())
else:
return dict([parse_launchctl_re(m) for m in LAUNCHCTL_RE.findall(status.stdout.decode())])
if __name__ == '__main__':
try:
service = sys.argv[1]
pprint.pprint(launchctl_status(service))
except IndexError:
print(f"Usage: {sys.argv[0]} <service>")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment