Discussion:
"libsystemdexec/systemd-run --exec-from-unit"
Add Reply
Colin Walters
2017-01-29 06:56:35 UTC
Reply
Permalink
Raw Message
Hey so, this is is a half-baked thought, but here goes:

One problem I've hit when trying to use systemd unit file
features is that they only work when executed by systemd.
Let's take the example of User=, but it applies to tons of
other ones too.

Wait you ask - your service runs under systemd, why
do you care about running it not under systemd? The
main case I hit is I often want to run my service
under a debugger.

If I just do gdb /usr/lib/myservice ... it will run as root.
Now of course, I could runuser myservice gdb --args /usr/lib/myservice.
But as a unit file gains more features, from WorkingDirectory
to ProtectSystem=, I find myself wanting something like:

systemd-run --exec-from-unit myservice.service /path/to/myservice/src/myservice

Basically exec an uninstalled copy from the builddir. Or alternatively,
do a `sudo make install` type thing and:

systemd-run --exec-from-unit myservice.service --execstart-args gdb --args

Has anyone else hit this? Am I missing something obvious?

Taking this out a little bit, I could imagine having the systemd unit -> execprep
as a shared library. This would make it easier to use inside daemon
code itself. This solves a few scenarios like having the service itself
spawn helper processes that don't quite fit into the template model.
Reindl Harald
2017-01-29 12:59:54 UTC
Reply
Permalink
Raw Message
Post by Colin Walters
One problem I've hit when trying to use systemd unit file
features is that they only work when executed by systemd.
Let's take the example of User=, but it applies to tons of
other ones too.
Wait you ask - your service runs under systemd, why
do you care about running it not under systemd? The
main case I hit is I often want to run my service
under a debugger.
If I just do gdb /usr/lib/myservice ... it will run as root.
Now of course, I could runuser myservice gdb --args /usr/lib/myservice.
But as a unit file gains more features, from WorkingDirectory
systemd-run --exec-from-unit myservice.service /path/to/myservice/src/myservice
what you really want is something like this (that's wat dropins below
/etc/systemd/ are for to not touch the unit itself) supported by gdb
because using valgrind within a systemd unit works for many years and
the same for strace and a logfile output

i never understodd why taht stupid gdb always ends in interactive mode
instead "if thee is some crash write backtraces to file xyz and shut up"

ExecStart=/usr/bin/valgrind --tool=memcheck --leak-check=yes
--log-file=/var/log/valgrind/imapd.log /usr/sbin/dbmail-imapd -D
Lennart Poettering
2017-02-06 19:22:48 UTC
Reply
Permalink
Raw Message
One problem I've hit when trying to use systemd unit file features
is that they only work when executed by systemd. Let's take the
example of User=, but it applies to tons of other ones too.
Wait you ask - your service runs under systemd, why do you care
about running it not under systemd? The main case I hit is I often
want to run my service under a debugger.
If I just do gdb /usr/lib/myservice ... it will run as root. Now of
course, I could runuser myservice gdb --args /usr/lib/myservice.
But as a unit file gains more features, from WorkingDirectory to
systemd-run --exec-from-unit myservice.service /path/to/myservice/src/myservice
Basically exec an uninstalled copy from the builddir. Or alternatively,
systemd-run --exec-from-unit myservice.service --execstart-args gdb --args
Has anyone else hit this? Am I missing something obvious?
Taking this out a little bit, I could imagine having the systemd unit -> execprep
as a shared library. This would make it easier to use inside daemon
code itself. This solves a few scenarios like having the service itself
spawn helper processes that don't quite fit into the template model.
Well, that would require us to duplicate much of the execution context
setup in this tool. And that's harder than it sounds, since we inherit
a lot of different bits from PID 1 which is much harder to do if you
are not a child of PID 1...

Since the usecase for this is debugging, I wonder if it would be
better to go the other way: provide a way how you can start a unit as
usual, but make systemd wait for a debugger to attach immediately
before executing the actual daemon binary. Then, we could provide a
tool "systemd-gdb" or so, which uses this for spawning a service and
immediately attaches to it by invoking gdb with the right command line
parameters.

This way you'd have the big benefit that what you debug is as close as
possible to what happens without debugging as it possibly could get.

I figure this could relatively easily be implemented by implementing a
new job mode "debug" or so, which would have the effect that any unit
started like this would simply raise SIGSTOP right before execve().

(But if we have that we could even build on that, and turn off the
watchdog logic when this is used, since it fucks up all good
debugging).

Lennart
--
Lennart Poettering, Red Hat
Loading...