Como obter o status do systemd no formato json?

4

Eu quero obter detalhes do status do serviço (Carregado, ativado, ativo, em execução, desde, PID principal) em formato legível por máquina e sei que as ferramentas systemd têm a opção --output=json , mas se eu o fizer:

 systemctl status servicename --output=json --plain

Eu vejo algo como:

● 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;...

Os registros do diário estão em JSON. Mas como obter o status do serviço no JSON se for possível?

    
por Stanislav Ivanov 16.04.2018 / 15:23

3 respostas

5

Maneira simples de obter o status do serviço em formato legível por máquina:

systemctl show servicename --no-page

este comando faz a saída em key=value format:

Type=notify
Restart=always
NotifyAccess=main
...

Se for necessário o formato json, você pode usar um script python simples (python 2 e 3 comatable) 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)

Uso:

get_service_info.py servicename
    
por 19.04.2018 / 12:11
3

Você também pode usar jq para isso:

systemctl show --no-page iptables \
    | jq --slurp --raw-input \
        'split("\n")
        | map(select(. != "") 
        | split("=") 
        | {"key": .[0], "value": (.[1:] | join("="))})
        | from_entries'

produz:

{
  "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"
}

Decodificar o comando jq :

--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

(seja avisado: isto irá truncar valores se o próprio valor contiver um sinal de igual. Isso provavelmente pode ser contornado, mas para este propósito parece bem)

{"key": .[0], "value": .[1]}  - build an key/value pair object

(neste momento, map retorna uma matriz de objetos chave / valor)

from_entries - turn an array of "key"/"value" objects into an object
    
por 20.06.2018 / 00:04
1

A recomendação dos desenvolvedores é usar a API dbus para acesso programático ao status do serviço. . Se você realmente precisa de JSON, você pode adaptar a API DBUS para produzir o JSON que você precisa.

Veja a questão do Github output json não produz saída do json para discussão entre os desenvolvedores sobre o porquê a API DBUS é recomendada sobre a saída JSON.

    
por 16.04.2018 / 16:44

Tags