Update:
I have succeeded in creating a very simple demo of using the init=
bootparam to specify that a custom binary (written in golang and compiled) should be used in place of the standard init. The binary in that project is compiled for the ARM processor of the Raspberry Pi, but the source should compile for any platform.
Original Post:
I've successfully put init=/bin/bash
in my bootparams and gotten a root shell on boot. Now I'd like to use bootparams to run a "first boot" setup script.
NOTE:
I know there are lots of alternatives that can be offered. Leave those as comments on the question if you'd like. But, I cannot use them; this question is not about them; they are not answers to this question. So, please don't post alternatives as answers.* It's not helpful to people who came here for this question.
Things I've tried that failed:
init="/bin/bash -c 'mount /dev/mmcblk0p1 /boot; date > /boot/test.txt'"
init='/bin/bash -c "mount /dev/mmcblk0p1 /boot; date > /boot/test.txt"'
init="/bin/bash"
init='/bin/bash'
So I'm going to assume that even quoting your init=
param is not an option.
- Correct me if I am wrong here.
I have read The Linux Kernel documentation on the matter. It says:
The kernel parses parameters from the kernel command line up to
--
; if it doesn’t recognize a parameter and it doesn’t contain a.
, the parameter gets passed to init: parameters with=
go into init’s environment, others are passed as command line arguments to init. Everything after--
is passed as an argument to init....
init= [KNL] Format: <full_path> Run specified binary instead of /sbin/init as init process.
Lesson learned:
That Format: <full_path>
would explain why it doesn't like me putting a full command (or multiple) in the init=
I have also read BOOTPARAM(7) (search for "passed to the init process") where they say:
Anything of the form 'foo=bar' that is not accepted as a setup function as described above is then interpreted as an environment variable to be set. A (useless?) example would be to use 'TERM=vt100' as a boot argument.
Any remaining arguments that were not picked up by the kernel and were not interpreted as environment variables are then passed onto PID 1, which is usually the init(1) program. The most common argument that is passed to the init process is the word 'single' which instructs it to boot the computer in single user mode, and not launch all the usual daemons. Check the manual page for the version of init(1) installed on your system to see what arguments it accepts.
- Are there any working examples of using this info to pass arguments to a custom specified
init=
?
If there is, it's hard to find and this question will serve to make it show up in Google results. If there is not, we'll create a working example for the community.
bash -c '$@' bash /bin/echo -arg1 -arg2
works in the shell. So maybeinit=/bin/bash -- -c $@ bash /path/to/executable -arg1 -arg2
. – sourcejedi Mar 05 '18 at 19:29executable
has finished. – sourcejedi Mar 05 '18 at 19:35init=
is not quite relevant. For an example of an init system which accepts various arguments passed using this mechanism, see the original sysvinit. http://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/init.c?id=3f98f493ff9331bf41ddf5d734729f9d5a89d73a#n2929 It accepted arguments like "single". I am fairly confident the-s
option the source code mentions would have been equally striaghtforward to pass on the kernel command line.exec /sbin/init
, and simply pass that script as the init. It sounds like you don't want that for some reason though. – sourcejedi Mar 05 '18 at 19:45/boot
where I am able to modify files, then that would be acceptable. What I'm trying to avoid is where people say things like "don't touch your kernel parameters". – Bruno Bronosky Mar 06 '18 at 10:25init=/bin/bash -c <some command>
, the system will execute that command as process #1, and once the command is complete, process #1 dies - which results in a kernel panic, as process #1 is not supposed to just die. – telcoM Mar 06 '18 at 12:56