Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Gentoo Chroot Script
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
StevenC21
n00b
n00b


Joined: 07 Jun 2018
Posts: 63

PostPosted: Fri Jan 04, 2019 6:36 am    Post subject: Gentoo Chroot Script Reply with quote

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
View user's profile Send private message
Muso
Veteran
Veteran


Joined: 22 Oct 2002
Posts: 1052
Location: The Holy city of Honolulu

PostPosted: Fri Jan 04, 2019 6:41 am    Post subject: Reply with quote

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
View user's profile Send private message
StevenC21
n00b
n00b


Joined: 07 Jun 2018
Posts: 63

PostPosted: Fri Jan 04, 2019 6:45 am    Post subject: Reply with quote

Can I move it somehow?
Back to top
View user's profile Send private message
fedeliallalinea
Administrator
Administrator


Joined: 08 Mar 2003
Posts: 30842
Location: here

PostPosted: Fri Jan 04, 2019 6:53 am    Post subject: Reply with quote

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
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 54122
Location: 56N 3W

PostPosted: Fri Jan 04, 2019 1:00 pm    Post subject: Reply with quote

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
View user's profile Send private message
StevenC21
n00b
n00b


Joined: 07 Jun 2018
Posts: 63

PostPosted: Fri Jan 04, 2019 7:08 pm    Post subject: Reply with quote

I thought about using fstab as well Neddy, but I am still concerned about those issues.
Back to top
View user's profile Send private message
Hu
Moderator
Moderator


Joined: 06 Mar 2007
Posts: 21518

PostPosted: Sat Jan 05, 2019 1:49 am    Post subject: Re: Gentoo Chroot Script Reply with quote

StevenC21 wrote:
Code:
#!/bin/bash
Missing use of set -eu.
StevenC21 wrote:
Code:
FS=$1
SH=$2
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
View user's profile Send private message
StevenC21
n00b
n00b


Joined: 07 Jun 2018
Posts: 63

PostPosted: Sat Jan 05, 2019 8:02 pm    Post subject: Reply with quote

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
View user's profile Send private message
Hu
Moderator
Moderator


Joined: 06 Mar 2007
Posts: 21518

PostPosted: Sat Jan 05, 2019 8:40 pm    Post subject: Reply with quote

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
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 54122
Location: 56N 3W

PostPosted: Sat Jan 05, 2019 9:43 pm    Post subject: Reply with quote

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
View user's profile Send private message
ralda
n00b
n00b


Joined: 21 Apr 2019
Posts: 28

PostPosted: Sun Apr 28, 2019 2:35 am    Post subject: Much more than a simple script to fire up a chroot container Reply with quote

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
View user's profile Send private message
k9dog
Tux's lil' helper
Tux's lil' helper


Joined: 22 Jun 2009
Posts: 103
Location: Denmark

PostPosted: Fri Dec 16, 2022 10:39 am    Post subject: Reply with quote

@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
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
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