AUTHOR: Boris Buegling DATE: 2004-03-28 LICENSE: The MIT License SYNOPSIS: Replacing init with minit DESCRIPTION: Using minit as a smaller and faster replacement for the default LFS sysvinit package. PREREQUISITES: LFS 5.0+ HINT: Contents ======== 1. Introduction 2. Downloading the software 3. Installation 4. Configuration 5. Beyond minit 6. Feedback and Resources Introduction ============ The SystemV init(1) approach of booting Unix systems was a good idea at its time and during the years it has become the de-facto standard for booting Linux and many other Unix systems (as far as I know it is not an official POSIX standard). However, many people are unsatified with the features sysvinit gives them in contrast to its size and its complicated structure, therefore many different alternatives are available today. In this hint, I'm going to present one of the best of them and describe how you can setup it on your LFS system. Advantages of minit: - very small - can respawn processes if they die - can handle dependencies between services - much faster than init(1), because it starts services paralell - more flexible controlling and logging mechanisms Disadvantages: - no mechanism for kill scripts (I'm providing a workaround for this in my minit-scripts package, though) - harder to setup, because there are not so many sample scripts out there (partially fixed by my minit-scripts package, too) - you need to install a bunch of additional, yet small, software Downloading the software ======================== 1. Minit available via http://www.fefe.de/minit/minit-0.9.1.tar.bz2 Obviously, this is required for following this hint. 2. Dietlibc available via http://www.kernel.org/pub/linux/libs/dietlibc/ dietlibc-0.25.tar.bz2 A very small libc replacement, which is used by minit, so it is also a must-have. 3. Daemontools (optional) available via http://cr.yp.to/daemontools/daemontools-0.76.tar.gz If you want to profit from the advanced logging mechanism minit provides, you should also install this package, which comes with the excellent multilog. 4. Fgetty (optional) available via http://www.fefe.de/fgetty/fgetty-0.6.tar.bz2 You do not need that, but when you're starting to replace your init system anyways, you can just as well get rid of the bloated agetty, which is installed by default during LFS installation. 5. Graphviz (optional) available via http://www.graphviz.org/pub/graphviz/graphviz-1.9.tar.gz If you want to have a nice graphical overview of your minit process, you can get that with a script from the minit-package. You will need graphviz to play with that. Requirements: standard BLFS installations of libpng, libjpeg, freetype2 and Tcl/Tk. 6. Feh (optional) available via [todo] This is a real fast image viewer, which you can use for the graphical init overview, too. Requirements: giblib 7. giblib (optional) available via [todo] Requirement for Feh. Requirements: standard BLFS installation of imlib2. 8. Minit-scripts (optional, but highly recommended) available via http://www.icculus.org/~boris/data/minit-scripts.tar.bz2 These are the scripts I'm currently using on my system to replace the default LFS bootscripts. If you do not intend on copy and pasting much stuff from this hint and you also want some scripts for standard BLFS services, you should download it. It also includes some additional utility script for enhancing your control over the services running on your system. 9. Patches If you choose to install daemontools, you will need the following pacthes: http://www.fefe.de/daemontools/daemontools-0.70-man.diff.bz2 http://www.icculus.org/~boris/crazy/daemontools-errno http://www.icculus.org/~boris/crazy/daemontools-POSIX If you choose to install graphviz, you will need the following patches: http://www.icculus.org/~boris/crazy/graphviz-posix http://www.icculus.org/~boris/crazy/graphviz-fix Installation ============ Note: The following instructions will not remove your ability to use the standard sysvinit booting mechanism, it will be an additional possibility to boot your system. However, you can choose to completely move your system to minit later on. Installing Dietlibc ------------------- This is a smaller and faster, yet incomplete implementation of the standard C runtime library (glibc on typical Linux systems). It will be installed into /opt/diet to not alter your system's libc. cp diet.c diet.c.orig sed s/-malign/-falign/g < diet.c.orig >diet.c make make install Installing Minit ---------------- export PATH=$PATH:/opt/diet/bin make make install install minit pidfilehack write_proc hard-reboot minit-update /sbin install msvc /bin install -m 750 shutdown /sbin/minit-shutdown install -m 644 hard-reboot.8 minit-list.8 minit-shutdown.8 \ minit-update.8 minit.8 msvc.8 pidfilehack.8 /usr/share/man/man8 mkfifo -m 600 /etc/minit/{in,out} Installing Daemontools ---------------------- The daemontools package is a replacement for the internet superserver inetd. It is not needed to run minit, however the multilog program, which comes with the package, can be used for minit's additional logging mechanism, which are quite powerful and interesting. When you unpack the package, a directory called 'admin' will be created. The actual package will be hidden in there, because the package conforms to Dan Bernstein's slashpackage (see Resources for more information) convention. bunzip2 -c ../daemontools-0.70-man.diff.bz2|patch -Np1 patch -Np1 -i ../daemontools-errno patch -Np1 -i ../daemontools-POSIX package/compile cd package sed 's|command|usr/sbin|' boot.inittab > boot.inittab~ mv boot.inittab~ boot.inittab cd ../command sed -e 's|/command:/usr/bin:/usr/sbin:||' -e 's|command|usr/sbin|' \ -e 's|/service|/etc/service|g' svscanboot > svscanboot~ mv svscanboot~ svscanboot chmod 555 svscanboot cp * /usr/sbin If you plan on using the daemontools package for djbdns (a better replacement for bind) or qmail (a secure and complicated mail-server), you might want to put svscanboot into working. See Resources for more information. cat ../package/boot.inittab >>/etc/inittab mkdir -p /etc/service Installing Fgetty ----------------- This can be used as a smaller replacement for the standard LFS agetty program. However, agetty will not be overwritten by the following instructions. Fgetty needs the absolute path to the tty device, in contrast to agetty, which only needs the relative path. export PATH=$PATH:/opt/diet/bin make make install Installing Graphviz ------------------- Make sure you have installed the requirements as listed above. patch -Np1 -i ../graphviz-posix patch -Np1 -i ../graphviz-fix ./configure --prefix=/usr make make install Installing giblib ----------------- Make sure you have installed imlib2 by the BLFS book instructions before you proceed. ./configure --prefix=/usr make make install Installing Feh -------------- Make sure you installed giblib before proceeding. This program is a fast and excellent image viewer which will serve you well. ./configure --prefix=/usr make make install Configuration ============= Now you have everything installed to replace init on your system. For the installation of bootscripts, there are two possibilities: a) Just install minit-scripts and only get basic information about the inner working of minit. b) Learn about the inner workings of minit to be able to write your own scripts and improve your understanding of Unix. Remember, all I'm offering is the truth, nothing more.... a) The easy way (TM) -------------------- **** 1. bootscripts **** ** Installation First, install the scripts and the updated functions file (compatible with LFS bootscripts, so don't worry that it gets overwritten). make install Now, you should install the default depends by running: make install-default If you have installed daemontools and you want to use multilog as a logging service, you should run make install-multilog If you use hotplug to manage your modules (as discussed in Alexander Patrakov's hint 'hardware-detection.txt'), you can add the necessary dependencies to the script by running the following command: make install-hotplug Now we're going to install the getty configuration (you need that to do a console login). The following instructions will install /etc/sysconfig/minit.tab, which will replace the getty handling usually done by /etc/inittab. All is well if you want to use fgetty and 24 tty consoles, if not, you should edit the minit.tab according to your needs. The second command will automatically create the getty services for all gettys. make install-sysconf make install-getty If you use wwwoffled (not covered by this hint or by BLFS), you need a little hack to get it to work with minit, so I explicitly cover it here. An explanation of the hack can be found in /etc/minit/wwwoffle/README and the following command sets the hack up on your system. You still need to add wwwoffle to your /etc/minit/default/depends if you want it to be started automatically on boot. make install-wwwoffle If you have just installed LFS you are nearly done now, you will need to add the appropriate services to /etc/minit/default/depends though, if you want to install packages from BLFS. The default installation handles everything done in the LFS book, though. ** Adding new services to /etc/minit/default/depends The minit-scripts package brings bootscripts for several different BLFS packages. You can easily add services to your default startup file by following this procedure: First, locate your service in /etc/minit. Let's assume you have installed Apache as by the BLFS book and you want to start it up on boot now. When you look into /etc/minit, you will see that there is already a premade script for apache. Adding the service is simple, just do this: echo apache >>/etc/minit/default/depends If you want to add another service, 'apache' needs to be replaced by the actual service directory, of course. The nice thing is, that you do not need to worry about where to add a certain service, because minit takes care of dependencies and the minit-scripts package specifies them for all included scripts. ** Removing services Just delete the corresponding line in /etc/minit/default/depends if you want to remove a certain service from the startup scripts. **** 2. using minit for bootup **** If you have added all the services you want, you can now test your new setup. If you use grub add init=/sbin/minit to your 'kernel' line in /boot/grub/menu.lst. If you use lilo add append="init=/sbin/minit" to your /etc/lilo.conf and re-run lilo. Now reboot. If you encounter any problems, do not forget that there is no warranty for anything done in this hint and that I am in no way responsible for any burning computers, cats or furbys which will probably be created when using this hint. That said, refer to the advanced instructions or the additional information given in Resources for hints on how to fix your problems and see Feedback for information on how to contact me. b) the hard way (TM) -------------------- Of course it is nice to install all the bootscripts automatically, but if you would want this, you wouldn't be here, so I'm going to cover everything you ever want to know about minit in this section and even a bit more. ** Structure The minit boot process consists of two major components, minit itself which will be run as process 1 like init(1) and msvc, the management interface which can, among other things, start and stop daemons. By using this scheme, you will have more control over your services. In the sysvinit world, you have to handle status reports and stop scripts yourself, msvc will give you this automatically, in addition to that, it can also respawn processes if they die, this is especially useful for network daemons. Let's take a look at the bootscripts itself. Every service has its own service directory in /etc/minit, which can include the following components: depends A list of services this service depends on. If they are not already runing, minit will start all of them before starting the service itself. run This can be two things: For simple services, like initializing the swap partition, this is just a symlink to the program which will be started. If you need more than that or you want to have shell expansion (for variables, etc.), you can also make it a script. params This file specifies the parameters of the run program. Every line must only consist of one word, e.g. for mountproc, it looks like this: Lenin:/etc/minit/mountproc$ cat params -n /proc respawn Touch this file if you want this service to be respawned if it exists. This is especially useful for network services. sync Touch this file if you want to make minit wait until this service ends. This is needed for static initializations like 'localnet' or the hotplug service. log If this directory exists, it will be run like any other service and the stdout of the current service will be connected to the stdin of the logging service. If the log service can not be started the service will be blocked when it writes to stdout. If the log process dies, no information will be lost and it will be immediately restarted, which makes this system much more reliable than syslog. The multilog program from daemontools can be used as such a log service. You will now understand that this scheme of services is much easier to use than writing sysvinit-style scripts. As an example look at the swap service: The scripts from lfs-bootscripts-1.x is 41 lines long (granted that includes comments and messages, but even if you strip it of everything, you will still need ~20 lines). In contrast to that, /etc/minit/swap from minit-scripts consists of a symlink to /sbin/swapon, two files with one line and the empty sync file. There are some service directories with a special meaning: ctrlaltdel This service is run if you press Ctrl+Alt+Del on the console, similar to the ctrlaltdel from /etc/inittab. default This service will be run on system bootup. If you want a bsd-style init you can just put all your initialization into default/run. Normally, you will put all the services which should be run on bootup into default/depends though. kbreq This will be started when the 'keyboard request' is issued (configurable with loadkeys). ** Supervised services As you know by now, all the services minit starts are supervised by msvc(8). You can just run 'msvc $service' to get a status message of that service. You can also send signals to the process (see the manpage for commandline switches) and finally you can start and stop services. However, you can not just run the ctrlaltdel service to bring your system down, because msvc does not work recursively. There is /sbin/minit-shutdown to reboot and halt your system, but it is not a good idea to run it directly when using minit-scripts which will I explain later. For rebooting and shutting your system down, use echo -n "s$service" >/etc/minit/in This will start the service without a monitoring msvc service. I provide premade replacements for reboot and shutdown in the scripts/ directory of minit-scripts. Note that you should never use reboot, halt or shutdown from the sysvinit package, because they will not work as expected. You can easily see all services which are running by using minit-list from the scripts/ directory. Keep in mind that only root can use msvc and the scripts though, because the named pipes (man fifo) /etc/minit/in and out can only be read and written by root. You should not change this for security reasons. If you are curious which running services depend on a certain service, you can use the depends.sh script. If you want a graphical overview of your service tree, you can run make show-graph in the minit-scripts directory. ** Logging with multilog I explained above why minit's logging mechanism is more reliable then the standard Unix syslogd. I will explain the usage of that mechanism with djb's multilog now, make sure you have daemontools installed before proceeding. Setting up the log directory is pretty easy: mkdir log ln -s /usr/sbin/multilog run echo -e "t\n./main" >params You already know that this will run multilog with the parameters t and ./main, but what does that do? t Inserts a precise timestamp in djb's tai64n(8) format in front of every log entry. ./main This puts the logging information into the directory main in the current directory. You can change this if you want to collect the logs in a central place like /var/log/$service. For more information on how to automatically filter the logs or sort them into several separate files, you should read the multilog manpage. For an easier setup of multilog log services, just use the log.sh script from minit-scripts. If you want to keep the logs in the /etc/minit/$service/log/main directory, like me, and you want to easily see all the log messages, you can use my clogs.sh script, which will print all the logs from all the running services to stdout. ** Adding a K##-like mechanism to minit When using sysvinit, you need to write stop-functions for every service you want to kill. With minit, shutting down the services and unmounting the filesystems is automatically handled by minit-shutdown(8). Unfortunately, there are some things which need a special shutdown method or which should do something completely different on shutdown. Of course, you can start and write sync'ed services for all these things and put them into the depends of your shutdown service. IMHO, this approach does not scale, because you need to add these things to reboot and shutdown depends and you need to keep track of two services for some packages. Therefore, I provide an additional kill mechanism for this in minit-scripts. The shutdown and ctrlaltdel service both depend on the kill service, which will look into all the service directories specified in /etc/minit/default/depends and will run the kill program in there, if it exists: [/etc/minit/kill/run] (this script was inspired by Zack Winkles create_files function from lfs-bootscripts-2.0.x) echo # This connects the depends file to stdin and redirects the new file # descriptor 9 to the old stdin exec 9>&0 < /etc/minit/default/depends # This reads from stdin while read svc junk do # Check if there is a kill program for the service if [ -x "/etc/minit/$svc/kill" ] then # Run it echo "Killing $svc..." /etc/minit/$svc/kill fi done # This resets the stdin file descriptor to its old value exec 0>&9 9>&- [end of script] Of course, this script is provided in the minit-scripts package. The kill program for services does not currently work like run, because it does not have an associated params file. Therefore, you will need to make it a script at the moment. ** Writing your own service directories There are already a bunch of services covered by minit-scripts and I plan to add scripts for all the BLFS packages in a future version, making minit-scripts a complete replacement for the LFS bootscripts. Nevertheless, you will come to the point where you want to write your own scripts. For static initialization, this is easy, you can just create a run script, look at cleanfs or alsa for simple examples from the minit-scripts package. For running daemons, you have to keep in mind that sysvinit is the de-facto standard for running services on Linux. Because of this, most daemons fork themselves into the background or do not write a correct pidfile (man getpid). For the supervised approach of minit, the service needs to run in the foreground, though. For running these daemons, Felix von Leitner wrote the pidfilehack(8) utility. In the follwing, I will give examples for creating a service directory with and without pidfilehack. **** Services with pidfilehack, using apache as an example If you have already installed the minit-scripts package by following the easy instructions, you will have an /etc/minit/apache diretory, so we will remove it: rm -rf /etc/minit/apache Create the directory and go there: mkdir /etc/minit/apache cd /etc/minit/apache Now we need to link pidfilehack to run: ln -s /sbin/pidfilehack run Our service name is apache echo apache >params Apache writes a correct pidfile echo /var/www/logs/httpd.pid >>params We need to pass the absolute path of the program we want to run: echo /usr/sbin/apachectl >>params Following this, we can put all the arguments we need to pass to the program, in this case it is only one: echo start >>params Now, you need to decide if you want the service to be respawned, in this case it is a network daemon, and you will want to: touch respawn Apache does not need to be synced, so we don't need to touch that file. Finally, we need to specify the dependencies of our service: echo network >depends Note that i use 'firewall' in minit-scripts, because I want to have iptables setup before starting any network services. In reality, apache only depends on the network being up, therefore I chose this example. If you want to log what the service writes to stdin, you can setup a log service now, as discussed above. **** Service without pidfilehack, using portmap as an example Portmap forks itself to the background by default, but it supports the command-line switch -d for debugging, which we can abuse here. As it is also included in minit-scripts, you possibly need to delete the directory and then create it and change to it. ln -s /sbin/portmap run echo -d >params The other files are created similar to the apache example. ** Installation of minit-scripts If you haven't already read section a), you should do it now, as it covers the installation of minit-scripts package, which includes a complete set of bootscripts which can be used with minit, as well as the scripts discussed in this section. ** Conclusion If you have followed the hint to this point, you have learned much about the initialization process of a Unix system, and how it was improved by minit. I hope you enjoyed the hint and learned that the default way of doing things is not always the best. Beyond minit ============ ** What I plan to do in future versions of this document - Provide replacements for all the lfs-bootscripts 2.0.x - Describe how to completely replace sysklogd with multilog and how to replace klogd with od_syslogd (see Resources). - Describe how to use the other programs from the daemontools package to replace (x)inetd. - Making the system more robust by additional services ** Journey to a smaller and better Unix system This document is my starting point to finally implement many nice pieces of software from the dietlibc- and djb-world, as I call it. I am planning to write other hints about using the dietlibc as a replacement for glibc, replacing the standard GNU utilities and using djb's network servies, as they are removed from the BLFS book now. This is a long term plan and it might take a while before all those hints actually show up. Feedback and Resources ====================== ** Feedback If you have any idea for improvement, you need help with the information contained in this document or you know 'How Saddam survived', feel free to contact me at boris@icculus.org. However, if you ask a question already answered here or in the material the links point to or if you flame me for anything, I will ignore your mail and put you onto my blacklist. ** Resources http://www.icculus.org/~boris/minit.txt Get a fresh version of the hint from there. http://www.icculus.org/~boris/init.html Primary location of this hint and the place where bugfixes and additional information might pop up. http://www.fefe.de/minit/ The minit homepage. You can find links to additional documentation, as well as sample /etc/minit configurations there. Grab new versions of minit from there, too. http://www.fefe.de Homepage of Felix von Leitner, who has written minit, dietlibc, fgetty and many other small and fast programs which replace standard bloated stuff. http://cr.yp.to Homepage of Dan J. Bernstein, who has written daemontools and some other interesting daemons and libraries. If you like the way minit works, you may like djb's software, too. http://homepage.dtn.ntl.com/richard.downing/betterboot/index.html A hint by Richard A Downing for runit, another smaller and better replacement for sysvinit. http://www.math.fu-berlin.de/~dreesen/diet_it/ Homepage of od_syslogd, a smaller replacement for syslogd and klogd. ACKNOWLEDGEMENTS: The fix for getting rid of the gcc warnings in dietlibc was taken from Richard A Downing's runit hint (Resources for the URL). I'm not sure of where I got the daemontools instructions from, if I recall it correctly, it was from the old BLFS daemontools page. See CREDITS in the minit-scripts package for some people who inspired my init scripts. CHANGELOG: [2004-03-28] * Updated dietlibc to 0.25 * Added a note about absolute paths to fgetty instructions [2004-03-26] * First usable version of the hint. [2004-03-25] * Initial writing of the hint.