Steve Langasek: A new chapter

/etc/default/grub
to add splash
to GRUB_CMDLINE_LINUX_DEFAULT
:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
Besides showing pretty pictures (and most importantly, getting them out of my
way if I press ESC
), plymouth also provides a user prompt that works with
parallel boot
which sounds like what I needed.
2014, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Required-Start: $network
The trouble with both of these approaches is that they assume that there is
a single point in time, early in the boot of the system, when the "network"
is up. This was an ok assumption 15 years ago, when the Linux kernel
initialized all devices serially and all our network configuration was static.
But nowadays, you simply cannot rely on systems booting in such a way that
the network is fully up shortly after boot - or in a way that you can block
the system boot waiting for the network to be up.
If all of our services would cope gracefully with being started without
the network, this would be a non-issue. Unfortunately, not all network
services are written in such a way as to work without a network; nor do
they all cope with dynamic changes to interfaces or addresses. While it
would be better if these services were written more robustly, since there's
no shortage of daemons written this way, it's convenient that upstart
provides tools for coping with this behavior in the meantime.
Here's a real (simplified) example of an upstart job for a service that needs
to wait for a non-loopback interface before it starts:
start on (local-filesystems and net-device-up IFACE!=lo)
stop on runlevel [!2345]
expect fork
respawn
exec nmbd -D
Now, you might also have a service that you only want to start up when a
particular network device comes up. This is easily expressed in upstart,
and might look like this hypothetical job:
start on net-device-up IFACE=wlan0
stop on net-device-down IFACE=wlan0
expect daemon
respawn
exec mydaemon
If you need to restart a daemon whenever the set of active network
connections changes, that's less straightforward. Upstart doesn't have
the notion of a 'restart' rule, so you would need two jobs to handle
this - one for the daemon itself that starts on the first network connection,
and a second job to trigger a restart of the daemon when the network status
changes. For the tftpd-hpa case in the abovementioned bug, this might look
like:
$ cat /etc/init/tftpd-hpa.conf
start on runlevel [2345]
stop on runlevel [!2345]
expect fork
respawn
script
if [ -f $ DEFAULTS ]; then
. $ DEFAULTS
fi
exec /usr/sbin/in.tftpd --listen --user $ TFTP_USERNAME --address $ TFTP_ADDRESS $ TFTP_OPTIONS $ TFTP_DIRECTORY
end script
$ cat /etc/init/tftpd-hpa-restart.conf
start on net-device-up
task
instance $IFACE
script
status tftpd-hpa grep -q start/ stop
restart tftpd-hpa
end script
For this case, upstart doesn't provide quite so great an advantage.
It's nice to be able to use upstart natively for both pieces, but you
can do the same thing with an init script plus an if-up.d
script for
ifupdown, which is what maintainers do today. I think adding a restart
on
stanza to upstart in the future to address this would be a good
idea. Though in any event, this is far simpler to do with upstart than
with any if-up.d
script I've ever seen for managing an
initscript-based service. Between the more friendly declarative syntax,
and the enhanced semantics for expressing when to run (or restart) a job,
upstart offers clear advantages over other init systems.
systemd has too many dependencies, or it is bloated, or it does too many things, or is too complexNow this concern actually has a lot of different facets, and I am trying to share my opinion on each of them. systemd has too many dependencies First, let s start with too many dependencies , because that is easy to check and reason about. I have created a document which lists all dependencies of the systemd binary itself (pid 1) and all the binaries which are currently shipped by the systemd Debian package. If you don t want to take my word for granted, please read that document. Have you read the document? Very nice! As you can see, the systemd binary itself has 10 dependencies (excluding libc). Now, the question is, what is bad about dependencies? Why do people list dependencies as a top concern?
enforce_user
which uses libcap. You ll notice that the code is not complex and usage of
the libraries is clear.
Software bloat is a process whereby successive versions of a computer program become perceptibly slower, use more memory or processing power, or have higher hardware requirements than the previous version whilst making only dubious user-perceptible improvements.The first part of the definition certainly does not match systemd it is measurably faster than sysvinit. As for memory usage: systemd s RSS is 1.8 MiB, whereas sysvinit uses 0.8 MiB. As I argued on the More memory use point in the dependencies section, I think the additional resource cost is well worth the benefits. Also note that systemd s features are NOT all implemented in the binary which is PID 1. As explained in the dependency list, systemd consists of many cleanly separated binaries. So if a new version of systemd gathers an additional feature, this does not mean that your PID 1 will be bigger. While systemd runs on any hardware, it has an indirect hardware requirement: it requires some Linux kernel features (which are all enabled in Debian kernels). That might rule out usage of systemd on really old embedded hardware where you don t have a chance to update the kernel. While it is sad that those machines cannot profit from systemd, switching to systemd as a default has no downside either: Debian continues to support sysvinit for quite some time, so these machines will continue to work even with upcoming Debian versions. systemd does too many things The Wikipedia definition continues:
[ ] perceived bloat can occur from the software servicing a large, diverse marketplace with many differing requirements. Most end users will feel they only need some limited subset of the available functions and will regard the others as unnecessary bloat, even if people with different requirements do use them.I think the last part of the Wikipedia definition applies to systemd: it does service a large and diverse marketplace . That marketplace is the entirety of existing software which is started by an init system. Also, systemd can be used on a wide range of hardware (embedded devices, tablets, phones, notebooks, desktops, servers) which requires different features. As an example: on a desktop system you typically don t care strongly about a watchdog feature, but on embedded or servers that feature is very handy. Similarly, on a tablet, forward secure sealing of logfiles is not as important as on a server. Therefore, I can understand if you feel that you don t need many of the features systemd provides. But please think of other users and maintainers who are very happy with systemd s benefits. Also note that while systemd supports many things (in separate binaries!), you don t have to use them all. It still makes sense to ship them all in the same package. Take coreutils as another example in that area. The binaries belong together, even though you most likely haven t used all of them (e.g. od, pr, ptx, :-)). systemd is too complex The remaining concern is that systemd is too complex. In my experience, complexity is often inherent to a specific area and one cannot simply make it go away. Instead, there are different models of how that complexity is represented. Think of the monolithic Linux kernel versus the MINIX microkernel. The latter has a very small amount of lines of source in the kernel, but puts the complexity into userspace. The former uses a different approach with more source in the kernel. The arguments between both camps show that neither is clearly right or clearly wrong. In a way, sysvinit represents the MINIX model: it has a small core (the init binary itself), but a lot of complexity in shell scripts and external programs. The fact that solutions are copied from one init script to another leads to lots of subtle errors and makes code reuse really hard. systemd however has more source code in the binaries, but requires only very simple, descriptive, textual configuration instead of complex init scripts. To me, it seems preferable to have the complexity in a single place instead of distributed across lots of people and projects. Conclusion In a way, you are right. systemd centralizes complexity from tons of init scripts into a single place. However, it therefore makes it very easy for maintainers to write service files (equivalent of an init script) and provides a consistent and reliable interface for service management. Furthermore, it is different than sysvinit, and different solutions often seem complex at first. While systemd consumes more resources than sysvinit, it uses them to make more information available about services; its finer-grained service management requires more state-keeping, but in turn offers you more control over your services.
initscripts
package
(essentially, /etc/rcS.d/*mount*
). Where things get interesting (and,
typically, controversial) is the way in which mountall
leverages
plymouth
to achieve this.
What is plymouth?
There is a great deal of misunderstanding around plymouth, a fact I was
reminded of again while working to get a modern version of upstart into
wheezy. When Ubuntu first started requiring plymouth as an essential
component of the boot infrastructure, there was a lot of outrage from users,
particularly from Ubuntu Server users, who believed this was an attempt to
force pretty splash screen graphics down their throats. Nothing could be
further from the truth.
Plymouth provides a splash screen, but that's not what plymouth is. What
plymouth is, is a boot-time I/O multiplexer. And why, you ask, would
upstart - or mountall, whose job is just to get the filesystem mounted at
boot - need a boot-time I/O multiplexer?
Why use plymouth?
The simple answer is that, like everything else in a truly event-driven
boot system, filesystem mounting is handled in parallel - with no defined
order. If a filesystem is missing or fails an fsck, mountall may need to
interact with the user to decide how to handle it. And if there's more than
one missing or broken filesystem, and these are all being found in parallel,
there needs to be a way to associate each answer from the user to the
corresponding question from mountall, to avoid crossed signals... and lost
data.
One possible way to handle this would be for mountall to serialize the
fsck's / mounts. But this is a pretty unsatisfactory answer; all other
things (that is, boot reliability) being equal, admins would prefer
their systems to boot as fast as possible, so that they can get back to
being useful to users. So we reject the idea of solving the problem of
serializing prompts by making mountall serialize all its filesystem
checks.
Another option would be to have mountall prompt directly on the console,
doing its own serialization of the prompts (even though successful mounts /
fscks continue to be run in parallel). This, too, is not desirable in the
general case, both because some users actually would like to have pretty
splash screens at boot time, and this would be incompatible with direct
console prompting; and because mountall is not the only piece of software
that need to prompt at boot time (see also: cryptsetup).
Plymouth: not just a pretty face
Enter plymouth, which provides the framework for serializing requests to the
user while booting. It can provide a graphical boot splash, yes; ironically,
even its own homepage
suggests that this is its purpose. But it can also provide a text-only
console interface, which is what you get automatically when booting without a
splash
boot argument, or even handle I/O over a serial console.
Which is why, contrary to the initial intuitions of the s390 porters upon
seeing this package, plymouth is available for all of Debian's Linux
architectures in wheezy, s390 and s390x included, providing a consistent
architecture for boot-time I/O for systems that need it - which is any
machine using a modern boot system, such as upstart or systemd.
Room for improvement
Now, having a coherent architecture for your boot I/O is one thing; having
a bug-free splash screen is another. The experience of plymouth in Ubuntu
has certainly not been bug-free, with plymouth making significant demands of
the kernel video layer. Recently, the binary video driver packages in Ubuntu
have started to blacklist the framebuffer kernel driver entirely due to
stability concerns, making plymouth splash screens a non-starter for users of
these drivers and regressing the boot experience.
One solution for this would be to have plymouth offload the video handling
complexity to something more reliable and better tested. Plymouth does
already have an X backend, but we don't use that in Ubuntu because even if
we do have an X server, it normally starts much later than when we would want
to display the splash screen. With Mir on the
horizon for Ubuntu, however, and its clean separation between system and
session compositors, it's possible that using a Mir backend - that can
continue running even after the greeter has started, unlike the current
situation where plymouth has to cede the console to the display manager when
it starts - will become an appealing option.
This, too, is not without its downsides. Needing to load plymouth when using
crypted root filesystems already makes for a bloated initramfs; adding a
system compositor to the initramfs won't make it any better, and introduces
further questions about how to hand off between initramfs and root fs.
Keeping your system compositor running from the initramfs post-boot isn't
really ideal, particularly for low-memory systems; whereas killing the system
compositor and restarting it will make it harder to provide a flicker-free
experience. But for all that, it does have its architectural appeal, as it
lets us use plymouth as long as we need to after boot. As the concept of
static runlevels becomes increasingly obsolete in the face of dynamic
systems, we need to design for the world where the distinction between
"booting" and "booted" doesn't mean what it once did.
Series: | Major Ariane Kedros #1 |
Publisher: | Roc |
Copyright: | December 2008 |
ISBN: | 0-451-46245-9 |
Format: | Mass market |
Pages: | 324 |
echo 'Yes, do as I say!' apt-get -o DPkg::options=--force-remove-essential -y --force-yes install upstart
Thanks to the ifupdown, sysvinit, and udev maintainers for their cooperation
in getting upstart support in place; to the Debian release team for
accomodating the late changes needed for upstart to be supported in wheezy;
and to Scott for his past maintenance of upstart in Debian.
Benchmarking
One of the consequences is that it's now possible to do meaningful
head-to-head comparisons of boot speed between sysvinit (with startpar),
upstart, and systemd. At one time or another people have tested systemd vs.
sysvinit when using bash as /bin/sh, and upstart vs. sysvinit, and systemd
vs. sysvinit+startpar, and there are plenty of bootcharts floating around
showing results of one init system or another on one distro or another, but
I'm not aware of anyone having done a real, fair comparison of the three
solutions, changing nothing but the init system.
I've done some initial comparisons in a barebones sid VM, and the results are
definitely interesting. Sysvinit with startpar (the default in Debian) can
boot a stock sid install, with no added services, in somewhere between 3.37
and 3.42 seconds (three runs). That's not a whole lot, but on the other hand
this is a system with a single filesystem and no interesting services yet. Is
this really as fast as we can boot?
No, even this minimal system can boot faster. Testing with upstart shows that
upstart can do the same job in between 3.03 and 3.19 seconds (n=3, mean=3.09).
This confirms what we'd already seen in Ubuntu, that it makes a difference to
boot speed to have filesystem mounting handled by an integrated process that
understands the whole system instead of as a group of serialized shell
scripts.
What about systemd? The same test gives a boot time between 2.32 and 2.85
seconds (n=4, mean=2.48). Interesting; what would make systemd faster than
upstart in sid? Well, a quick look at the system shows one possible
contributing factor: the rsyslog package in Debian has a systemd unit file,
but not an upstart job file. Dropping in the /etc/init/rsyslog.conf
from
Ubuntu has a noticeable impact, and brings the upstart boot time down nearer
to that of systemd (2.78-3.03s, n=5, mean=2.92). Besides telling me that
it's time to start spamming Debian maintainers with wishlist bugs asking them
to include upstart jobs in their packages, this suggests that the remaining
difference in boot time may be due to the outstanding init scripts in rcS.d
that are made built-in no-ops by systemd but not (yet) by upstart in Debian
(e.g., hwclock
, hostname
, udev-mtab
). (In Ubuntu, /etc/rcS.d has long
since been emptied out in favor of upstart jobs in the common case, since the
time it takes to get to runlevel=2 is definitely a major issue for boot speed
and boot parallelization.)
It also gives the lie to the claim that's been made in various places that
spawning shells is a major bottleneck for upstart vs. systemd. More study is
certainly needed to confirm this, but at least this naive first test suggests
that in spite of the purported benefits of hard-coding boot-time policies in C
code, upstart with its default degree of runtime configurability is at least
in the ballpark of systemd. Indeed, when OpenSuSE switched from upstart to
systemd, it seems that something else in the stack managed to nullify any
benefit from
improving the boot-time performance of apparmor. Contrary to what some
would have you believe, systemd is not some kind of silver bullet for boot
speed. Upstart, with its boot-time flexibility and its long history of
real-world testing in Ubuntu, is a formidable competitor to systemd in the
boot speed department - and a solid solution to the many longstanding
boot-time ordering bugs in Debian, which still affect users of sysvinit.
I've published the bootcharts for the above tests
here. Between the
fact that Debian's bootchart package logs by default to /var/log/bootchart.tgz
(thus overwriting on every boot) and the fact that these tests are in a VM, I
haven't bothered to include the raw data, just the bootcharts themselves. The
interested reader can probably generate more interesting boot charts of their
own anyway - in particular, it will be interesting to see how the different
init systems perform with more complicated filesystem layouts, or when booting
a less trivial set of services.
Other musings
The boot charts have been created with the bootchart
package rather than
with bootchart2
. For one thing, it turns out that bootchart2
includes
systemd units, not init scripts; so when replacing bootchart with bootchart2,
the non-matching init script is left behind and systemd in particular gets
terribly confused. This is now reported as
Bug #694403.
In an amusing twist, while I was experimenting with bootchart2, I also
noticed that having systemd installed would slow down booting with other
init systems, because systemd installs udev rules which take a noticeable
amount of time to run a helper command at boot even though the helper should
be a no-op. So if you're doing boot speed testing of other init systems,
be sure you don't have systemd on the system at the time!
[edit: the Internet is bad at me for my badly spelled german. Spelling corrected. ;)]Lightly coat an 8"x8" pan with cooking spray. Heat oven to 350 degrees. In medium bowl, combine flour, baking powder, salt and Steviva. Add grapeseed oil, milk and egg. Beat at medium speed 4 minutes. Pour batter into prepared pan. Place plums on top, cut side up, pushing down slightly into batter. Sprinkle cloves over the plums. Bake about 50 minutes or until a toothpick tests clean. Let the cake cool in the pan so the plum juices will be reabsorbed to create a moist cake. Sprinkle with confectioners' sugar, if desired, and cut into 16 squares.
- 1 c almond flour
- 1 tsp baking powder
- tsp salt
- c Steviva blend
- 3 tbsp grapeseed oil
- c milk
- 1 large egg
- 12 fresh plums, pitted and halved
- tsp cloves
Lightly coat an 8"x8" pan with cooking spray. Heat oven to 350 degrees. In medium bowl, combine flour, baking powder, salt and Steviva. Add grapeseed oil, milk and egg. Beat at medium speed 4 minutes. Pour batter into prepared pan. Place plums on top, cut side up, pushing down slightly into batter. Sprinkle cloves over the plums. Bake about 50 minutes or until a toothpick tests clean. Let the cake cool in the pan so the plum juices will be reabsorbed to create a moist cake. Sprinkle with confectioners' sugar, if desired, and cut into 16 squares.
- 1 c almond flour
- 1 tsp baking powder
- tsp salt
- c Steviva blend
- 3 tbsp grapeseed oil
- c milk
- 1 large egg
- 12 fresh plums, pitted and halved
- tsp cloves
ia32-libs
, but this time I decided to try multiarch. So I did:
# dpkg --add-architecture i386
# apt-get update
# apt-get install libc6:i386
and magically I was now able to run the printer driver binary. I know there's a lot more work still to be done (I need to check if I can ditch ia32-libs
on my laptop which runs a few more i386 only apps), but this is pretty cool - thanks to all those involved in making it happen!
Update: I tried to install all the multiarch bits required for Skype on my laptop but hit an issue with libqtgui4:i386
which ends up pulling in liblcms1:i386
which isn't yet multiarch enabled. There was already a bug, #637732 filed by vorlon, and mhy did the appropriate NMU a week ago, so it should hopefully hit testing in the next week. Thanks guys.
Subscribe to my newsletter to get my monthly summary of the Debian/Ubuntu news and to not miss further interviews. You can also follow along on Identi.ca, Google+, Twitter and Facebook.
2 comments Liked this article? Click here. My blog is Flattr-enabled.
Next.