Forums

Skip to content

Advanced search
  • Quick links
    • Unanswered topics
    • Active topics
    • Search
  • FAQ
  • Login
  • Register
  • Board index Discussion & Documentation Documentation, Tips & Tricks
  • Search

Gentoo Chroot Script

Unofficial documentation for various parts of Gentoo Linux. Note: This is not a support forum.
Post Reply
Advanced search
12 posts • Page 1 of 1
Author
Message
StevenC21
n00b
n00b
Posts: 63
Joined: Thu Jun 07, 2018 1:04 pm

Gentoo Chroot Script

  • Quote

Post by StevenC21 » Fri Jan 04, 2019 6:36 am

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: Select all

#!/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!
Top
Muso
Veteran
Veteran
User avatar
Posts: 1052
Joined: Tue Oct 22, 2002 7:45 am
Location: The Holy city of Honolulu
Contact:
Contact Muso
Website

  • Quote

Post by Muso » Fri Jan 04, 2019 6:41 am

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!
Top
StevenC21
n00b
n00b
Posts: 63
Joined: Thu Jun 07, 2018 1:04 pm

  • Quote

Post by StevenC21 » Fri Jan 04, 2019 6:45 am

Can I move it somehow?
Top
fedeliallalinea
Administrator
Administrator
User avatar
Posts: 31988
Joined: Sat Mar 08, 2003 11:15 pm
Location: here
Contact:
Contact fedeliallalinea
Website

  • Quote

Post by fedeliallalinea » Fri Jan 04, 2019 6:53 am

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.

"Those who would give up essential liberty to purchase a little temporary safety,
deserve neither liberty nor safety."
- Ben Franklin
https://www.news.admin.ch/it/nsb?id=103968
Top
NeddySeagoon
Administrator
Administrator
User avatar
Posts: 56108
Joined: Sat Jul 05, 2003 9:37 am
Location: 56N 3W

  • Quote

Post by NeddySeagoon » Fri Jan 04, 2019 1:00 pm

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.
Top
StevenC21
n00b
n00b
Posts: 63
Joined: Thu Jun 07, 2018 1:04 pm

  • Quote

Post by StevenC21 » Fri Jan 04, 2019 7:08 pm

I thought about using fstab as well Neddy, but I am still concerned about those issues.
Top
Hu
Administrator
Administrator
Posts: 24403
Joined: Tue Mar 06, 2007 5:38 am

Re: Gentoo Chroot Script

  • Quote

Post by Hu » Sat Jan 05, 2019 1:49 am

StevenC21 wrote:

Code: Select all

#!/bin/bash
Missing use of set -eu.
StevenC21 wrote:

Code: Select all

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: Select all

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: Select all

        echo "No Mount detected"
        echo "Mounting Necessary Filesystems..."
These can be combined.
StevenC21 wrote:

Code: Select all

        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: Select all

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: Select all

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.
Top
StevenC21
n00b
n00b
Posts: 63
Joined: Thu Jun 07, 2018 1:04 pm

  • Quote

Post by StevenC21 » Sat Jan 05, 2019 8:02 pm

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: Select all

#!/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
Top
Hu
Administrator
Administrator
Posts: 24403
Joined: Tue Mar 06, 2007 5:38 am

  • Quote

Post by Hu » Sat Jan 05, 2019 8:40 pm

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.
Top
NeddySeagoon
Administrator
Administrator
User avatar
Posts: 56108
Joined: Sat Jul 05, 2003 9:37 am
Location: 56N 3W

  • Quote

Post by NeddySeagoon » Sat Jan 05, 2019 9:43 pm

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.
Top
ralda
n00b
n00b
Posts: 28
Joined: Sun Apr 21, 2019 7:26 pm

Much more than a simple script to fire up a chroot container

  • Quote

Post by ralda » Sun Apr 28, 2019 2:35 am

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: Select all

# *****************************************************************************
#   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
Top
k9dog
Tux's lil' helper
Tux's lil' helper
Posts: 104
Joined: Mon Jun 22, 2009 10:58 pm
Location: Denmark

  • Quote

Post by k9dog » Fri Dec 16, 2022 10:39 am

@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
Top
Post Reply

12 posts • Page 1 of 1

Return to “Documentation, Tips & Tricks”

Jump to
  • Assistance
  • ↳   News & Announcements
  • ↳   Frequently Asked Questions
  • ↳   Installing Gentoo
  • ↳   Multimedia
  • ↳   Desktop Environments
  • ↳   Networking & Security
  • ↳   Kernel & Hardware
  • ↳   Portage & Programming
  • ↳   Gamers & Players
  • ↳   Other Things Gentoo
  • ↳   Unsupported Software
  • Discussion & Documentation
  • ↳   Documentation, Tips & Tricks
  • ↳   Gentoo Chat
  • ↳   Gentoo Forums Feedback
  • ↳   Duplicate Threads
  • International Gentoo Users
  • ↳   中文 (Chinese)
  • ↳   Dutch
  • ↳   Finnish
  • ↳   French
  • ↳   Deutsches Forum (German)
  • ↳   Diskussionsforum
  • ↳   Deutsche Dokumentation
  • ↳   Greek
  • ↳   Forum italiano (Italian)
  • ↳   Forum di discussione italiano
  • ↳   Risorse italiane (documentazione e tools)
  • ↳   Polskie forum (Polish)
  • ↳   Instalacja i sprzęt
  • ↳   Polish OTW
  • ↳   Portuguese
  • ↳   Documentação, Ferramentas e Dicas
  • ↳   Russian
  • ↳   Scandinavian
  • ↳   Spanish
  • ↳   Other Languages
  • Architectures & Platforms
  • ↳   Gentoo on ARM
  • ↳   Gentoo on PPC
  • ↳   Gentoo on Sparc
  • ↳   Gentoo on Alternative Architectures
  • ↳   Gentoo on AMD64
  • ↳   Gentoo for Mac OS X (Portage for Mac OS X)
  • Board index
  • All times are UTC
  • Delete cookies

© 2001–2026 Gentoo Foundation, Inc.

Powered by phpBB® Forum Software © phpBB Limited

Privacy Policy

 

 

magic