pages tagged systemdyakkinghttp://yakking.branchable.com/tags/systemd/yakkingikiwiki2017-05-31T12:00:13ZComplications arising from having a complex inithttp://yakking.branchable.com/posts/complexity-in-systemd/Richard Maw2017-05-31T12:00:13Z2017-05-31T12:00:05Z
<p>Useful, secure, finished. Pick two.</p>
<p>I've just spent a long time writing
about how <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> is the solution
to all your process management reliability woes.</p>
<p>As with everything though,
as I've alluded to in the subtitle,
there are trade-offs.</p>
<h2>What's the catch?</h2>
<p>It is arguable that increasing the responsibilities for <a href="https://en.wikipedia.org/wiki/Init">init</a>,
historically a very simple daemon,
is a dangerous thing to do.</p>
<p>I believe these changes have been warranted,
since the traditional UNIX process model
assumes processes are well-written and benign.</p>
<h3>Security updates</h3>
<p>To accommodate the changing world,
<a href="https://en.wikipedia.org/wiki/Init">init</a> is now sufficiently complicated that it requires security updates.</p>
<p>This is a problem because you can only have one <a href="https://en.wikipedia.org/wiki/Init">init</a> process,
so you can't just kill the old version and start a new one.</p>
<p><a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> has to work around this by re-executing <code>/sbin/init</code>
when it, or any of its dependent libraries, have been updated.</p>
<p>This mechanism should not be relied upon,
since it can fail and if it does fail recovery requires a reboot,
so if you need to be prepared to reboot on update,
why not just reboot the system when an update is required?</p>
<h3>Rebooting woes</h3>
<p>Rebooting is also further complicated by <a href="https://en.wikipedia.org/wiki/Init">init</a> being extended.</p>
<p>If a library that a process depends on is removed as part of an update
then the running process may keep a copy of it open
until the process re-executes or terminates.</p>
<p>This means file systems will refuse to be remounted as read-only
until the process stops using certain files.
This is hugely problematic if the filesystem is the root file system
and the process is init,
since init will want to remount the file system before terminating
and the file system will want init to terminate before remounting.</p>
<p>Previously the approach would be to shut-down
without remounting the file system read-only,
but this doesn't cleanly unmount the file system
so was a source of file system corruption.</p>
<p>The solution to this employed by <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a>
is for the init process to execute a <a href="https://www.freedesktop.org/software/systemd/man/systemd-halt.service.html">systemd-shutdown</a> binary.</p>
<h2>So why not move the complicated bits out of PID 1?</h2>
<p>PID 1 is complex, and this is a problem.
Therefore either <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a>'s developers don't consider the problems important
or there are good reasons why it can't be otherwise.</p>
<p>So, what responsibilities does PID 1 have,
and why do they have to be in PID 1?</p>
<h3>Process reaping</h3>
<p>When a process terminates before reaping its child subprocesses,
all those subprocesses are adopted by PID 1,
which is then responsible for reaping them.</p>
<p><code>PR_SET_CHILD_SUBREAPER</code> was added to <a href="http://man7.org/linux/man-pages/man2/prctl.2.html">prctl(2)</a>
which allows a different process subreaper in the process hierarchy,
so that gets to reap orphaned subprocesses instead of PID 1.</p>
<p>However PID 1 still neads to be able to reap subreapers,
so PID 1 needs the same reaping logic,
and both implementations need to be either shared or maintained,
at which point it's less difficult to just rely on PID 1 doing it.</p>
<p>Traditional init systems perform this function,
so it is not controversial for <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> to perform this.</p>
<h3>Spawning processes</h3>
<p>There are no special requirements necessary to spawn subprocesses,
so a separate process could be started to spawn subprocesses.</p>
<p>Unfortunately this has the same bootstrapping problem,
where PID 1 needs the same logic for starting its helpers
as needs to be used for arbitrary code in the rest of the system.</p>
<p>Traditional init systems perform this function,
so it is not controversial for <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> to perform this.</p>
<h3>Managing cgroups</h3>
<p>Because processes can't be trusted to not escape,
<a href="https://en.wikipedia.org/wiki/Cgroups">cgroups</a> are required to contain them.</p>
<p>A single process is required to manage them.</p>
<p>If services started by init are to be contained by cgroups,
then the cgroup management service
must either be the init process
or must be started by the init process
and have special logic to contain itself first.</p>
<p>This is tractable, but if it's a separate process,
then some form of IPC is required,
which adds extra latency, complexity and points of failure.</p>
<p>A similar concern exists in the form of <a href="https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html">journald</a>,
which is a separate service that <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> needs to communicate with
to get it to log the output of new services to a file.</p>
<p>This complexity already causes <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> trouble,
as a crashing <a href="https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html">journald</a> can bring the whole system to a halt,
so similar complications should be avoided.</p>
<h3>Communicating via <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a></h3>
<p>The init process needs some form of IPC to instruct it to do things.</p>
<p>Historically this was just <code>telinit</code>
writing to the <code>/dev/initctl</code> FIFO,
so was a pretty trivial form of IPC.</p>
<p>However we've established that init now requires new responsibilities,
so requires a much richer form of IPC.</p>
<p>Rather than inventing some bespoke IPC mechanism,
<a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> uses <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a>.</p>
<p><a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> also participates in the system bus,
once the <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a> daemon has been started,
which adds extra complexity since the <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a> daemon is started by <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a>.</p>
<p>This is handled by <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> also handling point-to-point <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a>,
though attempts have been made to move <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a> into the kernel
in the form of <a href="https://lwn.net/Articles/504970/">AF_BUS</a>, <a href="https://www.freedesktop.org/wiki/Software/systemd/kdbus/">kdbus</a> and most recently <a href="http://www.bus1.org/">bus1</a>,
and there has also been discussion
of whether <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> should be a <a href="https://www.freedesktop.org/wiki/Software/dbus/">DBus</a> daemon
to break this circular dependency.</p>
<h1>Summary</h1>
<p>The traditional UNIX process model wasn't designed to support a complex init,
because it assumed that programs would be benign and well written.</p>
<p>Because you can't trust processes to clean up after themselves properly
you need to make init more complicated to cope with it.</p>
<p>Because init is complicated it needs to be able to be updated.</p>
<p>Because the UNIX process model doesn't have a way to safely replace init
you have to allow for it failing and needing a reboot,
so you can't safely perform live updates.</p>
<p>Alternative ways of structuring init would make it even more complex
so more opportunity for things to go wrong.</p>
Is your process running 4 - Linux-specific approacheshttp://yakking.branchable.com/posts/procrun-4-linux/Richard Maw2017-05-10T12:00:12Z2017-05-10T12:00:06Z
<p>We previously discussed the traditional UNIX mechanisms for service management,
and how they assumed benign and well written software.</p>
<p>Fortunately Linux provides more than just traditional UNIX system calls,
so offers some features that can be used to track processes more completely.</p>
<h1>Intercepting processes with <a href="http://man7.org/linux/man-pages/man2/ptrace.2.html">ptrace(2)</a></h1>
<p>If you could run some code when a process creates a subprocess or exits
then you could use this to track which processes are active
and where they came from.</p>
<p>Debuggers like <a href="http://man7.org/linux/man-pages/man1/gdb.1.html">gdb(1)</a> also need to know this information
since you might want to set a breakpoint for subprocesses too.</p>
<p>So it would be possible to do this using the same mechanism as debuggers.</p>
<p>This is what <a href="http://upstart.ubuntu.com/">Upstart</a> does to work out which process to track
for double-forking daemons.</p>
<p>Unfortunately a process cannot be traced by multiple processes,
so if <a href="http://upstart.ubuntu.com/">Upstart</a> is tracing a process to track its subprocesses
then a debugger cannot be attached to the process.</p>
<p>For <a href="http://upstart.ubuntu.com/">Upstart</a> it detaches the debugger after it has worked out the main PID,
so it's a small window where it is undebuggable,
so it's only a problem for debugging faults during startup,
but detaching after the double-fork means
it can't trace any further subprocesses.</p>
<p>Continuing to trace subprocesses adds a noticeable performance impact though,
so it's for the best that it stops tracing after the double-fork.</p>
<h1>Store process in a <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a></h1>
<p><a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a> are a Linux <a href="https://en.wikipedia.org/wiki/Virtual_file_system">virtual filesystem</a>
that lets you create hierarchies to organise processes,
and apply resource controls at each level.</p>
<p><a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a> were created to handle the deficiency
of traditional UNIX resource control system calls
such as <a href="http://man7.org/linux/man-pages/man2/setrlimit.2.html">setrlimit(2)</a>,
which only apply to a single process
and can be thwarted by creating subprocesses,
since while a process inherits limits of its parent process
it does not share them with it.</p>
<p>Subprocesses of a process in a <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a> on the other hand
are part of the same <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a> and share the same resource limits.</p>
<p>In each <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a> directory there is a <code>cgroup.procs</code> virtual file,
which lists the process IDs of every process in the <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a>,
making it effectively a kernel-maintained PIDfile.</p>
<p>This is what <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> uses for its services,
and you can request a <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroup</a> for your own processes
by asking <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> (via <a href="http://man7.org/linux/man-pages/man1/systemd-run.1.html">systemd-run(1)</a> or the DBus interface)
or <a href="https://linuxcontainers.org/cgmanager/introduction/">cgmanager</a> (via <a href="http://manpages.ubuntu.com/manpages/yakkety/man1/cgm.1.html">cgm(1)</a> or the DBus interface)
to do so on your behalf.</p>
<h2>Why can't I mount my own cgroupfs?</h2>
<p>Unfortunately you can only safely have 1 process using a cgroup tree at a time,
and you can only have one cgroupfs mounted at a time,
so you always need to ask some daemon to manage cgroups on your behalf.</p>
<p>See <a href="https://lwn.net/Articles/555920">Changes coming for systemd and control groups</a>
for why a single writer and a single hierarchy are required.</p>
<h1>Conclusion</h1>
<p>It is necessary to track all the subprocesses of a service somehow,
using <a href="http://man7.org/linux/man-pages/man2/ptrace.2.html">ptrace(2)</a> prevents it being used for debugging,
<a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a> are an interface designed for this purpose
but technical limitations mean you need to ask another service to do it.</p>
<p>So I would recommend writing a <a href="https://www.freedesktop.org/software/systemd/man/systemd.service.html">systemd service</a>
if your processes are a per-system or per-user service,
or to use the <a href="https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/#theapis">DBus API</a> to create <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a> if not.</p>
<p>Thus <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a> allow us to know our processes are running,
and currently the best way to use cgroups is via <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a>.
The implications of relying on <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> to do this
are best served as a subject of another article.</p>
<p>If you are interested in learning more about <a href="http://man7.org/linux/man-pages/man7/cgroups.7.html">cgroups</a>,
I recommend reading <a href="https://lwn.net/Articles/604609/">Neil Brown's excellent series on LWN
</a>.</p>
Is your process running 2 - Nobody does pidfiles righthttp://yakking.branchable.com/posts/procrun-2-pidfiles/Richard Maw2017-04-19T11:20:36Z2017-04-19T11:20:30Z
<p>Previously we lamented that we had to read the <code>cmdline</code> for every process
to work out whether the program we want to run is already running,
and that we'd like to be able to look up a name to see if it's running.</p>
<p>The traditional way to do this
is to write the <a href="https://en.wikipedia.org/wiki/Process_identifier">process identifier (or PID)</a>
to a file called named after your program,
such as <code>/var/run/$PROGNAME.pid</code>.</p>
<p>This is an obvious solution, that you will probably have seen before,
and before <a href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</a> and <a href="http://upstart.ubuntu.com/">upstart</a> became popular,
was <em>the</em> way you handled running services in Linux.</p>
<h1>How people do pid files wrong</h1>
<p>On the surface just writing the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> looks like a good idea,
since you can use the presence of the file to tell that the process is running
or read the contents of the file to see which <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> it's using
so you can <a href="http://man7.org/linux/man-pages/man2/kill.2.html">kill(2)</a> the process.</p>
<p>This however is less reliable than parsing files in <a href="http://man7.org/linux/man-pages/man5/proc.5.html">procfs</a>,
since if you're reading from <code>/proc</code> you know it's <em>always</em> up to date
since it's provided by the kernel's process table.</p>
<p>There are no such guarantees from the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> file.
Your process could terminate abnormally and not clean it up.</p>
<p>Be extra cautious with <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> files not stored in <code>/run</code> or <code>/var/run</code>,
since there is no guarantee that they weren't left over from a previous boot.</p>
<p>Reliability can be improved
by checking whether the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> from the file is in use,
by running <a href="http://man7.org/linux/man-pages/man2/kill.2.html">kill</a><code>(pid, 0) == 0</code> in C,
or <a href="http://man7.org/linux/man-pages/man1/kill.1.html">kill</a><code>-0 $pid</code> in shell,
since this will evalutate to true if that process is running.</p>
<p>This is not yet reliable though,
since while killing with signal 0 will tell you
whether a process with that <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> is running,
you can't tell if it's the <em>correct</em> process,
since <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a>s get reused fairly frequently.</p>
<p>For <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> files to be reliable
you need some way to guarantee that the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> in the file
is actually referring to the correct process.</p>
<p>You need some way of tying the lifetime of the process to the file.</p>
<p>When a process terminates all the file descriptors it had open are closed,
so we can know that the contents are valid if a process is holding it open.</p>
<p>You may be tempted to use <a href="http://man7.org/linux/man-pages/man1/lsof.1.html">lsof</a><code>-Fp -f -- /var/run/$PROGNAME.pid</code>,
or parsing <a href="http://man7.org/linux/man-pages/man5/proc.5.html">procfs</a> manually to determine whether a process is using the file,
but this is awkward for the same reason
as not parsing the output of the <a href="http://man7.org/linux/man-pages/man1/ps.1.html">ps(1)</a> command to tell whether it's running.</p>
<p>We need to be able to do something to the file descriptor
that will have an observable effect through other file descriptors to that flie.</p>
<p>The solution to this is to take a lock on the file.</p>
<p>You may see some programs use <a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a> with <code>F_SETLK</code>.
This is tempting because <code>F_GETLK</code> will include the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> in the result
instead of requiring the service to serialise and write the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> to the flie
and the checking process having to read and parse the file.</p>
<p><code>F_SETLK</code> should be avoided because the lock is removed
when <em>any</em> file descriptor to that file owned by that process is closed,
so you need to be able to guarantee
that neither any of your code not any other code you use via a library
will ever open that <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> file again
even if your process normally opens arbitrary files by user input.</p>
<p>So rather than using <a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a> with <code>F_SETLK</code>,
use <a href="http://man7.org/linux/man-pages/man2/flock.2.html">flock(2)</a> with <code>LOCK_EX</code>, or <a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a> with <code>F_WRLK</code>
to take a write or exclusive lock on the file,
and test whether the contents are live by trying to take a read or shared lock,
with <a href="http://man7.org/linux/man-pages/man2/flock.2.html">flock(2)</a>'s <code>LOCK_SH</code>, or <a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a>'s <code>F_RDLK</code>.</p>
<p>If you succeed at taking a read lock then the contents of the file aren't valid
and the service isn't running.</p>
<p>Implementing this logic can be awkward,
fortunately if you're writing a C program
you can use the <a href="https://manpages.debian.org/testing/libbsd-dev/pidfile.3.en.html">libbsd-pidfile</a> functions.</p>
<h1>It's the wrong tool for the job</h1>
<h2>Setting it up correctly is tricky</h2>
<p>The <a href="https://manpages.debian.org/testing/libbsd-dev/pidfile.3.en.html">libbsd-pidfile</a> functions will handle locks correctly,
but as permissively licensed as it is,
it is not always available, perticularly if you're not writing a C program.</p>
<p>A brief survey of the top results for python libraries for handling PID files
resulted in <a href="https://github.com/trbs/pid/">pid</a>, <a href="https://github.com/mosquito/python-pidfile">python-pidfile</a> and <a href="https://github.com/bmhatfield/python-pidfile">pidfile</a>.</p>
<p><a href="https://github.com/mosquito/python-pidfile">python-pidfile</a> does not keep the file open or take a lock.
<a href="https://github.com/bmhatfield/python-pidfile">pidfile</a> only improves by taking the lock and holding it.
<a href="https://github.com/trbs/pid/">pid</a> checks the validity and sets correct permissions on the file.
None of them have a mechanism to safely retrieve the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> from the file.</p>
<p>So if you have to do it yourself,
you'll need to do the following:</p>
<ol>
<li>open with <code>O_CREAT</code> to make the lock file if it doesn't exist.</li>
<li>Try to non-blocking take a shared lock on the file.
If you fail it's running,
and depending on whether you want to end it, replace it or leave it,
you should either instruct it to
terminate and continue, exit, or terminate then exit.
If you succeed then it's not running.</li>
<li>If you want to start a new service or replace it,
upgrade your shared lock to an exclusive lock <strong>with a timeout</strong>.
If you take a blocking lock then your processes will deadlock
waiting for their turn to start the service,
and if you take a non-blocking lock then
if your process is pre-empted by another process between trying to lock
and releasing the shared lock,
then you could end up with every process exiting.</li>
<li>If you took the lock replace the contents of the file with your <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a>,
if you timed out unlock the file or exit.</li>
</ol>
<p>The above is already complicated and still doesn't handle edge-cases,
such as another process trying to start
between taking the lock and writing the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a>,
which <a href="https://manpages.debian.org/testing/libbsd-dev/pidfile.3.en.html">libbsd-pidfile</a> handles with a retry loop.</p>
<p>It also doesn't handle the file being <a href="http://man7.org/linux/man-pages/man2/unlink.2.html">unlink</a>ed while starting,
which would cause you to have multiple services running.</p>
<p><a href="https://manpages.debian.org/testing/libbsd-dev/pidfile.3.en.html">libbsd-pidfile</a> doesn't take the shared lock then upgrade,
so if many processes often want to know whether it's running,
then they would be unnecessarily contesting the lock.</p>
<h2>Views of PIDs are not universal</h2>
<p><a href="http://man7.org/linux/man-pages/man7/pid_namespaces.7.html">Process namespaces</a> exist.</p>
<p>While a single process' view of its <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> does not change,
other processes can see it with different <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a>s
since processes in sub-namespaces are viewable in multiple namespaces
and have a different <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> in each namespace.</p>
<p>You can detect whether the process is running by whether locking fails,
but you can't use the contents to terminate it,
since the PID it knows it to be is different from the PID you can reach it with,
unless you use <a href="http://man7.org/linux/man-pages/man2/setns.2.html">a restricted system call</a>
to enter the namespace of the process
in order to terminate it.</p>
<p><a href="http://man7.org/linux/man-pages/man2/fcntl.2.html">fcntl(2)</a>'s <code>F_GETLK</code> would return the <a href="https://en.wikipedia.org/wiki/Process_identifier">PID</a> correctly,
but is unreliable in other areas.</p>
<h2>Services can span more than one process</h2>
<p>The PIDfile model works acceptably if your service only runs in one process,
but some programs spawn helper processes
and terminating the lead process may not tidy up all the helper processes.</p>
<p>There are ways to have the termination of one process
cause the termination of others,
however this just moves the problem of "how do you know your process is running"
to the supervising process without solving the general problem.</p>
<p>So, we know that PID files aren't necessarily the right tool for the job,
in the next article we explore some alternatives.</p>
Is your process running 1 - Parsing proc and why you shoudn'thttp://yakking.branchable.com/posts/procrun-1-parsing-proc/Richard Maw2017-03-23T16:02:13Z2017-03-22T12:00:08Z
<p>Sometimes it is necessary to leave a process running,
performing some service in the background while doing something else.</p>
<p>It would be redundant and possibly harmful
to start a new one if it is already running.</p>
<p>Ideally all programs would safely shut themselves down if already running,
checking if it's running before starting
only guarantees that it was runing when you checked,
rather than that it is running when you need it.
For most purposes though it is reasonable to check first.</p>
<p>So how do we know if our service is running?</p>
<p>You may have run <a href="http://man7.org/linux/man-pages/man1/ps.1.html">ps(1)</a> before to see if a process is running,
so you might naturally think this would be how to do it.</p>
<p>This would of course fall into the trap of parsing the output of shell commands.
Why should we write fragile code
when <a href="http://man7.org/linux/man-pages/man1/ps.1.html">ps(1)</a> is using a proper API to do it?</p>
<p>The way this is accomplished
is the <a href="http://man7.org/linux/man-pages/man5/proc.5.html">procfs</a> <a href="https://en.wikipedia.org/wiki/Virtual_file_system">virtual file system</a> traditionally <a href="https://en.wikipedia.org/wiki/Mount_(computing)">mounted</a> at <code>/proc</code>.
There is a subdirectory in this file system for each process
listed by its process ID.</p>
<p>We can list all directories that are processes by running:</p>
<pre><code>find /proc -mindepth 1 -maxdepth 1 -name '[0-9]*'
</code></pre>
<p>Inside each of these directories are files describing the process.</p>
<h1>Check <code>comm</code></h1>
<p>When you look at the output of <a href="http://man7.org/linux/man-pages/man1/ps.1.html"><code>ps</code></a>
it shows the name of the process,
which is normally the base name of the file path
of the executable that the process was started with.</p>
<p>This is stored in the file in <code>/proc</code> called <code>comm</code>.</p>
<p>So if the name of your program is "myprogram",
you can find out if your program is running with the following command:</p>
<pre><code>find /proc -mindepth 1 -maxdepth 1 ! -name '*[^0-9]*' -type d -exec sh -c \
'[ "$(cat "$1/comm")" = myprogram ] && echo Is running' - {} ';'
</code></pre>
<p>I would recommend against checking if your program is running this way though,
as processes may call themselves whatever they want,
by writing the new name to <code>comm</code>.</p>
<pre><code>$ cat /proc/$$/comm
bash
$ printf dash >/proc/$$/comm
$ cat /proc/$$/comm
dash
</code></pre>
<p>This is often used by services that fork off helper processes
to name the subprocesses after their role
to make it easier for developers or sysadmins to know what they do.</p>
<h1>Check <code>exe</code></h1>
<p>The <a href="http://man7.org/linux/man-pages/man5/proc.5.html">procfs</a> entry also includes
the path of the executable the proccess was started from
as a symbolic link.</p>
<p>Thus if your program is installed at <code>/usr/bin/myprogram</code>
then we can check whether it is running with:</p>
<pre><code>find /proc -mindepth 1 -maxdepth 1 ! -name '*[^0-9]*' -type d -exec sh -c \
'[ "$(readink "$1/exe")" = /usr/bin/myprogram ] && echo Is running' - {} ';'
</code></pre>
<p>This cannot be modified by the proces after it has started,
but as usual caveats apply:</p>
<ol>
<li><p>Not all processes have an initial executable.
This symbolic link may be unreadable (fails with <a href="http://man7.org/linux/man-pages/man3/errno.3.html">errno</a> of <code>ENOENT</code>)
in the case of kernel threads.</p></li>
<li><p>It could be a program that has subcommands,
one of which may be a long-running service (e.g. git-daemon),
which you wouldn't want to fail to start
just because a shorter operation with a different subcommand
happened to be running at the same time.</p></li>
<li><p>This is unhelpful in the case of interpreted languages,
since it is always the name of the interpreter
rather than the name of the script.</p></li>
<li><p>The same program may be reachable by multiple file paths
if the executable has been hard-linked.</p></li>
<li><p>If the program's executable may be removed while it is running,
changing <code>exe</code> to append " (deleted)" to the file path.</p>
<p>If this file is then replaced
then another process may have the same executable path
but an incompatible behaviour.</p>
<p>This isn't even unusual if the name of the process is generic,
like "sh" or "httpd".</p></li>
</ol>
<p>So it's useless for interpreted programs
and unreliable if the executable can be replaced.</p>
<h1>Check <code>cmdline</code></h1>
<p>It could be perfectly safe to run the same program multiple times
provided it is passed different configuration.</p>
<p>The <code>cmdline</code> file can be parsed to infer this configuration
as a list of strings that are NUL terminated.</p>
<p>A problem with this approach
is the need to reimplement parsing logic
<em>and</em> know for all command-lines whether it's appropriate to start another.</p>
<p>This logic could be quite difficult,
but you could add a parameter just for determining whether it is the same.</p>
<p>This is far from ideal because:</p>
<ol>
<li>Lookup time gets worse as your system has more processes running.</li>
<li>Processes can modify their command-line too,
so another process could arrange to have the same command-line,
and make this unreliable.</li>
</ol>
<p>Next time we are going to look at a better use for that parameter.</p>
The value in attending conferenceshttp://yakking.branchable.com/posts/conferences/Richard Maw2015-11-25T12:00:14Z2015-11-25T12:00:08Z
<p>I spoke at the first <a href="https://systemd.events/">systemd.conf</a> recently.</p>
<p>This was an enjoyable experience,
and I can highly recommend attending relevant conferences.</p>
<h1>The value in conferences</h1>
<ol>
<li><p>Put names to faces of people you've never met in person before.</p>
<p>This adds a personal touch that makes future communication easier,
since you get a feel for how approachable someone is,
and they know you as someone they can talk to.</p>
<p>Some people's avatars look rather different to how they do in-person,
and now I have a good idea of the people who I had been chatting to in
<code>#systemd</code> actually are.</p>
<p>This is easier if the conference has social events arranged,
as they often include alcohol,
which can loosen the tongue sufficiently to get past the inhibitions
and awkwardness of speaking to people you don't know so well.</p></li>
<li><p>Participate in the less open discussions that interested subgroups have.</p>
<p>Some large projects organise themselves into subgroups,
aligned partially by interests,
and partially by the organisational structures of where they work.</p>
<p>The <code>kdbus</code> developers don't normally hold the discussions
of its development anywhere I frequent,
but I maintain an interest in its development,
so being able to hear how it was going was nice.</p></li>
<li><p>Discover common ground between different developers, to organise subgroups.</p>
<p>Systemd is normally consumed by downstream Linux distributions,
rather than the users directly,
who instead get it from their distribution,
and there is an amount of work involved.</p>
<p>Because <a href="https://systemd.events/">systemd.conf</a> allowed all the maintainers from the distributions
to get together in one room,
they were able to organise a common working group,
so that they could collaborate on downstream packaging,
most importantly communal maintanence of a stable release.</p></li>
<li><p>Hear the gossip that you don't normally hear.</p>
<p>I couldn't possibly comment.</p></li>
<li><p>Attend or give talks.</p>
<p>Attending talks gives you the opportunity to understand the perspectives
of others, in a manner structured to help you understand.</p>
<p>Giving talks is both the opportunity to share your perspective,
and if, like me, you are uncomfortable with public speaking,
the opportunity to step outside your comfort zone and expand it.</p></li>
</ol>
<h1>Getting involved in conferences</h1>
<p>If your project is small, it is possible to organise a dev-room,
in a community-driven conference, like <a href="http://fosdem.org/">FOSDEM</a>,
or a larger corporate conference where interests overlap,
like systemd used to.</p>
<p>Medium-sized projects, like systemd,
can arrange to have their own dedicated conference.</p>
<p>Large projects, like the Linux kernel or <a href="http://www.openstack.org/">OpenStack</a> have many,
big, corporate conferences, in far away, expensive places, a few times a year.</p>
<p>There is usually some form of sponsorship available,
for starving hackers to be able to attend conferences.</p>
<p>Big projects often have more expensive conferences,
but usually balance this by having sponsorship more readily available.</p>
<p>Small projects may find sponsorship more difficult,
so attendees will need to fund it themselves,
which makes community conferences like <a href="http://fosdem.org/">FOSDEM</a> more appropriate.</p>
<h1>Call to action</h1>
<p>If you're looking to attend a conference for some project that interests you,
but you don't have a specific project in mind,
you could look at the <a href="https://lwn.net/Calendar/">LWN.net Community Calendar</a>.</p>
<p>If you are a member of a project and would like to get together with other
developers or users, and there isn't a conference of its own for it,
try to find a community conference that is near to most of the developers,
and see if you can arrange for sponsorship for any more remote developers,
so that you can have a get-together.</p>
Networking - DHCPhttp://yakking.branchable.com/posts/networking-5-dhcp/Richard Maw2015-11-11T12:00:14Z2015-11-11T12:00:08Z
<p>I hope you've done your homework.
In a <a href="http://yakking.branchable.com/tags/systemd/networking-3-addresses-and-routes">previous article about networking</a>
we set an exercise to configure some machines with static IP addresses.</p>
<p>You probably agree that it would be annoying if you had to change the
address range as it is configured in all the different computers.</p>
<p>Wouldn't it be better if we could store this information in the network somehow?</p>
<p>Well, guess what? We can! Its called <a href="http://en.wikipedia.org/wiki/dhcp">DHCP</a>.</p>
<p>This works by nominating one computer on the network
to act as the master of networking configuration.</p>
<p>Computers which want to opt into the network
communicate with this server to be told what addresses to use.</p>
<p>Normally your router-modem that connects you to the internet
takes this responsibility,
but any machine, real or virtual, may do it.</p>
<h1>Example with network namespaces</h1>
<p>As before, we're going to use network namespaces
to simulate multiple machines sharing a network.</p>
<p>For DHCP to work you need a DHCP server on the managing machine,
and a DHCP client on every client machine that will join this network.
Since we are only virtualising the networking, we need both on the same machine.</p>
<p>You will likely have <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> and <a href="http://linux.die.net/man/8/dhclient">dhclient</a> on your system,
since while systemd can provide a DHCP server and client through <a href="http://man7.org/linux/man-pages/man8/systemd-networkd.8.html">networkd</a>,
this currently is generally only used in servers, embedded and containers,
while <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a> uses <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> and <a href="http://linux.die.net/man/8/dhclient">dhclient</a> on desktops.</p>
<p>While <a href="http://man7.org/linux/man-pages/man8/systemd-networkd.8.html">networkd</a> is capable of being both a DHCP client and server,
we can only demonstrate its use as a client,
since it requires a full container to isolate its configuration from the host.</p>
<h2>Configuring the virtual network</h2>
<p>We're going to use a network namespace called <code>dhcptest</code>,
which will be connected to the host network namespace
by a virtual ethernet device.</p>
<pre><code># ip netns add dhcptest
# ip link add host type veth peer name guest
# ip link set guest netns dhcptest
</code></pre>
<p>The subnet of the network linking us to <code>dhcptest</code> we use is <code>10.0.0.0/24</code>,
which ranges from <code>10.0.0.1</code> to <code>10.0.0.255</code>.</p>
<p>Since the machine in <code>dhcptest</code> will be the DHCP server,
we need to assign its own address statically.</p>
<pre><code># ip netns exec dhcptest ip addr add 10.0.0.1 dev guest
# ip netns exec dhcptest ip link set guest up
# ip netns exec dhcptest ip route add 10.0.0.0/24 dev guest
</code></pre>
<h2>Using dnsmasq as the DHCP server</h2>
<p>In a terminal, run:</p>
<pre><code># ip netns exec dhcptest dnsmasq --dhcp-range=10.0.0.2,10.0.0.254,255.255.255.0 --interface=guest --no-daemon
dnsmasq: started, version 2.72 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect
dnsmasq-dhcp: DHCP, IP range 10.0.0.2 -- 10.0.0.254, lease time 1h
dnsmasq: reading /etc/resolv.conf
dnsmasq: using nameserver 127.0.1.1#53
dnsmasq: read /etc/hosts - 1 addresses
</code></pre>
<p>This starts <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> on <code>dhcptest</code>,
serving the address range <code>10.0.0.2</code> to <code>10.0.0.254</code>,
with the subnet <code>10.0.0.0/24</code> (this is the <code>255.255.255.0</code> netmask<code>),
on the</code>guest` network interface.</p>
<p><code>--no-daemon</code> forces <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> to stay running in the foreground,
which makes it easier to clean up when finished,
since it can be cancelled with <code>^C</code>.</p>
<h2>Using dhclient as the DHCP client</h2>
<p>In a different terminal to the one that the DHCP server was started in, run:</p>
<pre><code># dhclient -d host
Internet Systems Consortium DHCP Client 4.3.1
Copyright 2004-2014 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/host/16:c0:28:6b:ea:76
Sending on LPF/host/16:c0:28:6b:ea:76
Sending on Socket/fallback
DHCPDISCOVER on host to 255.255.255.255 port 67 interval 3 (xid=0xd6a3b68)
DHCPREQUEST of 10.0.0.105 on host to 255.255.255.255 port 67 (xid=0x683b6a0d)
DHCPOFFER of 10.0.0.105 from 10.0.0.1
DHCPACK of 10.0.0.105 from 10.0.0.1
bound to 10.0.0.105 -- renewal in 1643 seconds.
</code></pre>
<p>This shows that it has successfully requested <code>10.0.0.105</code> as its address.</p>
<p>The <a href="http://linux.die.net/man/8/dhclient">dhclient</a> process will continue to run,
as it hasn't been given that address forever,
it has been given that address for an hour,
at which point it will expire and it must stop using it,
but before then <a href="http://linux.die.net/man/8/dhclient">dhclient</a> may renew the address to allow us to keep using it.</p>
<h2>Using networkd as the DHCP client</h2>
<p>First create the config file:</p>
<pre><code># install -m 644 /dev/stdin /etc/systemd/network/dhcptest.network <<'EOF'
> [Match]
> Name=host
> [Network]
> DHCP=yes
> EOF
</code></pre>
<p>Since <a href="http://man7.org/linux/man-pages/man8/systemd-networkd.8.html">networkd</a> currently only reads its config at startup,
we must restart it for the new config to take effect.
(This also has the effect of starting it for the first time,
on distros that don't start networkd by default.)</p>
<pre><code># systemctl restart systemd-networkd.service
</code></pre>
<p>This won't give any immediate feedback whether it worked,
but you can inspect its status by running:</p>
<pre><code>$ networkctl status host
● 6: host
Link File: /lib/systemd/network/99-default.link
Network File: /etc/systemd/network/dhcptest.network
Type: ether
State: routable (configured)
Driver: veth
HW Address: 16:c0:28:6b:ea:76
MTU: 1500
Address: 10.0.0.105
fe80::14c0:28ff:fe6b:ea76
Gateway: 10.0.0.1
DNS: 10.0.0.1
</code></pre>
<p>Note that this has created some persistent configuration,
so the next time the <code>host</code> ethernet device is created networkd will DHCP.</p>
<p>If you don't want to do this in future, you can remove the configuration
by running <code>rm /etc/systemd/network/dhcptest.network</code>.</p>
<h2>DHCPing successfully</h2>
<p>In the terminal running <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> you should see:</p>
<pre><code>dnsmasq-dhcp: DHCPDISCOVER(guest) 10.0.0.105 16:c0:28:6b:ea:76
dnsmasq-dhcp: DHCPOFFER(guest) 10.0.0.105 16:c0:28:6b:ea:76
dnsmasq-dhcp: DHCPREQUEST(guest) 10.0.0.105 16:c0:28:6b:ea:76
dnsmasq-dhcp: DHCPACK(guest) 10.0.0.105 16:c0:28:6b:ea:76 HOSTNAME
dnsmasq-dhcp: not giving name HOSTNAME to the DHCP lease of 10.0.0.105 because the name exists in /etc/hosts with address 127.0.1.1
</code></pre>
<p>In another terminal you can see that it configured the address by running:</p>
<pre><code>$ ip addr show dev host
6: host: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 16:c0:28:6b:ea:76 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.105/24 brd 10.0.0.255 scope global host
valid_lft forever preferred_lft forever
inet6 fe80::14c0:28ff:fe6b:ea76/64 scope link
valid_lft forever preferred_lft forever
</code></pre>
<h2>Testing the link</h2>
<p>We can now prove it works with netcat.</p>
<p>Run <code>ip netns exec dhcptest nc -l 1234</code> in one terminal,
and <code>nc 10.0.0.1 1234</code> in another,
and you will be able to see that text entered is repeated in both terminals.</p>
Systemd 7 - cron, at and systemd timershttp://yakking.branchable.com/posts/systemd-7-crontab-and-timers/Richard Maw2015-11-02T20:42:10Z2015-10-28T12:00:07Z
<p>You will, from time to time,
feel the need to run a command at a specific time.</p>
<p><a href="http://linux.die.net/man/1/at">at(1)</a> will run a command at a specified time,
so if you need a reminder that you should go to bed at midnight,
you could run the following command:</p>
<pre><code>$ at midnight
at> echo Go to bed | wall ^D
</code></pre>
<p>If you instead need to run a command at regular times,
such as a <a href="http://liw.fi/">backup</a> job,
then you can add a persistent timed job with <a href="http://man7.org/linux/man-pages/man1/crontab.1.html">crontab(1)</a>.</p>
<p>You would run <code>crontab -e</code> to add a command to your crontab,
as described in <a href="http://man7.org/linux/man-pages/man5/crontab.5.html">crontab(5)</a>.</p>
<p>To run nightly <a href="http://obnam.org/">obnam</a> backup
(instructions taken from <a href="http://bastian.rieck.ru/blog/posts/2013/backups_with_obnam/">Bastian Rieck's blog</a>),
add the following to the crontab file.</p>
<pre><code>0 20 * * * /usr/bin/obnam backup $HOME
</code></pre>
<p>This could instead be written as a systemd timer unit,
which can be used without a separate cron service running,
by creating two configuration files as follows:</p>
<pre><code>$ mkdir -p ~/.config/systemd/user
$ cat >~/.config/systemd/user/backup.timer <<'EOF'
> [Unit]
> Description=Backup timer
> [Timer]
> OnCalendar=daily
> [Install]
> WantedBy=default.target
> EOF
$ cat >~/.config/systemd/user/backup.service <<'EOF'
> [Unit]
> Description=Backup Service
> [Service]
> Type=simple
> ExecStart=/usr/bin/obnam backup %h
> [Install]
> WantedBy=default.target
> EOF
$ systemctl --user daemon-reload
$ systemctl --user enable backup.timer backup.service
$ systemctl --user start backup.timer backup.service
</code></pre>
<p>This is more verbose than the cron syntax, though arguably less arcane.</p>
<p>However systemd timer units have the advantage
of allowing you to set <code>WakeSystem=</code>,
which will unsuspend your system to react to timer events.</p>
<p>There are instructions on how to use this to make an alarm clock
on <a href="http://joeyh.name/blog/entry/a_programmable_alarm_clock_using_systemd/">Joey Hess' blog</a>.</p>
systemd for the uninformed - networkinghttp://yakking.branchable.com/posts/systemd-6-networkd/Richard Maw2015-07-01T11:00:13Z2015-07-01T11:00:07Z
<p>Networking is one of the most important things a computer can do, since
it's no so useful on its own.</p>
<h1>systemd-networkd</h1>
<p>Networking under Linux is powerful, but managed by a set of wildly
different tools, with different capabilities and with very different
interfaces.</p>
<p>To handle this, <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> introduced <a href="http://www.freedesktop.org/software/systemd/man/systemd-networkd.html">networkd(8)</a> to provide a
common interface to all the network configuration, and is becoming a
standard way of doing this across the different distributions.</p>
<p>At the time of writing, <a href="http://www.freedesktop.org/software/systemd/man/systemd-networkd.html">networkd(8)</a> is intended to be
a replacement for static network config in the form of the
Debian-derived <a href="http://manpages.ubuntu.com/manpages/utopic/man5/interfaces.5.html">interfaces(5)</a> file, or the Red Hat-derived
<a href="http://www.linuxcertif.com/man/5/ifcfg/">ifcfg(5)</a>, rather than the dynamic network config managed by
<a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a> or <a href="https://01.org/connman">connman</a>.</p>
<p>However, you can do some form of dynamic network configuration by
putting files in <code>/etc/systemd/network</code> and restarting <a href="http://www.freedesktop.org/software/systemd/man/systemd-networkd.html">networkd(8)</a>
by running <code>systemctl restart systemd-networkd.service</code>.</p>
<p>You can configure networks by adding a <a href="http://www.freedesktop.org/software/systemd/man/systemd.network.html">systemd.network(5)</a>
file, or create virtual network devices (such as bridges) with a
<a href="http://www.freedesktop.org/software/systemd/man/systemd.netdev.html">systemd.netdev(5)</a> file.</p>
<p>This is normally the domain of the system administrator, but <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a>
ships a few default rules to make networking with containers launched with
[systemd-networkd(1)][] work better.</p>
<p><a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> ships a rule for containers to use <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a> on network
interfaces named <code>hostN</code>, to get their IP address. And ships a rule
such that the other end of these host-only interfaces provide a <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a>
server, and use <a href="http://en.wikipedia.org/wiki/Network_address_translation">NAT</a> to allow containers to speak to the internet.</p>
<h1>systemd-resolved</h1>
<p><a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a> isn't the whole story though, as you need names to usefully
access the internet, so <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> has some support for <a href="http://en.wikipedia.org/wiki/Domain_Name_System">DNS</a>.</p>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-resolved.html">resolved(8)</a> provides per-interface <a href="http://en.wikipedia.org/wiki/Hostname">DNS hostname</a> resolution. This
is an improtant improvement over the current state of Linux networking,
because network interfaces are a lot more dynamic than they used to be.</p>
<p>It is not unusual to be connected to multiple networks, especially if
you need to use a <a href="http://en.wikipedia.org/wiki/Virtual_private_network">VPN</a> to talk to machines that are not allowed to
connect to the internet.</p>
<p>If name resolution is not handled per-interface, then you need to flush
the <a href="http://en.wikipedia.org/wiki/Domain_Name_System">DNS</a> cache to avoid having entries that are only relevant to
networks you are no longer connected to.</p>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-resolved.html">resolved(8)</a> is only indirectly used, via the standard name lookup
procedure specified in the "hosts" line in the <a href="http://man7.org/linux/man-pages/man5/nsswitch.conf.5.html">nsswitch.conf(5)</a>
file, by adding "resolve".</p>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-resolved.html">resolved(8)</a> doesn't normally need further configuration, as name
resolution is typically per-network configuration, and this network
configuration is usually shared by a <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a> server.</p>
<p>However, if this is not reliable, then the name servers can be configured
per-interface in a <a href="http://www.freedesktop.org/software/systemd/man/systemd.network.html">systemd.network(5)</a> file, or system-wide in the
[resolved.conf(5)][] configuration file.</p>
systemd for the uninformed - managing machineshttp://yakking.branchable.com/posts/systemd-5-machined/Richard Maw2015-06-18T09:00:51Z2015-06-17T11:00:09Z
<p><a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> has a few services that are mostly just about providing
a common interface to information about the current machine, or other
machines.</p>
<h1>Daemons for recording information</h1>
<p>There's <a href="http://www.freedesktop.org/software/systemd/man/systemd-hostnamed.html">hostnamed(8)</a>, <a href="http://www.freedesktop.org/software/systemd/man/systemd-localed.html">localed(8)</a> and <a href="http://www.freedesktop.org/software/systemd/man/systemd-timedated.html">timedated(8)</a> for
providing a wirtable D-Bus interface to the system's hostname, locale
and time respectively; and <a href="http://www.freedesktop.org/software/systemd/man/systemd-machined.html">machined(8)</a>, which provides information
about the "chassis type" or "form factor".</p>
<p>It may sound wasteful to have an entire server just to make this
information available over D-Bus, but when a server is waiting for
requests it is often paged-out, meaning it's only consuming a small
amount of memory.</p>
<p>However, this wasn't good enough for the <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> developers, so
these services are D-Bus activated, which means that they'll only be
started when something makes a request of them. Combined with the fact
that these services will exit when idle, and they don't even need to
consume that small amount of memory any more.</p>
<p>One user of <a href="http://www.freedesktop.org/software/systemd/man/systemd-hostnamed.html">hostnamed(8)</a> is the <a href="http://www.freedesktop.org/software/systemd/man/nss-myhostname.html">myhostname</a> <a href="http://www.gnu.org/software/libc/manual/html_node/Name-Service-Switch.html">NSS</a> module,
which if <a href="http://www.gnu.org/software/libc/manual/html_node/NSS-Configuration-File.html#NSS-Configuration-File">nsswitch.conf</a> is configured correctly, allows the addresses
of the curent machine to be resolved without hard-coding them in the
<a href="http://man7.org/linux/man-pages/man5/hosts.5.html">hosts file</a>.</p>
<h1>machined supporting containers</h1>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-machined.html">machined(8)</a> also manages information about other machines, though
this stretches the definition of "machine" a little, since it means
the host machine, containers and virtual machines, rather than
multiple physical machines on a network.</p>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-machined.html">machined(8)</a> is usually used indiectly by your virtual-machine
manager or container manager, to provide a common interface for managing
them with <a href="http://www.freedesktop.org/software/systemd/man/machinectl.html">machinectl(1)</a>.</p>
<p>The usual management tasks aren't much more than just seeing which
machines are online and stopping them if necessary, but if a machine
is registered with <a href="http://www.freedesktop.org/software/systemd/man/systemd-machined.html">machined(8)</a>, then other <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> management
commands, such as <a href="http://www.freedesktop.org/software/systemd/man/systemctl.html">systemctl(1)</a> allow you to pass a machine name to
the <code>--machine</code> option, to get it to operate on that machine instead of
the host.</p>
<p><a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> comes with a container manager built-in, called
<a href="http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html">systemd-nspawn(1)</a>, which has more full integration with
<a href="http://www.freedesktop.org/software/systemd/man/machinectl.html">machinectl(1)</a>, allowing the download of container images, configuring
whether they start on-boot, and commands to log-in to the container and
copy files in or out.</p>
systemd for the uninformed - session and seat management with logindhttp://yakking.branchable.com/posts/systemd-4-logind/Richard Maw2015-05-27T11:00:14Z2015-05-27T11:00:08Z
<p><a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> has a service for managing user sessions called <a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a>,
this replaces the existing <a href="http://www.freedesktop.org/wiki/Software/ConsoleKit/">ConsoleKit</a> tool, which was the previous
cross-desktop and cross-distribution tool.</p>
<p>This caused some controversy, as <a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a> is not usable without
<a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a>, and the fear was that this would cause distributions to
force the use of <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a>.</p>
<p>There was some misplaced anger at both the <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> developers and the
<a href="https://www.gnome.org">GNOME</a> developers, when the <a href="https://www.gnome.org">GNOME</a> package maintainers in <a href="https://www.debian.org/">Debian</a>
decided to build <a href="https://www.gnome.org">GNOME</a> without <a href="http://www.freedesktop.org/wiki/Software/ConsoleKit/">ConsoleKit</a> support, as <a href="https://www.gnome.org">GNOME</a>
still supported being built with <a href="http://www.freedesktop.org/wiki/Software/ConsoleKit/">ConsoleKit</a>, and the <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a>
developers are not responsible for other developers' decisions to support
<a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a> exclusively.</p>
<p>So, controversy aside, what does <a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a> provide to us?</p>
<h1>User session management</h1>
<p><a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a> tracks user log-ins and keeps track of which processes are
used, by use of a <a href="http://www.freedesktop.org/software/systemd/man/pam_systemd.html">pam_systemd</a> <a href="http://www.linux-pam.org/">PAM</a> module, so that processes can
be cleaned up when a user logs out, or the user is forced to log out,
such as when the administrator needs to perform maintainance, or the
user is no longer permitted to use the server.</p>
<p>There's little to no configuration needed by users for this aspect of
<a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a>, but if a user should be allowed to run processes after
they log out, such as if they run a <a href="http://man7.org/linux/man-pages/man1/screen.1.html">screen(1)</a> session, then this can
be allowed by using <a href="http://www.freedesktop.org/software/systemd/man/loginctl.html">loginctl(1)</a> to run <code>loginctl enable-linger $USER</code>.</p>
<h1>Seat assignment</h1>
<p>It's common these days for everybody to have their own computer, and
the only shared computers are servers, which you interact with via your
local comptuer, over a network.</p>
<p>However, back in the day, it was more common for there to be 1 computer
shared directly to multiple users, each with their own physical terminal.</p>
<p>Personal computing has made shared machines with multiple terminals
mostly unnecessary, but there's still a few uses, such as kiosks,
internet cafes, or classrooms, where it would be more cost efficient to
have people sharing the computer.</p>
<p>To make this work, <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a> supports <a href="http://en.wikipedia.org/wiki/Multiseat_configuration">Multiseat configuration</a>,
by assigning multiple physical devices, such as a display, a keyboard
and a mouse, to different seats.</p>
<p>Some hardware is automatically configured as a separate seat, but
hardware can be explicitly assigned to a seat if these automatic rules
are incorrect, by using <code>loginctl attach SEAT DEVICE_PATH</code>.</p>
<h1>Hardware sleep</h1>
<p>If your computer is battery powered you may want the machine to go to
sleep when idle to save power, or you may want to block a system reboot
while performing crucial operations, like a system update.</p>
<p>To handle this, <a href="http://www.freedesktop.org/software/systemd/man/systemd-logind.html">logind(8)</a> allows you to take an <a href="http://www.freedesktop.org/wiki/Software/systemd/inhibit/">inhibit</a> lock,
which is implemented with file descriptor passing, so a crashing process
will automatically release it.</p>
<p>To use an inhibitor lock, either run a command with the
<a href="http://www.freedesktop.org/software/systemd/man/systemd-inhibit.html">systemd-inhibit(1)</a> wrapper command, or request a file descriptor
with the <a href="http://www.freedesktop.org/wiki/Software/systemd/logind/">logind D-Bus interface</a>.</p>