diff --git a/README b/README deleted file mode 100644 index b9b9528..0000000 --- a/README +++ /dev/null @@ -1,68 +0,0 @@ - - This directory contains the source code for a tiny init devised for - the Pygos system. - - The main goal of this project is to create a simple framework for: - - system boot up and initialization - - service supervision - - With the additional aims of having something that: - - simply works - - is easy to understand - - is easy to configure and maintain - - - The init process is intended to run on top of Linux and makes use of some - Linux specific features (e.g. signalfd), but if sufficient interest exists, - it should still be possible to make it run on some BSDs or whatever else. - - The init system tries to mimic the concept of unit files from systemd as - those were considered to be a good design choice. - - Right now, the system is in a "basically works" proof of concept stage and - needs some more work to become usable. - - There are plans for *maybe* *eventually* adding support for Linux name - spaces, seccomp filters and cgroups as needed in the medium future. - - - There are already a bunch of similar projects out there that have been - considered for use in the Pygos system. The reason for starting a new - one was mainly dissatisfaction with the existing ones. Other Projects - that have been considered include: - - - systemd - Contains a lot of good ideas, but it is HUGE. It has tons of - dependencies. It implements tons of things that it simply shouldn't. - It has a horrid, "modern", python based, hipster build system. - It's simply too damn large and complex. - - - SystemV init - A bad combination of unnecessary complexity where it isn't needed and a - complete lack of abstraction where it would be needed. Shell script - copy and paste madness. There are reasons people started developing - alternatives (other than "hurr-durr-parallel-boots"). - - - upstart - Seems nice overall, but needlessly big and complex for the intended - use case in Pygos. Would have needlessly added D-Bus to the system. - - - OpenRC - Was already integrated into Pygos. Things turned out to be broken. - Upstream developers did not accept fixes (after ignoring them for weeks - and preferring typo fixes instead). Complaints from other people who - tried to contribute fixes were observed on Github. Complaints from - package maintainers about deteriorating code quality were observed - on the official IRC channel. Documentation is non-existent. - - - daemontools and similar (runnit, s6, minit, ...) - The sixties are over. And even code from that era is more readable. The - source code for those projects should better be tossed out the window and - rewritten from scratch. If you are a first semester CS student and you - hand something like this in as a homework, the best you might get is a - well deserved slap on the back of your head. - - - busybox init - Nice and simple. Probably the best fit if the rest of your user space is - busybox as well. - diff --git a/README.md b/README.md new file mode 100644 index 0000000..a944831 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +# About + +This directory contains the source code for a tiny init devised for +the Pygos system. + +The main goal of this project is to create a simple framework for: + +- system boot up and initialization +- service supervision + +With the additional aims of having something that: + +- simply works +- is easy to understand +- is easy to configure and maintain + + +The init process is intended to run on top of Linux and makes use of some +Linux specific features (e.g. signalfd), but if sufficient interest exists, +it should still be possible to make it run on some BSDs or whatever else. + +The init system tries to mimic the concept of unit files from systemd as those +were considered to be a good design choice. + +Those parameterizeable service description files are stored in `/usr/share/init` +by default. Services are enabled by creating a symlink in `/etc/init.d`. This +can be done using the `service` command line tool. + +See [docs/services.md](docs/services.md) for more information on service +description files. + +See [docs/bootup.md](docs/bootup.md) for more information on what the init +daemon does during system boot. + + +Right now, the system is in a "basically works" proof of concept stage and +needs some more work to become usable. + +There are plans for *maybe* *eventually* adding support for Linux name +spaces, seccomp filters and cgroups as needed in the medium future. + + +## Why + +There are already a bunch of similar projects out there that have been +considered for use in the Pygos system. The reason for starting a new +one was mainly dissatisfaction with the existing ones. Other Projects +that have been considered include: + +- systemd + + Contains a lot of good ideas, but it is HUGE. It has tons of + dependencies. It implements tons of things that it simply shouldn't. + It has a horrid, "modern", python based, hipster build system. + It's simply too damn large and complex. + +- SystemV init + + A bad combination of unnecessary complexity where it isn't needed and a + complete lack of abstraction where it would be needed. Shell script + copy and paste madness. There are reasons people started developing + alternatives (other than "hurr-durr-parallel-boots"). + +- upstart + + Seems nice overall, but needlessly big and complex for the intended + use case in Pygos. Would have needlessly added D-Bus to the system. + +- OpenRC + + Was already integrated into Pygos. Things turned out to be broken. + Upstream developers did not accept fixes (after ignoring them for weeks + and preferring typo fixes instead). Complaints from other people who + tried to contribute fixes were observed on GitHub. Complaints from + package maintainers about deteriorating code quality were observed + on the official IRC channel. Documentation is non-existent. + +- daemon tools and similar (runnit, s6, minit, ...) + + The sixties are over. And even code from that era is more readable. The + source code for those projects should better be tossed out the window and + rewritten from scratch. If you are a first semester CS student and you + hand something like this in as a homework, the best you might get is a + well deserved slap on the back of your head. + +- busybox init + + Nice and simple. Probably the best fit if the rest of your user space is + busybox as well. + diff --git a/docs/bootup.md b/docs/bootup.md new file mode 100644 index 0000000..1f107bd --- /dev/null +++ b/docs/bootup.md @@ -0,0 +1,71 @@ +# System Bootup Process + +## Initial Ram Disk to Rootfs transition + +After mounting the root filesystem, either the kernel or the initial ram disk +startup process is expected to exec the init program from the root filesystem. + +At the current time, there is no support for re-scanning the service files +*yet*, so when init is started, the final configuration in `/etc/init.d` has to +be present. As a result, we currently cannot perform mounting of `/etc/` or +packing init into the initial ram disk and doing the rootfs transition. + +Also, as a result of this, changing the service configuration requires a system +reboot to be effective. + +This _will_ change in the future. + + +## Processing Service Descriptions + +The init process reads service description files from `/etc/init.d` which are +usually symlinks to actual files in `/usr/share/init`. + +The exact locations may be changed through configure flags when compiling init. + +Service files specify a *target* which is basically like a SystemV runlevel and +can be one of the following: + +* boot +* reboot +* shutdown +* ctrlaltdel + +After parsing the configuration files, the init process starts running the +services for the `boot` target in a topological order as determined by their +*before* and *after* dependencies. + +Services can be of one of the following *types*: + +* wait +* once +* respawn + +Services of type `wait` are started exactly once and the init process waits +until they terminate before continuing with other services. + +The type `once` also only runs services once, but immediately continues +starting other services in the mean time without waiting. + +Services of type `respawn` also don't stall the init process and are re-started +whenever they terminate. + +## Service Process Setup + +If a service description contains only a single `exec` line, the init process +forks and then execs the command directly in the child process. + +If the service description contains a `tty` field, the specified device file +is opened in the child process and standard I/O is redirected to it before +calling exec. Also, a new session is created. + + +If a service description contains multiple `exec` lines, the init process forks +off to a single child process that does the same setup as above, and then runs +the command lines sequentially by forking a second time for each one, followed +by an exec in the grand child and a wait in the original child. + +If a single command line returns something other than `EXIT_SUCCESS`, +processing of multiple command lines is immediately stopped and the offending +exit status is returned to init. + diff --git a/docs/services.md b/docs/services.md new file mode 100644 index 0000000..223cfb5 --- /dev/null +++ b/docs/services.md @@ -0,0 +1,110 @@ +# Service Files + +Services that can be started and managed by init are described by service +description files stored in `/usr/share/init`. + +The init process actually reads from `/etc/init.d` which contains symlinks to +the actual service files. + +Enabling a service means adding a symlink, disabling means removing a symlink. + +Service descriptions can be parameterized. The arguments are extracted from the +name of the symlink. Currently only 1 parameter is supported. The argument +value is separated from the service name by an '@' character in the symlink +name. + + + +Below is an annotated example for a simple, service description for a +generic, parameterized agetty service: + + # + # The text that init should print out when the status of the + # service changes. + # + # The '%0' is replaced with the first argument extracted from the + # symlink name. + # + description "agetty on %0" + + # + # How to run the service. 'respawn' means restart the service when it + # terminates, 'once' means run it only once and continue with other + # services in the mean while, 'wait' means run it once, but block until + # it exits. + # + type respawn + + # + # When to start the service. 'boot' means when booting the system. Other + # options are 'reboot', 'shutdown' and 'ctrlaltdel'. The system always + # starts into the 'boot' target and then later transitions to one of the + # others. + # + target boot + + # + # A list of service names that must be started before this service can + # be run, i.e. this services needs to be started after those. + # + # This can only refer to generic names, not specific instances. For + # instance, you can say "after getty" to make sure a service comes up after + # all gettys are started, but you cannot specify "after agetty@tty1". + # + # Similar to 'after', there is also a 'before' keyword for specifying + # dependencies. + # + after sysinit + + # + # The 'tty' directive specifies a file to which all I/O of the process is + # redirected. The specified device file is used as a controlling tty for + # the process and a new session is created with the service process as + # session leader. + # + # In this example, we derive the controlling tty from the service + # description argument. + # + tty "/dev/%0" + + # + # The 'exec' directive specifies the command to execute in order to start + # the service. See in the example below on how to run multiple commands. + # + # Again we use the argument to specify what terminal our getty + # should run on. + # + exec agetty %0 linux + +As can be seen in this simple example, each line in a service description is +made up of a keyword, followed by one or more arguments and terminated by a +line break. + +Blank lines are ignored and shell-style comments can be used. + +Arguments are separated by space. Quotation marks can be used to treat +something containing spaces or comment character as a single argument. + +In between quotation marks, C-style escape sequences can be used. + +Argument substitution (arguments derived from the symlink name) can be +done using a '%' sign, followed by the argument index. A '%' sign can be +escaped by writing '%%'. + + +If a service should sequentially run multiple commands, they can be grouped +inside braces as can be seen in the following, abbreviated example: + + description "mount /var" + type wait + target boot + before vfs + exec { + mount -t tmpfs none /var + mkdir /var/log -m 0755 + mkdir /var/spool -m 0755 + mkdir /var/lib -m 0755 + mkdir /var/tmp -m 0755 + mount --bind /cfg/preserve/var_lib /var/lib + } +