You are not logged in.

#1 2014-10-20 01:19:23

Gigadoc 2
Member
Registered: 2009-11-14
Posts: 16
Website

Getting machine-readable process list of a systemd unit

Hi,
I realize that this might be a very stupid question, but searches on google and the forums have not yielded me an answer for this simple problem:
I want the process list of a systemd unit - just like systemctl status $unitname does - but in machine-readable output, to look for specific processes.

E.g. instead of this

● session-c43.scope - Session c43 of user gigadoc2
   Loaded: loaded (/run/systemd/system/session-c43.scope; static)
  Drop-In: /run/systemd/system/session-c43.scope.d
           └─50-After-systemd-logind\x2eservice.conf, 50-After-systemd-user-sessions\x2eservice.conf, 50-Description.conf, 50-SendSIGHUP.conf, 50-Slice.conf
   Active: active (running) since Mo 2014-10-20 02:49:53 CEST; 3min 19s ago
   CGroup: /user.slice/user-16776.slice/session-c43.scope
           ├─12894 sshd: gigadoc2 [priv]
           ├─12899 sshd: gigadoc2@pts/1
           ├─12900 -bash
           └─12936 systemctl status session-c43.scope

Okt 20 02:49:53 cappuccino sshd[12894]: Accepted publickey for gigadoc2 from [redacted] port 38955 ss...e:80:a6
Okt 20 02:49:53 cappuccino sshd[12894]: pam_unix(sshd:session): session opened for user gigadoc2 by (uid=0)
Hint: Some lines were ellipsized, use -l to show in full.

I want something like this:

12894 sshd: gigadoc2 [priv]
12899 sshd: gigadoc2@pts/1
12900 -bash
12936 systemctl status session-c43.scope

Or, better yet, this:

sshd
sshd
bash
systemctl

Currently I can think of two methods to achieve this:
Firstly, I could just cut out the middle part of the systemctl status output, and then grep for what I am looking for. However, systemctl status is meant for humans to read and might be subject to change without warning. Also, it is kind of ugly.
The other method would look something like this:

ps -o comm= -p $(tr '\n' , < /sys/fs/cgroup/systemd/"$(systemctl show session-c43.scope --property ControlGroup | cut -d = -f 2-)"/cgroup.procs | sed 's/,$//')

which basically gets the cgroup path from systemctl and then transforms the PIDs to process names using ps and a bunch of other commands. This is ugly as well, and IIRC the way cgroups are exposed trough sysfs will change in the future as well.

So, does anyone know a nicer way to get this kind of output?

Offline

#2 2014-10-21 18:39:28

branch
Member
Registered: 2014-03-16
Posts: 196

Re: Getting machine-readable process list of a systemd unit

This one may not be any less ugly, but it uses cgm from the community/cgmanager package to future proof against sysfs changes.

#!/bin/sh

unit="$1"
cg=$(systemctl show --property ControlGroup "${unit}" | cut -d '=' -f2)
pidlist=$(cgm gettasksrecursive name=systemd "${cg}")
ps -h -o comm --pid ${pidlist}

Note that the cgmanager daemon has to be running for the cgm frontend to work.

Offline

#3 2014-10-22 07:56:12

stoggy
Member
Registered: 2014-10-22
Posts: 2

Re: Getting machine-readable process list of a systemd unit

something like this?

systemctl status session-c43.scope | awk 'BEGIN{CG=0; print""} {if ($1=="CGroup:") CG=1; else if (CG==1) if ($1~/[├└─]/) {gsub(/[├└─]/,"",$1); print;}} END {print""}'

Offline

#4 2014-10-23 01:43:41

Gigadoc 2
Member
Registered: 2009-11-14
Posts: 16
Website

Re: Getting machine-readable process list of a systemd unit

branch wrote:

This one may not be any less ugly, but it uses cgm from the community/cgmanager package to future proof against sysfs changes.

#!/bin/sh

unit="$1"
cg=$(systemctl show --property ControlGroup "${unit}" | cut -d '=' -f2)
pidlist=$(cgm gettasksrecursive name=systemd "${cg}")
ps -h -o comm --pid ${pidlist}

AFAIK, in the future only one daemon will be able to access cgroups, wich, on Arch, will most likely be systemd. As such, I am not sure whether this solution will work "indefinitely" either. It would be better than directly interacting with sysfs, though.

stoggy wrote:

something like this?

systemctl status session-c43.scope | awk 'BEGIN{CG=0; print""} {if ($1=="CGroup:") CG=1; else if (CG==1) if ($1~/[├└─]/) {gsub(/[├└─]/,"",$1); print;}} END {print""}'

This looks like my first solution. It would work for now, but since systemctl status is explicitly designed for human interaction only, the specific formatting might change without warning.

Offline

Board footer

Powered by FluxBB