How get systemd status in json format?
I want to get service status details (Loaded, enabled, active, running, since, Main PID) in machine readable form and I know that systemd tools have --output=json
option, but if I do:
systemctl status servicename --output=json --plain
I see something like:
● snapd.service - Snappy daemon
Loaded: loaded (/lib/systemd/system/snapd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2018-04-16 11:20:07 MSK; 4h 45min ago
Main PID: 738 (snapd)
Tasks: 10 (limit: 4915)
CGroup: /system.slice/snapd.service
└─738 /usr/lib/snapd/snapd
{ "__CURSOR" : "s=461ecb6a4b814913acd57572cd1e1c82;...
Journal records are in JSON. But how to get the service status in JSON if it's possible?
Simple way to getting service status in machine readable form:
systemctl show servicename --no-page
This command outputs data in key=value
format:
Type=notify
Restart=always
NotifyAccess=main
...
If JSON
format is required, you can use the following simple Python script (Python 2 and 3 compatible) get_service_info.py
:
import os, sys, subprocess, json
key_value = subprocess.check_output(["systemctl", "show", sys.argv[1]], universal_newlines=True).split('\n')
json_dict = {}
for entry in key_value:
kv = entry.split("=", 1)
if len(kv) == 2:
json_dict[kv[0]] = kv[1]
json.dump(json_dict, sys.stdout)
Usage:
get_service_info.py servicename
You can use jq
for this, too:
systemctl show --no-page iptables \
| jq --slurp --raw-input \
'split("\n")
| map(select(. != "")
| split("=")
| {"key": .[0], "value": (.[1:] | join("="))})
| from_entries'
produces:
{
"Type": "oneshot",
"Restart": "no",
"NotifyAccess": "none",
"ExecStart": "{ path=/usr/libexec/iptables/iptables.init ; argv[]=/usr/libexec/iptables/iptables.init start ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
[... like 60 more entries ...],
"CollectMode": "inactive"
}
Decode of jq
command:
--slurp - read the whole thing as a really big string
--raw-input - p.s. it's not json input
split("\n") - break the input into an array of lines
map( ... ) - perform some transformation on each array element
select(. != "") - skip blank lines
split("=") - split the current line into array elements at each "="
(.[1:] | join("=")) - avoid mangling values with equal signs
(be warned: this will truncate values if the value itself contains an equals sign. This can probably be worked around but for this purpose seems fine)
{"key": .[0], "value": .[1]} - build an key/value pair object
(at this point map
returns an array of key/value objects)
from_entries - turn an array of "key"/"value" objects into an object
The recommendation by the developers is to use the dbus API for programmatic access to service status instead. If you really need JSON, you could adapt the DBUS API to produce the JSON you need.
See the Github issue --output json doesn't produce json output for discussion among the developers about why the DBUS API is recommended over JSON output.