There are various command-line tools to make dbus calls; systemd comes with one called busctl
. So you can call StartTransientUnit
from the command line.
The command
The syntax is positively annoying, but it looks like this (for one process id, 14460):
busctl call --user org.freedesktop.systemd1 /org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
'SCOPE-NAME.scope' fail 1 PIDs au 1 14460 0
Explanation
That is positively opaque (and took some tries to get right, and ultimately using dbus-monitor
to see how systemd-run
did it — only on the system manager though, systemd-run --user
seems not to go through dbus). So an explanation, parameter by parameter:
busctl call --user # use user session dbus, not system
org.freedesktop.systemd1 # dbus service name
/org/freedesktop/systemd1 # dbus object in that service
org.freedesktop.systemd1.Manager # interface name in that service
StartTransientUnit # method we're going to call
'ssa(sv)a(sa(sv))' # signature of method, see below
'SCOPE-NAME.scope' # first argument, name of scope
fail # second argument, how to handle conflicts (see below)
1 # start of third argument, number of systemd properties for unit
PIDs # name of first property
au # data type of first property, (a)rray [aka list] of (u)nsigned integers
1 # count of array — that is, number of pids
14460 # first pid
0 # fourth argument: array size=0 (unused parameter)
Adding to the command
More properties
To add another systemd property to the unit, you'd increase the number of properties and add it on. Note that each property is at least three additional command-line arguments: the key, the value-type, and the value. As an example, adding a Slice property would go from:
… fail 1 PIDs au 1 14460 0
to
… fail 2 PIDs au 1 14460 Slice s whatever.slice 0
^ ^^^^^ ^ ^^^^^^^^^^^^^^
count key type value
Type "s" is string. The list of them can be found in the D-Bus specification’s “Type system" chapter
You can of course change the count to 3 and add a third property. Etc.
More pids
Similar to more properties, but this time it's the count buried inside the "PIDs" property value. An example should make it clearer:
… fail 1 PIDs au 1 14460 0
becomes
… fail 1 PIDs au 2 14460 14461 0
^ ^^^^^
internal count second pid
if you add PID 14461 as well as 14460.
You can add a third, fourth, etc. PID in the same way.
Combining them
You can of course combine additional properties with additional pids. Just remember that the list of pids is a property value, so it needs to stay together. You can't mix pid arguments with other properties. The right way is to change:
… fail 1 PIDs au 1 14460 0
to:
… fail 2 PIDs au 2 14460 14461 Slice s whatever.slice 0
(the order doesn't matter, you could put the Slice block before the PIDs block).
Where does the signature come from?
The signature is obtained either from the systemd dbus API documentation or, probably more easily, by using dbus introspection:
$ busctl introspect org.freedesktop.systemd1 /org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager | grep1 StartTransientUnit
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.StartTransientUnit method ssa(sv)a(sa(sv)) o -
(for grep1
, see https://unix.stackexchange.com/a/279518)
There are a lot of methods and dbus-properties listed, over 180 here. So don't omit the grep
.
What does “fail” handling conflicts mean? What else is there?
According to the systemd documentation (look under "CreateUnit"), the useful values are fail
and replace
. fail
means your scope will fail to start if there is some conflict. replace
means systemd will get rid of the conflicting unit. Note that this seems to only be for units that are currently starting or scheduled to (it does say "queued") — replace won't, for example, replace an already-running scope with the same name.