LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (https://www.linuxquestions.org/questions/slackware-14/)
-   -   About the ability to run custom commands from initrd's init (https://www.linuxquestions.org/questions/slackware-14/about-the-ability-to-run-custom-commands-from-initrds-init-4175655412/)

LuckyCyborg 06-09-2019 12:17 PM

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.

Chuck56 06-09-2019 01:30 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.

LuckyCyborg 06-09-2019 01:39 PM

Quote:

Originally Posted by Chuck56 (Post 6003625)
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.

Alien Bob 06-09-2019 02:07 PM

Quote:

Originally Posted by LuckyCyborg (Post 6003626)
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.

Simple: by running mkinitd without the "-c" option. Customize whatever and wherever you want, just do not use the "-C" option.

LuckyCyborg 06-09-2019 02:24 PM

Quote:

Originally Posted by Alien Bob (Post 6003638)
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:

https://wiki.archlinux.org/index.php/Mkinitcpio#HOOKS

As another random example, Fedora uses instead "modules", like we see there:

https://git.kernel.org/pub/scm/boot/...tree/modules.d

Also the Debian uses "hooks", like they told there:

https://manpages.debian.org/jessie/i...l#HOOK_SCRIPTS

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.

ZhaoLin1457 06-09-2019 02:59 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.

Alien Bob 06-09-2019 03:28 PM

Too bad then. But you can create your own solution of course.

GazL 06-09-2019 03:29 PM

edit: nevermind. I was just repeating what eric said earlier. I guess I should have read all the thread before responding.

Chuck56 06-10-2019 06:22 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.

Have fun!

Tonus 06-11-2019 09:53 AM

About the ability to run custom commands from initrd's init
 
Reading this I was wondering if that could be integrated upstream, with an mkinitrd.conf option...

gus3 06-12-2019 11:04 PM

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.

bassmadrigal 06-18-2019 01:16 AM

Quote:

Originally Posted by gus3 (Post 6004688)
Code:

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.)

Code:

ls -1 /boot/vm*generic*           
/boot/vmlinuz-generic@
/boot/vmlinuz-generic-4.13.7
/boot/vmlinuz-generic-4.14-rc6
/boot/vmlinuz-generic-4.14-rc7
/boot/vmlinuz-generic-4.14.0*
/boot/vmlinuz-generic-4.18.12
/boot/vmlinuz-generic-4.19.12
/boot/vmlinuz-generic-4.19.24
/boot/vmlinuz-generic-4.19.41
/boot/vmlinuz-generic-4.19.5
/boot/vmlinuz-generic-4.4.75
/boot/vmlinuz-generic-4.9.38

I was able to solve this by throwing a sort -V in there and adding a dash after generic to prevent getting the symlink in there.

Code:

KERNEL_VERSION="$(ls -1 /boot/vm*generic-* | sort -V | tail -n 1 | sed 's/.*generic-//')"
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.)

Code:

KERNEL_VERSION="$(ls -1 /boot/vm*generic-* | sort -V | tail -n 1 | rev | cut -d- -f1 | rev)"
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.

crts 07-28-2019 11:43 AM

Quote:

Originally Posted by bassmadrigal (Post 6006595)
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.)

Code:

ls -1 /boot/vm*generic*           
/boot/vmlinuz-generic@
/boot/vmlinuz-generic-4.13.7
/boot/vmlinuz-generic-4.14-rc6
/boot/vmlinuz-generic-4.14-rc7
/boot/vmlinuz-generic-4.14.0*
/boot/vmlinuz-generic-4.18.12
/boot/vmlinuz-generic-4.19.12
/boot/vmlinuz-generic-4.19.24
/boot/vmlinuz-generic-4.19.41
/boot/vmlinuz-generic-4.19.5
/boot/vmlinuz-generic-4.4.75
/boot/vmlinuz-generic-4.9.38


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.

bassmadrigal 07-29-2019 12:32 AM

Quote:

Originally Posted by crts (Post 6019298)
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).

GazL 07-29-2019 03:42 PM

Quote:

Originally Posted by bassmadrigal (Post 6019431)
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.


All times are GMT -5. The time now is 10:17 AM.