[systemd-devel] Stop all uninstalled units

Lennart Poettering lennart at poettering.net
Wed Jul 17 16:47:00 PDT 2013


On Wed, 17.07.13 22:14, Tim Cuthbertson (tim at gfxmonk.net) wrote:

> Hi Folks,
> 
> I've posted a serverfault question [0], but it got no answers so I thought
> I'd bring it to the mailing list:
> 
> I have some systemd units installed and running. Let's say I manually
> uninstall foo.service by
> 
>  - removing its .service (and .socket) files
>  - removing all symlinks (e.g from default.target.wants/)
> 
> I can run systemctl daemon-reload, and then I see:
> 
>     # systemctl status foo.service
>     foo.service
>        Loaded: error (Reason: No such file or directory)
>        Active: active (running) since Mon 2013-07-08 13:50:29 EST; 48s ago
>      Main PID: 1642 (node)
> 
> So systemd knows that it's not installed, and that it is running. Is there
> some command I can use to stop all running services which no longer have a
> unit file?
> 
> I do not want to have to somehow know what I've uninstalled, or for the
> command to work only in some circumstances - I want something that I can
> run at any point, with no additional knowledge, that will stop all units
> not backed by a unit file.
> 
> I've currently got a hacky script that:
>  - Runs `list-units` to get all unit names
>  - Then `show -p ActiveState -p UnitFileState $unit` on each
>  - It then runs `systemctl stop` on each unit with a UnitFileState of ""
> (empty string), and ActiveState of anything but "failed".
> 
> This is almost certainly missing some edge case, as I couldn't really find
> any documentation of these properties, it just seemed to be what occurred
> with the examples I encountered.
> 
> I'm hoping there's a better way, can anyone point me in the right direction?
> 
> [0]:
> http://serverfault.com/questions/521504/systemd-stop-all-uninstalled-units

So, the correct way to handle this is to make sure the packages in
question contain the right scriplets that terminate all units they
include before deinstallation. Of course, there'll always be broken
packages like this I fear, hence I can totally see your usecase.

There's currently no nice way to handle this, but what you can do is this:

systemctl --all --type=not-found --type=error

This will list you all units where the load state is either "error" or
"not-found" (note that 'not-found' is available only in very recent
versions, and in older systemd versions was just a special case of
'error'. The command line above works for all versions). The --type=
switch is used to filter unit types, but actually also can be used to
filter for the load state.

Then filter out the first column:

systemctl --no-legend --all --type=not-found --type=error | awk '{ print $1 }'

This will give you a list of unit files which got referenced or started
but have no unit file installed. Then use this to stop the units:

systemctl stop `systemctl --no-legend -all --type=not-found --type=error | awk '{ print $1}'`

And there you go.

Lennart

-- 
Lennart Poettering - Red Hat, Inc.


More information about the systemd-devel mailing list