View previous topic :: View next topic |
Author |
Message |
StevenC21 n00b
Joined: 07 Jun 2018 Posts: 63
|
Posted: Fri Jan 04, 2019 6:36 am Post subject: Gentoo Chroot Script |
|
|
Hey, so I wrote a small script mostly taken from the Gentoo Handbook. Its designed to chroot into a Gentoo system in such a way that you are able to begin maintenance on it. It does not handle mounting the partitions for the Gentoo system, since that can be very variable and I don't know of a reliable way to figure out what partitions mount where. That is for the user to determine. Anyways, here it is.
Code: |
#!/bin/bash
FS=$1
SH=$2
if [ ! -e /tmp/*.gntmnt ]; then # If nobody is in the system then we should mount the needed filesystems
echo "No Mount detected"
echo "Mounting Necessary Filesystems..."
sudo mount --types proc /proc ${FS}/proc
sudo mount --rbind /sys ${FS}/sys
sudo mount --make-rslave ${FS}/sys
sudo mount --rbind /dev ${FS}/dev
sudo mount --make-rslave ${FS}/dev
fi
echo "Chrooting into Gentoo system..."
touch /tmp/${$}.gntmnt # Create a temporary file to tell the script that we are inside the system
sudo chroot ${FS} ${SH}
# By this point the user has exitted from the Chroot, its time to unmount filesystems - assuming this is the only shell still in it...
rm /tmp/${$}.gntmnt
if [ ! -e /tmp/*.gntmnt ]; then
echo "Unmounting Filesystems..."
sudo umount -l ${FS}/dev{/shm,/pts,}
else
echo "Other shells chrooted, not unmounting filesystems..."
fi
|
Any comments/suggestions/questions are welcome! |
|
Back to top |
|
|
Muso Veteran
Joined: 22 Oct 2002 Posts: 1052 Location: The Holy city of Honolulu
|
Posted: Fri Jan 04, 2019 6:41 am Post subject: |
|
|
This should probably posted in Documentation, Tips & Tricks. _________________ "You can lead a horticulture but you can't make her think" ~ Dorothy Parker
2021 is the year of the Linux Desktop! |
|
Back to top |
|
|
StevenC21 n00b
Joined: 07 Jun 2018 Posts: 63
|
Posted: Fri Jan 04, 2019 6:45 am Post subject: |
|
|
Can I move it somehow? |
|
Back to top |
|
|
fedeliallalinea Administrator
Joined: 08 Mar 2003 Posts: 31284 Location: here
|
Posted: Fri Jan 04, 2019 6:53 am Post subject: |
|
|
StevenC21 wrote: | Can I move it somehow? |
No, but you can use report button (at top right) and ask to move thread _________________ Questions are guaranteed in life; Answers aren't. |
|
Back to top |
|
|
NeddySeagoon Administrator
Joined: 05 Jul 2003 Posts: 54588 Location: 56N 3W
|
Posted: Fri Jan 04, 2019 1:00 pm Post subject: |
|
|
Moved from Other Things Gentoo to Documentation, Tips & Tricks.
After the user has mounted root (at /mnt/gentoo) in the chroot, you can read /mnt/gentoo/etc/fstab and parse that.
You can't use it as is but you can prepend /mnt/gentoo/ to the mount points.
Extracting the filesystem location (partition) is harder. If its given as UUID or PARTUUID, you can use it as is.
If its /dev/sd*, the drive may not be correct but you can compare it to the drive that has a partition attached at /mnt/gentoo/
For multi drive installs, that use several /dev/sd*, you don't have enough information. _________________ Regards,
NeddySeagoon
Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail. |
|
Back to top |
|
|
StevenC21 n00b
Joined: 07 Jun 2018 Posts: 63
|
Posted: Fri Jan 04, 2019 7:08 pm Post subject: |
|
|
I thought about using fstab as well Neddy, but I am still concerned about those issues. |
|
Back to top |
|
|
Hu Administrator
Joined: 06 Mar 2007 Posts: 22729
|
Posted: Sat Jan 05, 2019 1:49 am Post subject: Re: Gentoo Chroot Script |
|
|
Missing use of set -eu.You should test if these are set to sane values. If the user runs without arguments, you may get odd results. StevenC21 wrote: | Code: | if [ ! -e /tmp/*.gntmnt ]; then # If nobody is in the system then we should mount the needed filesystems |
| Since /tmp is world-writable, someone else may have created a conflicting file. On a multi-user system, you should put your lockfile somewhere that no one else can interfere. StevenC21 wrote: | Code: | echo "No Mount detected"
echo "Mounting Necessary Filesystems..." |
| These can be combined. StevenC21 wrote: | Code: | sudo mount --types proc /proc ${FS}/proc
sudo mount --rbind /sys ${FS}/sys
sudo mount --make-rslave ${FS}/sys
sudo mount --rbind /dev ${FS}/dev
sudo mount --make-rslave ${FS}/dev |
| Why use sudo on every single command? It would be simpler to say that the script must run as root. StevenC21 wrote: | Code: | touch /tmp/${$}.gntmnt # Create a temporary file to tell the script that we are inside the system |
| Brace notation is not needed here. You can use $$ (but as above, you shouldn't be putting your lockfile in /tmp).
StevenC21 wrote: | Code: | if [ ! -e /tmp/*.gntmnt ]; then |
| There are some Time-of-Check/Time-of-Use errors here. If another instance starts after this test and mounts its pseudo-filesystems before you reach the umount, you will take them away from it. If a stray lockfile is present when your script starts, and not present when you reach this line, then you will unmount filesystems that you never mounted. This could be particularly bad if $FS is blank, which you do not guard against. In that case, you would lazy-unmount the host pseudo-filesystems.
The simplest fix for all these problems is to use mount namespaces. Make a private mount namespace. Unconditionally bind mount the pseudo-filesystems you want. Let the kernel remove them when you exit. That removes the need for lock files and eliminates all the associated race conditions. |
|
Back to top |
|
|
StevenC21 n00b
Joined: 07 Jun 2018 Posts: 63
|
Posted: Sat Jan 05, 2019 8:02 pm Post subject: |
|
|
I am curious about your last suggestion. You mentioned that a second instance could mount the pseudo filesystems... but this would not happen, since it checks for any lockfiles denoting that someone is already in the filesystem. If you could explain in greater detail how this scenario might occur I would be grateful .
Here is the current version of the script:
Code: |
#!/bin/bash
set -eu
FS=$1
SH=$2
if [ -z $FS ]; then
echo "Filesystem to chroot not set"
exit 1
fi
if [ -z $SH ]; then
echo "Shell to chroot with not set"
exit 1
fi
mkdir -p /var/lib/gntmnt/
if [ ! -e /var/lib/gntmnt/*.gntmnt ]; then # If nobody is in the system then we should mount the needed filesystems
touch /var/lib/gntmnt/$$.gntmnt # Create a temporary file to tell the script that we are inside the system
echo "No Mount detected, Mounting Necessary Filesystems..."
mount --types proc /proc ${FS}/proc
mount --rbind /sys ${FS}/sys
mount --make-rslave ${FS}/sys
mount --rbind /dev ${FS}/dev
mount --make-rslave ${FS}/dev
fi
echo "Chrooting into Gentoo system..."
sudo chroot "${FS}" "${SH}"
# By this point the user has exitted from the Chroot, its time to unmount filesystems - assuming this is the only remaining shell.
rm /var/lib/gntmnt/$$.gntmnt
if [ ! -e /var/lib/gntmnt/*.gntmnt ]; then
echo "Unmounting Filesystems..."
umount -l ${FS}/dev{/shm,/pts,}
else
echo "Other shells chrooted, NOT unmounting filesystems..."
fi
|
|
|
Back to top |
|
|
Hu Administrator
Joined: 06 Mar 2007 Posts: 22729
|
Posted: Sat Jan 05, 2019 8:40 pm Post subject: |
|
|
Considering the first version of the script, suppose that there are two instances of the script running.
- Instance #1 starts, runs through to the chroot, and pauses there while the user shell runs.
- Instance #2 starts, notices that there is a lockfile, and skips creating the bind mounts.
- Instance #1 exits the chroot and deletes its lockfile.
- Instance #1 is preempted after the rm runs, but before the [ test runs.
- Instance #2 resumes, deletes its lockfile, and runs the test. It finds no lockfile (because rm deleted it, and instance #1 already removed its lockfile).
- Instance #2 unmounts the pseudo-filesystems, then exits.
- Instance #1 resumes, runs the test, and finds no lockfiles. It too decides to unmount the pseudo-filesystems. However, due to your locking at the start, only one of the two instances mounted the pseudo-filesystems, so only one of them should unmount.
Threaded programming is hard. Any time you introduce locks, you need to think very carefully about whether the locks actually lock out all the bad situations.
Considering the second version, you removed some uses of sudo, but not others. The mount calls need to run as root, so the second script only works as root. This is fine, but if it is already guaranteed to be root, it doesn't need to sudo the chroot call.
In both versions, you mount, but never unmount, the proc andd sys pseudo-filesystems.
Also, your lockfile test will malfunction if more than one lockfile exists. The glob expands first, then the shell complains that you cannot test for more than one file. |
|
Back to top |
|
|
NeddySeagoon Administrator
Joined: 05 Jul 2003 Posts: 54588 Location: 56N 3W
|
Posted: Sat Jan 05, 2019 9:43 pm Post subject: |
|
|
Hu,
Its not a lock that's needed, its a counter, to determine how many instances of the script are running in the same chroot.
Eww ... recursion is hard when you have to do it all yourself. _________________ Regards,
NeddySeagoon
Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail. |
|
Back to top |
|
|
ralda n00b
Joined: 21 Apr 2019 Posts: 28
|
Posted: Sun Apr 28, 2019 2:35 am Post subject: Much more than a simple script to fire up a chroot container |
|
|
Hi Folks,
I read this here, while a stumbled on similar questions. As I'm able to look at over 30 year Unix experience, I've written a bigger script to address the problem to manage several chroot containers with different setups and multiple invocations of same chroot, and automatic setup/clean when required (or manual if desired):
It is a script called chroot-commands with multiple operations:
- default - to set a default chroot to use in other commands
- select - to select the default chroot from a list of known setups
- show - show the current default chroot name
- setup - invoke manual setup of chroot container
- clean - to clean setup of a chroot container
- go - to start a shell or program in a chroot container
The setup for the chroot containers are specified using configuration files in a directory, e.g. Code: | # *****************************************************************************
# x86_64-uclibc.setup - cClibc based Gentoo container for x86_64
# *****************************************************************************
# The chroot base directory and the mount source (device) names are expanded
# in the host shell environment. This allows tilde and variable expansions.
# set the chroot base directory
base = ~systems/x86_64-uclibc
# set the chroot shell program
shell = /bin/bash
# set the chroot search PATH value
path = /usr/sbin:/sbin:/usr/bin:/bin
# mount the essential virtual file systems
mount proc - - virtual -tproc
mount sys - - virtual -tsysfs
mount dev - - /dev -obind
mount dev/pts - - virtual -tdevpts -ogid=5
# bind tmp and var/tmp to host file system directories
mount tmp - - /tmp -obind
mount var/tmp - - /var/tmp -obind
# setup run directory on a new tmpfs
mount run root:root 0751 virtual -ttmpfs -osize=16M
mkdir run/lock root:root 1777
mkdir run/shm root:root 1777
mkdir run/mnt root:root 0755
# setup other mount points
mkdir mnt/portage root:root 0755
... | (just a partial example as I've setup a chroot container, you are free to specify your own setup).
On first container invocation, the setup configuration is parsed and the required operations are invoked (including error checking). More invocations of the same container just bypass the setup step and go straight to the chroot, but are registered (counted) in a directory (/run/chroot). When the last invocation exits the container, the setup configuration is parsed in reverse order, doing the appropriate reverse operation (umount). In case you don't want automatic setup/clean with single but reoccurring invocations, the setup can be locked manual and unlocked afterwards. Container clean is invoked when there are no more chroot invocations and not manually locked.
The list of setup operations is currently limited to make directory, make mountpoint directory, and mount. The script itself is designed to be easily extendable, so more setup/clean operations may be added on request. It runs with /bin/dash (so shall be compatible to other shells), uses only a small set of standard utilities (all provided by e.g. Busybox), and is not dedicated to Gentoo chroot containers.
If there is interest, i'm willing to provide this script to others. Please tell me, how I can distribute this here.
Harald |
|
Back to top |
|
|
k9dog Tux's lil' helper
Joined: 22 Jun 2009 Posts: 103 Location: Denmark
|
Posted: Fri Dec 16, 2022 10:39 am Post subject: |
|
|
@StevenC21
Nice script. Pity you not including the source /etc/profile stuff (.. Yeah I know, had that problem too ..). I had 2 scripts myself, this makes it a lot simpler! Thanks!
Anyway I thought I'd submit these lines for the variables. Please not all bash might be in /bin so still useful to be able to set path. If which command is missing set a string.
FS='/mnt/gentoo'
[ -n "$1" ] && FS=$1
SH=($which bash)
[ -n "$2" ] && SH=$2 |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|