Linux Init Script – Can the Init Process Be a Shell Script?

initinit-scriptlinux

I was going through a tutorial on setting up a custom initramfs where it states:

The only thing that is missing is /init, the executable in the root of
the initramfs that is executed by the kernel once it is loaded.
Because sys-apps/busybox includes a fully functional shell, this means
you can write your /init binary as a simple shell script (instead of
making it a complicated application written in Assembler or C that you
have to compile).

and gives an example of init as a shell script that starts with #!/bin/busybox sh

So far, I was under the impression that init is the main process that is launched and that all the other user space process are eventually children of init. However, in the given example, the first process is actually bin/busybox/ sh from which later init is spawned.

Is this a correct interpertation? If I were, for example, have a available interpreter available at that point, I could write init as a Python script etc.?

Best Answer

init is not "spawned" (as a child process), but rather exec'd like this:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

exec replaces the entire process in place. The final init is still the first process (pid 1), even though it was preceded with those in the Initramfs.

The Initramfs /init, which is a Busybox shell script with pid 1, execs to Busybox switch_root (so now switch_root is pid 1); this program changes your mount points so /mnt/root will be the new /.

switch_root then again execs to /sbin/init of your real root filesystem; thereby it makes your real init system the first process with pid 1, which in turn may spawn any number of child processes.

Certainly it could just as well be done with a Python script, if you somehow managed to bake Python into your Initramfs. Although if you don't plan to include busybox anyway, you would have to painstakingly reimplement some of its functionality (like switch_root, and everything else you would usually do with a simple command).

However, it does not work on kernels that do not allow script binaries (CONFIG_BINFMT_SCRIPT=y), or rather in such a case you'd have to start the interpreter directly and make it load your script somehow.

Related Question