#862 Issue closed: remove needless bash from chroot calls (simplification avoids initramfs isn't recreated during recovery)

Labels: cleanup, fixed / solved / done, minor bug

Wsaibot opened issue at 2016-06-03 20:32:

  • rear version :1.17.2
  • OS version: RHEL 7.2
  • After doing a "rear recover" from a rear-ISO initrd isn't recreated with needed storage driver. I can see the following problem in script "finalize/Fedora/i386/17_rebuild_initramfs.sh"

++ chroot /mnt/local /bin/bash --login -c 'mkinitrd -v -f --with=crc32c-intel --with=crct10dif-pclmul --with=crct10dif_common --with=crct10dif_generic --with=ahci --with=ata_generic --with=ata_piix --with=libahci --with=libata --with=pata_acpi --with=floppy --with=virtio_blk --with=cdrom --with=virtio_console --with=iscsi_ibft --with=cirrus --with=drm --with=drm_kms_helper --with=ttm --with=i2c-core --with=serio_raw --with=dm-log --with=dm-mirror --with=dm-mod --with=dm-region-hash --with=e1000 --with=8139cp --with=mii --with=virtio_net --with=iscsi_boot_sysfs --with=sd_mod --with=sr_mod --with=virtio_scsi --with=syscopyarea --with=sysfillrect --with=sysimgblt --with=virtio --with=virtio_pci --with=virtio_ring --with=xfs --with=crc-t10dif --with=libcrc32c --with=garp --with=mrp --with=stp --with=8021q --with=llc --with=sg --with=vmw_pvscsi /boot/initramfs-3.10.0-229.7.2.el7.x86_64.img 3.10.0-229.7.2.el7.x86_64'
fork: No such file or directory
++ LogPrint 'WARNING !!!
initramfs creation for Kernel 3.10.0-229.7.2.el7.x86_64 failed, please check '''/var/log/rear/rear-server.log''' to see the error
messages in detail and decide yourself, wether the system will boot or not.
'

  • Work-around, if any: change chroot command to (for latest kernel): chroot /mnt/local/ /usr/bin/dracut --force
    @

gdha commented at 2016-06-07 12:25:

@Wsaibot Are you trying to explain that mkinird fails and dracut should be used instead for RHEL 7.2?
The man page tells me: mkinitrd - is a compat wrapper, which calls dracut to generate an initramfs.

Could it be that one of the modules was not present (seems a very long list to me)?

Wsaibot commented at 2016-06-07 15:51:

@gdha You are correct about the man page. I tried a little bit more deep analysing the problem. As you can see above, the chroot /mnt/local /bin/bash --login -c ... command gives the error:fork: No such file or directory. I found out, that has nothing todo with the mkinit-command. I did the commands manually from the revocery-ISO and the issue is:

  • chroot /mnt/local is working, I get a chroot-environment
  • chroot /mnt/local /bin/bash is working, I get a chroot-environment
  • chroot /mnt/local /bin/bash --login is not working, I get error "fork: No such file or directory"

I tried then this:

  • chroot /mnt/local mkinitrd -v -f --with=crc32c-intel --with=crct10dif-pclmul --with=crct10dif_common --with=crct10dif_generic --with=ahci --with=ata_generic --with=ata_piix --with=libahci --with=libata --with=pata_acpi --with=floppy --with=virtio_blk --with=cdrom --with=virtio_console --with=iscsi_ibft --with=cirrus --with=drm --with=drm_kms_helper --with=ttm --with=i2c-core --with=serio_raw --with=dm-log --with=dm-mirror --with=dm-mod --with=dm-region-hash --with=e1000 --with=8139cp --with=mii --with=virtio_net --with=iscsi_boot_sysfs --with=sd_mod --with=sr_mod --with=virtio_scsi --with=syscopyarea --with=sysfillrect --with=sysimgblt --with=virtio --with=virtio_pci --with=virtio_ring --with=xfs --with=crc-t10dif --with=libcrc32c --with=garp --with=mrp --with=stp --with=8021q --with=llc --with=sg --with=vmw_pvscsi /boot/initramfs-3.10.0-229.7.2.el7.x86_64.img 3.10.0-229.7.2.el7.x86_64

This command is working fine. Also later in the automatic recovery process the creation of grub2 is working. There is also a chroot command without the part "/bin/bash --login -c".

Can you verify this issue?

gdha commented at 2016-06-07 17:32:

@Wsaibot Thank you for the detailed analysis! I'll verify it tomorrow.

Wsaibot commented at 2016-06-10 14:17:

@gdha: I did some more testing. In my environment I get the same failure in RHEL6. After that, I thought it couldn't be a rear problem and I have 80% right ,-).

We have an entry in .bash_profile called "exec /usr/bin/rootsh". When I remove this entry, mkinitrd works fine. Later in the rear recover process, the chroot command for grub also don't uses the "/bin/bash --loging -c" part. Do you know, why this is used for the mkinitrd command? For minimize .bash_profile problems for a login shell, it would be good, to change the chroot-command as I posted before (chroot /mnt/local mkinitrd -v -f --with...). This is also working for RHEL6/RHEL7 and would be more like also the grub-command.

gdha commented at 2016-06-10 14:31:

@jsmeix could you verify if the behavior on SLES is the same?

gdha commented at 2016-06-10 14:33:

@Wsaibot if you add the usr/bin/rootsh script to the COPY_AS_IS array then your problem should be fixed I hope

Wsaibot commented at 2016-06-10 16:29:

@gdha the /usr/bin/rootsh is an the server, which is backuped and restored (in the chroot-environment). COPY_AS_IS would copy the file to the recovery media. So the tool is on the place, the .bash_profile (on server, not revocery media) needs it. I think, that the rootsh has a problem, running in a chroot. So it's a problem from the tool.

For me the "only" question is, if we will change the chroot-command in finalize/Fedora/i386/17_rebuild_initramfs.sh to not using a a login shell for creating the initrd.

Thanks!

jsmeix commented at 2016-06-13 09:12:

@gdha
regarding your https://github.com/rear/rear/issues/862#issuecomment-225197934
(verify if the behavior on SLES is the same?):

On SUSE finalize/SUSE_LINUX/i386/17_rebuild_initramfs.sh is run.

Both in finalize/SUSE_LINUX/i386/17_rebuild_initramfs.sh
and finalize/Fedora/i386/17_rebuild_initramfs.sh there is

chroot $TARGET_FS_ROOT /bin/bash --login -c "mkinitrd ...

is run.

In general I wonder why a login shell is needed to run in between
(but I am not at all a mkinitrd expert).

In my personal direct install script at
https://en.opensuse.org/SDB:Disaster_Recovery#Generic_system_installation_with_the_plain_SUSE_installation_system
it worked for me without a shell in between:

# Mountpoint in the installation system of the target system filesystem root:
target_system_filesystem_root="/mnt"
...
# Make initrd verbosely in the target system:
if test -n "$make_initrd"
then chroot $target_system_filesystem_root /sbin/mkinitrd -v
fi

What is the reason that "mkinitrd" has to be run
from a login shell?

jsmeix commented at 2016-06-13 09:30:

@gdha
according to

$ git log -p usr/share/rear/finalize/Fedora/i386/17_rebuild_initramfs.sh
...
commit 38eaf8966850819b0acb8fd08c181a74a063793b
Author: Gratien D'haese 
Date:   Wed Apr 4 16:40:06 2012 +0200
...
--- /dev/null
+++ b/usr/share/rear/finalize/Fedora/i386/17_rebuild_initramfs.sh
...
+       if chroot /mnt/local /bin/bash --login -c "mkinitrd ...

it was you who initially made the

chroot /mnt/local /bin/bash --login -c "mkinitrd ...

command with the longin shell in between.

Do you remember the reason why?

FYI:
in the rear sources using

find . -name '*.sh' | xargs grep -2 ' chroot '

finds a lot of chroot with a login shell in between.

I wonder in general if chroot with a login shell in between
is really a good idea or if perhaps keep things simpler
and omit the login shell in general for chroot is better?

jsmeix commented at 2016-06-13 11:33:

The oldest commits that contain 'chroot .*bash --login'
are from @schlomo in 2009 and 2010.

I assume all other 'chroot .*bash --login' code
is via copy and paste.

@schlomo
do you know the reason behind why

chroot ... /bin/bash --login -c "mkinitrd ...

is used with the login shell in between
instead of directly calling it via

chroot ... /sbin/mkinitrd ...

Details:

In the current rear sources I did

$ find . -name '*.sh' | xargs grep -l 'chroot .*bash --login'
./usr/share/rear/finalize/Debian/i386/17_rebuild_initramfs.sh
./usr/share/rear/finalize/Fedora/i386/17_rebuild_initramfs.sh
./usr/share/rear/finalize/Linux-ppc64/20_install_yaboot.sh
./usr/share/rear/finalize/Linux-ppc64/22_install_grub2.sh
./usr/share/rear/finalize/Linux-ppc64le/22_install_grub2.sh
./usr/share/rear/finalize/SUSE_LINUX/i386/17_rebuild_initramfs.sh
./usr/share/rear/finalize/SUSE_LINUX/ppc64/20_install_yaboot.sh
./usr/share/rear/finalize/default/89_finish_checks.sh

and then for each of those files I get the history using

git log -p filename

jsmeix commented at 2016-06-13 12:28:

I asked our (i.e. SUSE's) dracut package maintainer
(our dracut package contains /sbin/mkinitrd)
if he knows about a reason to run mkinitrd
with a login shell in between as in

chroot ... /bin/bash --login -c "mkinitrd ...

and offhandedly he does not know a reason
why there should be a login shell in between.

gdha commented at 2016-12-31 10:28:

@jsmeix @schlomo Seems we lost track of this issue. We should pick this one up after ReaR v2.0 release, no?

jsmeix commented at 2017-01-02 09:29:

After ReaR v2.0 release I will remove the login shell in between
when it is not obviously needed.

jsmeix commented at 2017-01-20 13:12:

With
https://github.com/rear/rear/pull/1171
merged, this issue should (hopefully) be fixed.

FYI:
It was much more complicated than I initially assumed.
One cannot "simply remove" a login shell in between
from a chroot call.
Reason:
With a login shell in between one has in the chrooted
environment all the advantages of a "normal working shell"
which means one can write the commands for 'chroot'
as one would type them in a normal working shell.
In particular one can call programs by their basename without path
so that it usually "just works" independent where each particular
Linux distribution installs programs as long as the program
is in one of the directories in $PATH.
With this experience I wonder now if it makes things really
work better in 'chroot' without the login shell in between.
When it does not work with a login shell in between
one could also argue that then the login shell setup
on that particular system is broken which is not an
issue in ReaR because a login shell must "just work"
so that the login shell setup must be fixed
by the admin of that particular system.

jsmeix commented at 2017-02-23 16:16:

An example where a login shell in between is needed:

A login shell in between is needed in particular
when shell scripts are called inside 'chroot'.

For example grub2-mkconfig is a shell script:

RESCUE e205:~ # chroot /mnt/local /bin/bash -c '/usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg'
Generating grub configuration file ...
/etc/grub.d/00_header: line 23: cut: command not found

RESCUE e205:~ # cat -n /mnt/local/etc/grub.d/00_header | grep '    23'
    23  grub_lang=`echo $LANG | cut -d . -f 1`

RESCUE e205:~ # chroot /mnt/local /bin/bash -c 'echo $LANG | cut -d . -f 1'
/bin/bash: cut: command not found

RESCUE e205:~ # chroot /mnt/local /bin/bash -c 'echo $LANG ; echo $PATH'
en_GB.iso885915
/bin

RESCUE e205:~ # chroot /mnt/local /bin/bash --login -c '/usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg'
Generating grub configuration file ...
Found theme: /boot/grub2/themes/SLE/theme.txt
Found linux image: /boot/vmlinuz-4.4.21-69-default
Found initrd image: /boot/initrd-4.4.21-69-default
done

jsmeix commented at 2017-05-08 07:58:

It seems using no login shell for chroot calls
causes more issues that it solves, see
https://github.com/rear/rear/pull/1345


[Export of Github issue for rear/rear.]