レナート   Wunschkonzert, Ponyhof und Abenteuerspielplatz   ﻟﻴﻨﺎﺭﺕ

Wed, 02 Mar 2011

systemd for Administrators, Part V

It has been a while since the last installment of my systemd for Administrators series, but now with the release of Fedora 15 based on systemd looming, here's a new episode:

The Three Levels of "Off"

In systemd, there are three levels of turning off a service (or other unit). Let's have a look which those are:

  1. You can stop a service. That simply terminates the running instance of the service and does little else. If due to some form of activation (such as manual activation, socket activation, bus activation, activation by system boot or activation by hardware plug) the service is requested again afterwards it will be started. Stopping a service is hence a very simple, temporary and superficial operation. Here's an example how to do this for the NTP service:

    $ systemctl stop ntpd.service

    This is roughly equivalent to the following traditional command which is available on most SysV inspired systems:

    $ service ntpd stop

    In fact, on Fedora 15, if you execute the latter command it will be transparently converted to the former.

  2. You can disable a service. This unhooks a service from its activation triggers. That means, that depending on your service it will no longer be activated on boot, by socket or bus activation or by hardware plug (or any other trigger that applies to it). However, you can still start it manually if you wish. If there is already a started instance disabling a service will not have the effect of stopping it. Here's an example how to disable a service:

    $ systemctl disable ntpd.service

    On traditional Fedora systems, this is roughly equivalent to the following command:

    $ chkconfig ntpd off

    And here too, on Fedora 15, the latter command will be transparently converted to the former, if necessary.

    Often you want to combine stopping and disabling a service, to get rid of the current instance and make sure it is not started again (except when manually triggered):

    $ systemctl disable ntpd.service
    $ systemctl stop ntpd.service

    Commands like this are for example used during package deinstallation of systemd services on Fedora.

    Disabling a service is a permanent change; until you undo it it will be kept, even across reboots.

  3. You can mask a service. This is like disabling a service, but on steroids. It not only makes sure that service is not started automatically anymore, but even ensures that a service cannot even be started manually anymore. This is a bit of a hidden feature in systemd, since it is not commonly useful and might be confusing the user. But here's how you do it:

    $ ln -s /dev/null /etc/systemd/system/ntpd.service
    $ systemctl daemon-reload

    By symlinking a service file to /dev/null you tell systemd to never start the service in question and completely block its execution. Unit files stored in /etc/systemd/system override those from /lib/systemd/system that carry the same name. The former directory is administrator territory, the latter terroritory of your package manager. By installing your symlink in /etc/systemd/system/ntpd.service you hence make sure that systemd will never read the upstream shipped service file /lib/systemd/system/ntpd.service.

    systemd will recognize units symlinked to /dev/null and show them as masked. If you try to start such a service manually (via systemctl start for example) this will fail with an error.

    A similar trick on SysV systems does not (officially) exist. However, there are a few unofficial hacks, such as editing the init script and placing an exit 0 at the top, or removing its execution bit. However, these solutions have various drawbacks, for example they interfere with the package manager.

    Masking a service is a permanent change, much like disabling a service.

Now that we learned how to turn off services on three levels, there's only one question left: how do we turn them on again? Well, it's quite symmetric. use systemctl start to undo systemctl stop. Use systemctl enable to undo systemctl disable and use rm to undo ln.

And that's all for now. Thank you for your attention!

posted at: 21:45 | path: /projects | permanent link to this entry | 18 comments


Posted by Bender at Wed Mar 2 22:27:55 2011
And people are complaining that systemd will replace sys v. To me it looks as a well thought off init system that will suck less or not at all :) From my greenhorn's point of view this is great and easier to implement everywhere thanks to compatiblity! (right now running systemd on gentoo)

This is great engineering piece of code and i hope it will some day replace upstart in gentoo ;)

And since canonical loves to mooch off others inventions they will change gladly :)

Posted by Bender at Wed Mar 2 22:29:51 2011
Sorry, i meant ubuntu.

Posted by Anonymous at Wed Mar 2 22:59:50 2011
How can you change whether a service starts when the system boots regardless of whether another service requires it, versus starting only when needed?

Related to that, does systemd have any facility for having a service exit when no longer needed?

Posted by Lennart at Wed Mar 2 23:26:43 2011
Anonymous: you can always create and remove your own triggers by adding/removing symlinks in .wants/ directories in /etc/systemd/system. Consult the systemd documentation for details. If you want to start a service at boot you probably want to do something like: ln -sf /lib/systemd/system/foo.service /etc/systemd/system/multi-user.target.wants/foo.service. And if you don't, you just remove that link.

It is in general not possible to determine from the outside if a service is "no longer needed". Only the service itself knows whether a transaction is still going on or a client connected. Hence it must be the service that terminates itself when idle, not systemd from the outside.

However, note that usually exit-on-idle is not a good strategy anyway. It is often cheaper to leave a service running (swapped out) than to stop it. Because when you need it the next time you need to reinitialize fully if it exited, while if you left it running you could just swap it back in. A correctly written daemon just hangs in a poll() without consuming CPU when idle, hence leaving it running swapped out should come relatively cheap.

Posted by Anonymous at Thu Mar 3 00:35:13 2011
Thanks for the information about .wants directories.

Regarding "no longer needed", the first use case that comes to mind comes straight from inetd: done when the connection closes.  That alone applies to many services.  Perhaps throw in a timeout to avoid rapidly starting and stopping the service as requests come in.

Consider distcc, for instance.

Regarding swap, that assumes that the kernel will identify the right process to swap out.  It often seems to want to swap out bits of active processes rather than bits of inactive processes.  And more importantly, the kernel (rightly) doesn't often swap out inactive processes to make room for more cache; it'll usually just do without.

Posted by Lennart at Thu Mar 3 01:01:07 2011
Anonymous: well, the kernel is actually pretty good at identifying processes that just hang in a poll() and do nothing, since those never ever touch a memory page. And even if it doesn't get it right, then this might be incentive to fix the kernel logic, instead of adding workarounds in userspace.

Don't understand me wrong: there are cases where behaviour like you suggest makes sense, but this has to be implemented in the daemons, notin systemd.

Posted by James at Thu Mar 3 03:59:13 2011
Thanks for the writeup-- One comment:

Since the "action" is no longer at the end of the command, it requires extra typing to change and re-run something from your history.

Formerly you could: up-arrow, control-w, then type stop.
[hack, hack hack...]
up-arrow, control-w, type start

Now it's longer. Workaround?

Posted by James at Thu Mar 3 05:13:30 2011
PS: I'm aware of things like: ^stop^start^, which are somewhat annoying to type; i'm mostly just pointing out the change which might make a sysadmin's life 5% more annoying.

Posted by Adam Williamson at Thu Mar 3 06:23:16 2011
"The Three Levels of "Off""

is one of them "Mode Execute Ready"? =)

Posted by Milded at Thu Mar 3 15:59:32 2011
About services stopping on idle, it might get useful in some cases.

For instances, on my laptop, I have MySQL, Apache, PostGreSQL, all for developpment. But I actually don't need them often. I'd like them to stop when I don't need them.

But I agree, only the service can do that.

Posted by Lennart at Thu Mar 3 16:11:35 2011
James: well, but on to other hand if you want to execute the same command for a couple of services it is now easier to do...

Posted by Lennart at Thu Mar 3 16:12:49 2011
Adam: sorry, I don't get the reference...

Posted by James at Fri Mar 4 05:11:09 2011
Lennart: nice dodge! When does that ever happen? My only real use case is when I'm testing/debugging and setting up some service. Thanks for systemd and it's lack of a CLA.

Posted by Bharatt at Mon Mar 14 04:12:48 2011
Hi Lennart,

Is there any equivalent command in systemd for,

# chkconfig --level 35 <service_name> <on|off>

Have seen in this post that we can "enable" or "disable" a service.
Do we have an option to do it for particular runlevels?

Thanks

Posted by Lennart at Mon Mar 14 20:40:56 2011
Bharatt: we don't really have runlevels anymore in systemd. If you want to hook your stuff into particular triggers you can easily do this by calling "ln -s" manually. That's much less cumbersome than with SysV.

Posted by Daniel at Sat Mar 26 16:51:59 2011
I am trying to figure out how to start services in multi-user (old runlevel 3) but not have them started in graphical (old runlevel 5).

I have 4 services that I want to start only when in multi-user but I do not want them started when I boot into graphical.

Is there a way to do this?

Using the older sysvinit method, I could just drop them into the runlevel 3 without putting them in runlevel 5 and it worked.

How do I accomplish this with systemd?

Posted by Lennart at Tue Mar 29 19:13:08 2011
Daniel: in systemd graphical.target is a superset of multi-user.target by default. The former pulls in the latter. For the vast majority of set-ups this is what people want. If you really want to start more in multi-user than in graphical please copy /lib/systemd/system/graphical.target to /etc/systemd/system/graphical.target and edit it there. Drop the lines that pull in multi-user-target. Then you can organize what is started yourself, simply by placing or removing symlinks in /etc/systemd/system/graphical.target.wants/ and /etc/systemd/system/multi-user.target.wants/.

Posted by Matt at Fri Apr 22 23:35:43 2011
i'm working on a machine running systemd and I'm editing oblogout.conf to support proper shutdown/restart/suspend/hibernate support.  Previously, these were implemented using dbus-send, with a destination of either ConsoleKitManager or UPower.  How would this be done properly and securely under systemd?  I want the users to be able to shutdown the computer, but I don't want them to be able to do any direct service manipulation.

Leave a Comment:

Your Name:


Your E-mail (optional):


Comment:


As a protection against comment spam, please type the following number into the field on the right:
Secret Number Image

Please note that this is neither a support forum nor a bug tracker! Support questions or bug reports posted here will be ignored and not responded to!


It should be obvious but in case it isn't: the opinions reflected here are my own. They are not the views of my employer, or Ronald McDonald, or anyone else.

Please note that I take the liberty to delete any comments posted here that I deem inappropriate, off-topic, or insulting. And I excercise this liberty quite agressively. So yes, if you comment here, I might censor you. If you don't want to be censored your are welcome to comment on your own blog instead.


Lennart Poettering <mzoybt (at) 0pointer (dot) net>
Syndicated on Planet GNOME, Planet Fedora, planet.freedesktop.org, Planet Debian Upstream. feed RSS 0.91, RSS 2.0
Archives: 2005, 2006, 2007, 2008, 2009, 2010, 2011

Valid XHTML 1.0 Strict!   Valid CSS!