Skip to main content
clarity of comments
Source Link

Here are two ways which work in ubuntu bionicfocal&bionic (and possiblylikely elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, might need tweaking to work elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: $sub becomes root directly, nothing gets any chance to see the partition root # con: requires the subdirectory's initramfs/initrd to be tweaked and rebuilt #2nd choice: specify this scriptfile as init= on the kernel commandline # pro: no need to rebuild initramfs # con: requires bin/bash in the partition root must be executable by $sub/vmlinux (iepartition $subroot sameolder orthan newer$sub thanlikely partitionwill rootwork) # con: if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr # con: additional initramfs scripts might also look in the partition root rather than $sub #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #for the 2nd choice, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this scriptfile (chmod 744) #for the 1st choice, the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *}  #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt  #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&  #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&&  #mount subroot # umount part #&&sleep 15  #unmount partition root (uncomment &&sleep for time to watch) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90  #if error pause to see it # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new initrd/initramfs installed thereafter subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (eg dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 

Here are two ways which work in ubuntu bionic (and possibly elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, might need tweaking to work elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: $sub becomes root directly, nothing gets any chance to see the partition root # con: requires the subdirectory's initramfs/initrd to be tweaked and rebuilt #2nd choice: specify this scriptfile as init= on the kernel commandline # pro: no need to rebuild initramfs # con: requires bin/bash in the partition root executable by $sub/vmlinux (ie $sub same or newer than partition root) # con: if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr # con: additional initramfs scripts might also look in the partition root rather than $sub #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #for the 2nd choice, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this scriptfile (chmod 744) #for the 1st choice, the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *}  #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt  #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&  #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&&  #mount subroot # umount part #&&sleep 15  #unmount partition root (uncomment &&sleep for time to watch) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90  #if error pause to see it # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new initrd/initramfs installed thereafter subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (eg dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 

Here are two ways which work in ubuntu focal&bionic (and likely elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, might need tweaking to work elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: $sub becomes root directly, nothing gets any chance to see the partition root # con: requires the subdirectory's initramfs/initrd to be tweaked and rebuilt #2nd choice: specify this scriptfile as init= on the kernel commandline # pro: no need to rebuild initramfs # con: bin/bash in partition root must be executable by $sub/vmlinux (partition root older than $sub likely will work) # con: if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr # con: additional initramfs scripts might also look in the partition root rather than $sub #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #for the 2nd choice, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this scriptfile (chmod 744) #for the 1st choice, the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment &&sleep for time to watch) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to see it # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new initrd/initramfs installed thereafter subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (eg dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 
minor further clarifications
Source Link
#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, couldmight beneed differenttweaking to work elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: subdirectory$sub becomes root directly, nothing gets any chance to see the partition root # con:  only works ifrequires the subdirectory's initramfs/initrd isto be tweaked and rebuilt #2nd choice: specify this scriptscriptfile as init= on the kernel commandline # pro: no need to rebuild initramfs # con: ifrequires bin/bash in the partition root etc/fstabexecutable mountsby $sub/usrvmlinux the(ie initramfs$sub willsame haveor alreadynewer mountedthan itpartition root) # con: it'sif conceivablethe somepartition initramfsroot scriptetc/fstab mightmounts still/usr, lookthe in$sub theinitramfs partitionwill rootmount ratherthe thanpartition yourroot subdirectory/usr # con: thisadditional scriptinitramfs requiresscripts bin/bashmight etalso allook in the partition root rather than $sub #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo #  uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894  #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub  # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #to#for usethe this2nd scriptchoice, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this scriptscriptfile (chmod 744) #the#for the 1st choice, the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment sleep&&sleep for time to lookwatch) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to looksee it # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new kernelinitrd/initramfs installed  thereafter  subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (ieeg dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 
#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, could be different elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: subdirectory becomes root directly, nothing gets any chance to see the partition root # con:  only works if the subdirectory's initramfs/initrd is tweaked and rebuilt #2nd choice: specify this script as init= on the kernel commandline # pro: no need to rebuild initramfs # con: if the partition root etc/fstab mounts /usr the initramfs will have already mounted it # con: it's conceivable some initramfs script might still look in the partition root rather than your subdirectory # con: this script requires bin/bash et al in the partition root #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo #  uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub  # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #to use this script, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this script (chmod 744) #the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment sleep for time to look) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to look # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new kernel installed  subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (ie dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 
#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, might need tweaking to work elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: $sub becomes root directly, nothing gets any chance to see the partition root # con: requires the subdirectory's initramfs/initrd to be tweaked and rebuilt #2nd choice: specify this scriptfile as init= on the kernel commandline # pro: no need to rebuild initramfs # con: requires bin/bash in the partition root executable by $sub/vmlinux (ie $sub same or newer than partition root) # con: if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr # con: additional initramfs scripts might also look in the partition root rather than $sub #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894  #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #for the 2nd choice, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script #pathname from partition root to this scriptfile (chmod 744) #for the 1st choice, the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: # set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline # [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment &&sleep for time to watch) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to see it # set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new initrd/initramfs installed thereafter  subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *} #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (eg dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&& #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash #land in a shell if moves or pivot fail 
caught a bug
Source Link

Here's a scriptHere are two ways which workswork in ubuntu bionic (and possibly elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these 2 choices:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, could be different elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: subdirectory becomes root before any script ordirectly, drivernothing gets aany chance to look insee the partition root # con: only works if the subdirectory's initramfs/initrd is tweaked and rebuilt #2nd choice: specify this script as init= on the kernel commandline # pro: no need to rebuild initramfs # con: if the partition root etc/fstab mounts /usr the initramfs will have already mounted it # con: it's conceivable some initramfs script or driver might still look in the partition root rather than your subdirectory # con: this script requires bin/bash et al in the partition root  #the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} #with: # (set -x # mkdir part #mountpoint for partition root # part=$rootmnt a=" $(cat<proc/cmdline) " b=${a#* subroot=};[ "$a" = "$b" ]&&echo subroot not specifyed||subroot=${b%% *} part=part #extract subroot from kernel commandline # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&[ $subroot ]&&mount --bind part/$subroot $rootmnt&&umount part #&&sleep 15 #mount partition, mount subroot, unmount partition root # ) #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs will rebuild for the current kernel, #and it will automatically build into every new kernel installed  #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" #  sub=foosub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux /$sub/vmlinuz ro root=UUID=$uuid subroot=$sub  # echo "initrd /$sub/initrd.img" # initrd /$sub/initrd.img  #works in recent releases where the /initrd.img softlink is relative #} #to use this script, in addition to subroot= on the kernel commandline also specify: # init=patinit=/path/to/script pathname #pathname from partition root to this script (chmod 744) subroot()#the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} a="${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: #  set -x # karg=" $(cat<proc/cmdline) " b=$m=${a#*karg#* subroot=}  # [ "$a""$m" = "$b""$karg" ]&&]||subroot=${m%% echo*} no  #extract subroot onfrom kernel cmdline;returncommandline # 1; [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag}||subroot=$ ${b%%FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment sleep for time to look) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to look #  set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new kernel installed subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *}  #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (ie dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||return||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mntmnt&& #&&sleep 15  #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot&&exec chrootsubroot ."$@"&&exec init "$@"||exec bash  #land in a shell if anythingmoves failsor pivot fail 

Here's a script which works in ubuntu bionic (and possibly elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these 2 choices:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, could be different elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: subdirectory becomes root before any script or driver gets a chance to look in the partition root # con: only works if the subdirectory's initramfs/initrd is tweaked and rebuilt #2nd choice: specify this script as init= on the kernel commandline # pro: no need to rebuild initramfs # con: if the partition root etc/fstab mounts /usr the initramfs will have already mounted it # con: it's conceivable some initramfs script or driver might still look in the partition root rather than your subdirectory # con: this script requires bin/bash et al in the partition root  #the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} #with: # (set -x # mkdir part #mountpoint for partition root # part=$rootmnt a=" $(cat<proc/cmdline) " b=${a#* subroot=};[ "$a" = "$b" ]&&echo subroot not specifyed||subroot=${b%% *} part=part #extract subroot from kernel commandline # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&[ $subroot ]&&mount --bind part/$subroot $rootmnt&&umount part #&&sleep 15 #mount partition, mount subroot, unmount partition root # ) #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs will rebuild for the current kernel, #and it will automatically build into every new kernel installed  #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" #  sub=foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux /$sub/vmlinuz ro root=UUID=$uuid subroot=$sub # echo "initrd /$sub/initrd.img" # initrd /$sub/initrd.img #works in recent releases where the /initrd.img softlink is relative #} #to use this script, in addition to subroot= on the kernel commandline also specify: # init=pat pathname from partition root to this script (chmod 744) subroot(){ a=" $(cat<proc/cmdline) " b=${a#* subroot=}   [ "$a" = "$b" ]&&{ echo no subroot on kernel cmdline;return 1;}||subroot=${b%% *} #extract subroot from kernel commandline while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (ie dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||return #mount subroot for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt #&&sleep 15 #unmount partition root } subroot&&exec chroot . init "$@"||exec bash #land in a shell if anything fails 

Here are two ways which work in ubuntu bionic (and possibly elsewhere). i've not enough rep to comment, but, bionic:/usr/share/initramfs-tools/init looks in /etc/fstab for /usr right after calling mountroot and before calling the *-bottom scripts, so adding an init-bottom script (as suggested in another answer here) is "too late". instead i recommend these:

#!/bin/bash -f #copyleft 2018 greg mott #set a subdirectory as root (so multiple installs don't need partitions) #these work in ubuntu bionic, could be different elsewhere #1st choice: tweak initramfs-tools/scripts/local # pro: subdirectory becomes root directly, nothing gets any chance to see the partition root # con: only works if the subdirectory's initramfs/initrd is tweaked and rebuilt #2nd choice: specify this script as init= on the kernel commandline # pro: no need to rebuild initramfs # con: if the partition root etc/fstab mounts /usr the initramfs will have already mounted it # con: it's conceivable some initramfs script might still look in the partition root rather than your subdirectory # con: this script requires bin/bash et al in the partition root #for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot: #menuentry "subroot foo" { # echo "subroot foo" # sub=/foo # uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894 #use your partition's uuid # search --no-floppy --fs-uuid --set=root $uuid # linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub  # echo "initrd $sub/initrd.img" # initrd $sub/initrd.img  #works in recent releases where the /initrd.img softlink is relative #} #to use this script, in addition to subroot= on the kernel commandline also specify: # init=/path/to/script  #pathname from partition root to this script (chmod 744) #the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace: # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt} # mountroot_status="$?" #with: #  set -x # karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} # [ "$m" = "$karg" ]||subroot=${m%% *}   #extract subroot from kernel commandline #  [ $subroot ]&&part=part||part=$rootmnt #no subroot, just mount partition as root # mkdir part # mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&& #mount partition # if [ "$subroot" ] # then mount --bind part/$subroot $rootmnt&& #mount subroot # umount part #&&sleep 15 #unmount partition root (uncomment sleep for time to look) # fi # mountroot_status="$?" # [ $mountroot_status = 0 ]||sleep 90 #if error pause to look #  set +x #once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel, #and it will automatically build into every new kernel installed subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=} [ "$m" = "$karg" ]||subroot=${m%% *}  #extract subroot from kernel commandline [ $subroot ]||return 0 #no subroot, just proceed in partition root while read -r m r m do for m in $M x #build list of what's already mounted do [[ $r = $m* ]]&&break #exclude subtrees (ie dev/**) done||[[ $r = / ]]||M=$M\ $r #exclude / done<proc/mounts (set -x;mount --bind $subroot mnt)||{ set -x #mount subroot sleep 30 #if not found pause to see error return 0;} #then reincarnate as partition root init for m in $M do (set -x;mount -n --move $m mnt$m)||return #move listed mounts to subroot done set -x cd mnt&& pivot_root . mnt&& #subroot becomes root umount -l mnt&&   #unmount partition root #sleep 15 && #so far so good? uncomment for time to look exec chroot . init "$@" #reincarnate as subroot init } subroot "$@"&&exec init "$@"||exec bash  #land in a shell if moves or pivot fail 
added 84 characters in body
Source Link
Loading
revised&clarified
Source Link
Loading
added 102 characters in body
Source Link
Loading
edited body
Source Link
Loading
revised, clarified, comment added
Source Link
Loading
revised and clarified
Source Link
Loading
Source Link
Loading