About the ability to run custom commands from initrd's init
SlackwareThis Forum is for the discussion of Slackware Linux.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
About the ability to run custom commands from initrd's init
An idea exposed by me in another thread, which I think is worth more attention: I talk about customizing the initrd, because I think there's a huge lack on the infrastructure of initrd used by Slackware: the hooks for it.
Or at least, a way to merge a small custom script at the near end of "/boot/initrd-tree/init"
The single way I found today, even on slackware-current, to make my customization to survive to a clean generation of the initrd, is to modify this "/init" script within "/usr/share/mkinitrd/initrd-tree.tar.gz" then to careful watch if an upgrade of package will overide it or not.
Code:
...
else
echo
echo "RESCUE mode"
echo
echo " You can try to fix or rescue your system now. If you want"
echo " to boot into your fixed system, mount your root filesystem"
echo " read-only under /mnt:"
echo
echo " # mount -o ro -t filesystem root_device /mnt"
echo
echo " Type 'exit' when things are done."
echo
/bin/sh
fi
##########################################################
# HERE YOU CAN RUN CUSTOM MOUNTING OR WHATEVER
##########################################################
# Need to make sure OPTIONS+="db_persist" exists for all dm devices
# That should be handled in /sbin/mkinitrd now
/sbin/udevadm info --cleanup-db
/sbin/udevadm control --exit
unset ERR
mount -o move /proc /mnt/proc
mount -o move /sys /mnt/sys
mount -o move /run /mnt/run
[ "$DEVTMPFS" = "1" ] && mount -o move /dev /mnt/dev
echo "${INITRD}: exiting"
exec switch_root /mnt $INIT $RUNLEVEL
Why we need sometimes to run custom commands from this initrd script? For example, for mounting the /usr when it is hosted in a separate storage device, or any fine tuning considered to be done before switching to the real operating system.
I think that could be resolved this by modifying the /sbin/mkinitrd to look for a script named "/boot/initrd.sh" and if it exists, its content to be merged or injected using sed or whatever, in a certain place from "/boot/initrd-tree/init" before it to be compressed.
Please note that today any customization of "/boot/initrd-tree/init" is gone if the user generates cleanly another initrd.
Last edited by LuckyCyborg; 06-09-2019 at 12:27 PM.
How does this relate to using /etc/mkinitrd.conf to customize the /sbin/mkinitrd command? There are man pages for both mkinitrd and mkinitrd.conf as well as more info can be found in the /etc/mkinitrd.conf.sample file.
How does this relate to using /etc/mkinitrd.conf to customize the /sbin/mkinitrd command? There are man pages for both mkinitrd and mkinitrd.conf as well as more info can be found in the /etc/mkinitrd.conf.sample file.
Please be kind to explain me how you configure today an initrd to run before to switch to the real operating system, the following command:
Code:
mount -t ext4 /dev/sda3 /mnt/usr
This use case, to run certain custom commands on initrd, well... it is not supported today.
There are many options given, but none for adding custom scripts or commands on initrd.
Last edited by LuckyCyborg; 06-09-2019 at 01:45 PM.
Simple: by running mkinitd without the "-c" option. Customize whatever and wherever you want, just do not use the "-C" option.
Well, it is not that simple. Usually, the user will want to generate a clean initrd, because s/he do that after a kernel update, or even some packages update.
Unless using "-C" option, the initrd will grown and grown, and forever grown, hosting modules for multiple kernels from the past and multiple variants of libraries. And what if the user updates the mkinitrd package itself?
I would like to note that to offer the ability to run custom commands on initrd, some of the other distributions uses the concept of "hooks", like described there for Arch Linux:
Howver, what I ask is not a full implementation of those initrd "hooks" or "modules", but just the ability to define somewhere a script and/or custom commands which could be integrated in initrd, no mater if it is is clean generated or not.
Last edited by LuckyCyborg; 06-09-2019 at 02:45 PM.
I guess that it is hard to notice the disadvantages of the monolithic setup used for initrd by Slackware, unless you need to customize it in a daily basis.
Regarding the customization of the boot script from initrd, I have an even more generic idea than the OP:
the mkinird to check for the file "/etc/initrd.d/init.sh" and if it exists, to copy it on the place of "/boot/initrd-tree/init" before to generate the initrd.
This way the user have the full control over his custom init script from initrd, no matter what combination of options he use, with no fear that it will be overridden in a way or other.
Last edited by ZhaoLin1457; 06-09-2019 at 03:13 PM.
So for grins and giggles I wrote the following script and txt file to address the OP's suggestion. It works on my system and creates an initrd.gz that contains a modified init file based on a separate txt file. It should be run as root and on a vanilla Slackware installation is in the standard path.
This is the script file /usr/local/bin/mkinitrd.sh to generate the initrd.gz with the modified init file. Just replace the "# [...]" lines (2 of them) with your preferred mkinitrd commands.
Code:
#!/bin/sh
# 1st of 2 runs of mkinitrd
# use "-c" option, clear existing init-tree and recreate init-tree
# [Insert your preferred mkinitrd command here. Make sure to use the "-c" option so the initrd-tree is cleared]
# insert mkinitrd_init.txt into init file
sed -i -e '/# Need to make sure OPTIONS+/{r /usr/local/etc/mkinitrd_init.txt' -e 'N}' /boot/initrd-tree/init
# protect init file from delete or overwrite
# make init file immutable, add flag
chattr +i /boot/initrd-tree/init
# 2nd of 2 runs of mkinitrd
# do not use "-c" option, keep existing init-tree and overwrite init-tree
# [Insert your preferred mkinitrd command here. Make sure to not use the "-c" option so the existing initrd-tree is maintained.]
# unprotect init file from delete or overwrite
# make init file not immutable, remove flag
chattr -i /boot/initrd-tree/init
This is the txt file /usr/local/etc/mkinitrd_init.txt that gets copied into the init file using sed. Just replace the "# [...]" lines with the command(s) you want to add (as many or as few since the whole file is copied).
Code:
##########
# inserted contents from /usr/local/etc/mkinitrd_init.txt
# [add command #1 to insert into the init file here]
# [add command #2 to insert into the init file here]
# [add command #3 to insert into the init file here]
##########
Interesting fact, this is one of the few times I've used the immutable bit to preserve a file during processing.
This seems like a nice thread to drop in a little suggestion.
I customized my /etc/mkinitrd.conf concerning loaded modules, but I found no documented default for KERNEL_VERSION (-k on the mkinitrd command line). So I scripted it into my 64-bit desktop's mkinitrd.conf:
Code:
KERNEL_VERSION="$(ls -1 /boot/vm*generic* | tail -n 1 | sed 's/.*generic-//')"
This way, if someone (like me) has used installpkg instead of upgradepkg to load a new kernel, the command
Code:
# mkinitrd -F
will automatically detect the version of the newest kernel-generic, and use that for the module path.
For my 32-bit netbook, it's slightly different:
Code:
KERNEL_VERSION="$(ls -1 /boot/vm*generic* | tail -n 1 | sed 's/.*generic-smp//')"
This takes into account the Slackware kernel version naming scheme.
Side note: my sysadmin experience (i.e. how many ways can I mess up my desktop?) says "keep the working boot files until you can replace them with minimal chance of disaster." Since I use LILO to boot, I leave the old files in place until all the new files are ready. Then, just running "lilo" takes a few seconds to re-configure the file mappings for /boot/kernel-generic and /boot/initrd.gz. By keeping a previous /boot/kernel-huge around, I have that escape route to finish a proper kernel upgrade in the event of a power failure or other catastrophic system crash.
KERNEL_VERSION="$(ls -1 /boot/vm*generic* | tail -n 1 | sed 's/.*generic-//')"
This code didn't work for me since I had a mix of kernels that don't sort properly with the current command. Running it led me to a 4.9.38 kernel. (Yes, I have a lot of unused kernels.)
You could also change the sed command to a rev with a cut and another rev to not need separate commands between smp and 64bit kernels. (Although, this undoubtedly would break some peoples' custom kernel naming schemes.)
It would be nice to have an update to mkinitrd that will use the option -k to override the kernel version set in /etc/mkinitrd.conf. If it's not set, use the default, but if it is set, override it. I just don't know enough about the program to even try and propose a patch.
This code didn't work for me since I had a mix of kernels that don't sort properly with the current command. Running it led me to a 4.9.38 kernel. (Yes, I have a lot of unused kernels.)
Are the symlinks in /boot not supposed to point to the current kernel in use? Sorry if I am missing something obvious but I avoid having multiple kernels on my system so all the symlinks point to my current (and only) kernel. If this is also true for systems that have multiple kernels in the /boot directory then why not just use
Code:
readlink -f /boot/vmlinuz-generic| sed 's/.*generic-//'
No sort, no tail and it avoids parsing the output of ls.
Are the symlinks in /boot not supposed to point to the current kernel in use?
I think using symlinks is common in Slackware when people use packages (and probably some that do it manually), but AFAIK, they are only there for simplicity in naming/referencing when configuring kernels in your bootloader's config.
You're also supposed to copy your system.map and kernel config to /boot/, but I never do. I also never change my /usr/src/linux/ symlink to point to the current kernel... I used to, but it didn't break anything when I stopped doing it, so again, it is a step (or several) that I just don't worry about when compiling my own kernels.
For me, it is one extra step that I just don't worry about. However, I do realize that my setup is probably not the standard setup. I wasn't posting to get gus3 to change his command, just providing a data point for them to consider when using their command. I realize that with my non-standard setup that not all scripts will work as intended (which is why I don't use eliloconfig, since it overwrites my elilo.conf file).
Last edited by bassmadrigal; 07-29-2019 at 12:34 AM.
I also never change my /usr/src/linux/ symlink to point to the current kernel... I used to, but it didn't break anything when I stopped doing it, so again, it is a step (or several) that I just don't worry about when compiling my own kernels.
It used to be used to find kernel headers, but that was replaced by the /lib/modules/$(uname -r)/{source,build} symlinks a long time ago. If you have a /usr/src/linux symlink these days, it's just for the convenience of the sysadm.
I still use one to point to my local copy of linux-stable.git.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.