My *nix world

Gentoo 32-bit chroot environment on amd64 no-multilib

I have a Gentoo amd64 no-multilib configuration and sometimes I really need to run 32-bit application (Skype or Android SDK that are available only for 32bit environment).

For these I have prepared a 32-bit chroot-ed environment as specified in 32Bit Chroot Guide for Gentoo/AMD64.

Inside the 32-bit chroot environment I want to use the XServer with Xfce desktop environment. To make sure I will have a basic Xfce environment as I already have in the amd64 environment, I just copied the /etc/make.conf file to /mnt/gentoo32/etc/make.conf and I have adjust few options (tunned for my 32-bit virtual environment)

Gentoo 32-bit chroot environment on amd64 no-multilib

# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.

# compiler optimization
CFLAGS="-O2 -pipe -march=native -mtune=native -fomit-frame-pointer -fno-var-tracking"
CXXFLAGS="${CFLAGS}"
LDFLAGS="-Wl,-O1 -Wl,--as-needed"

# parallel build " gcc cache
MAKEOPTS="-j2"
CCACHE_DIR="/var/tmp/ccache"
CCACHE_SIZE="1G"
FEATURES="parallel-fetch userfetch ccache candy compress-build-logs"

# WARNING: Changing your CHOST is not something that should be done lightly.
# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.
CHOST="i686-pc-linux-gnu"
ACCEPT_KEYWORDS="x86"
LINGUAS="en"

# use the following gentoo repository servers:
GENTOO_MIRRORS="http://mirror.mdfnet.se/gentoo"
SYNC="rsync://rsync.se.gentoo.org/gentoo-portage"

# by default we acknowledge the have the following devices
INPUT_DEVICES="keyboard mouse evdev synaptics"
VIDEO_CARDS="radeon vesa fbdev"
ALSA_CARDS="ens1370"
WEB_CAM="v4l v4l2"
APACHE2_MODULES="*-"
CAMERAS="*-"
CALLIGRA_FEATURES="*-"
GPSD_PROTOCOLS="*-"
LCD_DEVICES="*-"

# do not unmask automatically anything but accept any 3rd party license agreement
EMERGE_DEFAULT_OPTS="--autounmask=n"
ACCEPT_LICENSE="*"

# These are the USE flags that were used in addition to what is provided by the
# profile used for building.
# See: http://www.gentoo.org/dyn/use-index.xml
USE_OPTIMIZATION="optimization strong-optimization mmx pch sharedmem smp sse sse2 lto graphite optimized-qmake"
USE_SYS_KERNEL="savedconfig"
USE_SYS_LIBS="glibc-omitfp python"

USE_LAPTOP="acpi" # bluetooth"
USE_X="truetype X new-login xorg"
USE_IMAGE="jpeg gif tiff png svg pdf"
USE_MEDIA="sound alsa mad vidix asf win32codecs dvd mp4 aac x264 xvid nsplugin mp3 real gstreamer"
USE_GENERAL="udev ncurses bash-completion libnotify ftp samba java bzip2 symlink sqlite threadsafe spell xml lm_sensors"
USE_SYSTEM="hal fam dbus aoss nptl threads"
USE_DONT="-arts -qt4 -ipv6 -opengl"
USE_KDE="-kde -qt3"
#USE_GNOME="gtk cairo gnome gnome-keyring archive sendto aisleriot"
USE_GNOME="-gnome -gnome-keyring"
USE_LXDE="-lxde cairo"
USE_XFACE="session startup-notification"

USE_APP_ADMIN="edit sudo custom-optimization"
USE_APP_EMULATION="consolekit"
USE_WWW_PLUGINS="32bit"
USE_X11_TERMS="mousewheel"
USE_X11_DUALMONITOR="-xinerama"
USE_X_COMPOSITE="xcomposite"
USE="${USE_DONT} ${USE_SYSTEM} ${USE_GENERAL} ${USE_IMAGE} ${USE_X} ${USE_KDE} ${USE_MEDIA} ${USE_OPTIMIZATION} ${USE_APP_ADMIN} ${USE_APP_EMULATION} ${USE_GNOME}"
USE="${USE} ${USE_SYS_KERNEL} ${USE_SYS_LIBS} ${USE_WWW_PLUGINS} ${USE_X11_DRIVERS} ${USE_X11_TERMS} ${USE_LXDE} ${USE_XFACE} ${USE_X11_DUALMONITOR} ${USE_X_COMPOSITE} ${USE_KVM} ${WEB_CAM} ${USE_LAPTOP}"

Also, I have configured the /mnt/gentoo32/etc/portage/package.use and /mnt/gentoo32/etc/portage/package.keywords configuration files with those options necessary to build my 32-bit environment:

package.use

x11-base/xorg-server udev
sys-auth/consolekit policykit
sys-apps/hal policykit
dev-libs/libxml2 python
sys-fs/udev extras
app-crypt/pinentry gtk
gnome-base/gvfs gdu
media-libs/libpng apng
app-emulation/wine custom-cflags

package.keywords

>=net-im/skype-2.2.0.35-r1
app-emulation/winetricks **

In the virtual 32-bit environment I have installed just those applications I will really need, such as:

  • app-admin/sudo
  • app-editors/nano
  • app-emulation/wine
  • app-emulation/winetricks
  • app-portage/gentoolkit
  • dev-util/ccache
  • net-im/skype
  • gnome-extra/zenity
  • x11-base/xorg-drivers
  • x11-base/xorg-server
  • x11-terms/terminal
  • xfce-base/thunar
  • xfce-base/xfce4-meta
  • xfce-extra/thunar-archive-plugin
  • xfce-extra/thunar-volman
  • xfce-extra/tumbler

For building the above 32-bit application within the chroot-ed environment just chroot inside the 32-bit environment (eg: sudo linux32 chroot /mnt/gentoo32/ /bin/bash) and run (as root) the command below:

emerge -DuN world

After several minutes/hours (this depends on your hardware) you should have a 32-bit environment with everythig that is need it for running a XServer with Xfce desktop environment.

Inside the chroot-ed environment create the following file in the home directory of user (eg: /mnt/gentoo//):

.bashrc

# /etc/skel/.bashrc
#
# This file is sourced by all *interactive* bash shells on startup,
# including some apparently interactive shells such as scp and rcp
# that can't tolerate any output. So make sure this doesn't display
# anything or bad things will happen !

# Test for an interactive shell. There is no need to set anything
# past this point for scp and rcp, and it's important to refrain from
# outputting anything in those cases.
if [[ $- != *i* ]] ; then
# Shell is non-interactive. Be done now!
return
fi

# Put your fun stuff here.

# if X is not started already then start your favorite X session
# otherwise just run the normal terminal (within the chroot-ed X session)
if [ -z $DISPLAY ];then
startxfce4 -- :1
exit
fi

Inside the chroot-ed environment create a file named 90xsession in the /etc/env.d/ folder:

XSESSION="Xfce4"

Now, if you issue the X command at the console within the chroot-ed environment, it should start the XServer and launch the Xfce desktop environment for you. When you logoff from the Xfce session it should return to the console within the chroot-ed environment.

Let's automate little bit the way we get into the chroot environment and how we launch the Xfce session on that environment!

Instead of mounting/unmounting the virtual filesystem (as described in step 2.c) I have created a bash script which will help me to:

  • automatically mount the necessary folders/devices for my chroot environment virtual file system
  • copy the necessary configuration files into the chroot-ed environment (eg: resolv.conf, hosts, passwd)
  • enter to 32-bit chroot-ed environment and login as prefered user
  • start Xfce session (or whatever program from the chrooted environment) in the chroot-ed environment on display 1 (or even on the display 0), so both sessions - the amd64 default Xfce session and the newly created chroot-ed 32bit Xfce session - are available simultaneously (switch between them with Ctrl+Alt+Fn, where n could be 7,8,...); if you started just a program on current display (eg: display 0) then no switch available/need it
  • exit cleanly from chroot-ed environment and umount previously mounted folders for the virtual file system

So just launching the bash script it will create automatically for you the chroot environment and will start a new X session on another virtual display (eg: display 1). You can, as explained above, work on both sessions, but you have to switch between them with Ctrl+Alt+Fn keys.

First create a bash script called gentoo32 as bellow:

#!/bin/bash

######################################################################
#
# Title : Linux x86 chroot bootstrap
#
# Author: Eugen Mihailescu 
# Created date: 2011, November
# Last modified 2012-09-06
#
# Generic bash script to chroot into a x86 Linux environment
# (e.g. from a x86_64 Linux environment), to mount some custom mount
# points then to launch a command (e.g start a Xfce4 session in
# display #2). On exist it clears all the way back, clean & smooth.
#
# Note: all options are described in print_syntax() function bellow.

######################################################################

# Path where the chroot environment is installed
CHROOT_ENV_PATH="/mnt/gentoo32"

# Print the script help syntax
function print_syntax()
{
	echo -e "Usage : $0 [OPTION]...\nLogin to a chrooted environment as  then imediately run the  command on the specified  display.\n"
	echo -e "Mandatory arguments to long options are mandatory for short options too.\n"
	echo -e "  -s, --service \tmount|unmount necessary folders and start|stop chroot-ed environment"
	echo -e "  -c, --command \trun the  command immediately after loging in the chroot-ed environment"
	echo -e "  -d, --display \tthe virtual terminal used to display the  command"
	echo -e "  -u, --user \tthe user used to login in the chroot-ed environment\n"
	echo "Report bugs to "
}

SHORTOPTS="s: c: d: u:"
LONGOPTS="service: command: display: user:"
set -- `getopt -a -u --options="$SHORTOPTS" --longoptions="$LONGOPTS" --name="$0" -- "$@"` || print_syntax

# Check for sufficent args
if [ $# -lt 2 ] ; then
        print_syntax
        exit 1
fi

# Read the options/arguments from command-line
while [ $# -gt 0 ];do
  case $1 in
    -s|--service)
	SERVICE=$2;shift;;
    -c|--command)
	COMMAND=$2;shift;;
    -d|--display)
	VT=$2;shift;;
    -u|--user)
	CHROOT_USR=$2;shift;;
    \?)	echo "Invalid option: -$1";
	print_syntax;
	exit 1;
 	;;
    :)
	echo "Option -$1 requires an argument.";
	print_syntax;
	exit 1;
	;;
    -h) print_syntax;;
    --) shift;break;;
    -*) print_syntax;;
     *) break;;
  esac
  shift
done

if [ "${CHROOT_USR}" == "" ];then
	CHROOT_USR="`whoami`"
fi

kernel_version=`uname -r`

# Set terminal title
# @param string $1  Tab/window title
# @param string $2  (optional) Separate window title
# The latest version of this function can be obtained here:
# http://fvue.nl/wiki/NameTerminal
function nameTerminal() {
    [ "${TERM:0:5}" = "xterm" ]   && local ansiNrTab=0
    [ "$TERM"       = "rxvt" ]    && local ansiNrTab=61
    [ "$TERM"       = "konsole" ] && local ansiNrTab=30 ansiNrWindow=0
        # Change tab title
    [ $ansiNrTab ] && echo -n $'\e'"]$ansiNrTab;$1"$'\a'
        # If terminal support separate window title, change window title as well
    [ $ansiNrWindow -a "$2" ] && echo -n $'\e'"]$ansiNrWindow;$2"$'\a'
}

# Terminal title
nameTerminal "32bit chroot enviroment"

# Create a .bashrc file on the home directory of chrooted user ${CHROOT_USR}
# This .bashrc file is prepared to run the command  on display 
function prepare_bashrc(){
        # Replace   and " in  with a space respectively with double quote
        # Note: you can specify   in your  instead of  ASCII,
        # the script will convert it to ASCII space at runtime
        startup_app=$(echo $1|awk '{p=gsub(/ /, " ");gsub(/"/, "\""); print}')
	display=$2
	bashrc_path="${CHROOT_ENV_PATH}/home/${CHROOT_USR}/.bashrc"
	echo "#Automatically created by $0"  > ${bashrc_path}
	echo "export PS1=\"(\`uname -m\`) \$PS1\"" >> ${bashrc_path}
	echo "if [[ \$- != *i* ]] ; then" >> ${bashrc_path}
	echo "	return" >> ${bashrc_path}
	echo "fi" >> ${bashrc_path}
	echo "if [ -z \$DISPLAY ];then" >> ${bashrc_path}
	if [ "${display}" != "" ];then
		echo "	export DISPLAY=":${display}"" >> ${bashrc_path}
	fi
	echo "	${startup_app}" >> ${bashrc_path}
        echo "	exit" >> ${bashrc_path}
	echo "fi" >> ${bashrc_path}
	chown ${CHROOT_USR}:${CHROOT_USR} ${bashrc_path}
}

start() {
    echo -e "\E[1;31m[1] Mounting chroot dirs...\033[0m"

    # MANDATORY : mount the volume where gentoo32 is installed
    is_mounted=$(mount|grep -i ${CHROOT_ENV_PATH}/proc)
    if [ "$is_mounted" == "" ];then
	    mount /dev/vg/lvgentoo32 ${CHROOT_ENV_PATH}
    else
	echo "${CHROOT_ENV_PATH} already mounted. Carry on..."
    fi

    if [ "$is_mounted" == "" ];then
	    # MANDATORY : bind the local system folders to the corresponding folders inside the chrooted environment
	    mount -o bind /proc ${CHROOT_ENV_PATH}/proc
	    mount -o bind /sys ${CHROOT_ENV_PATH}/sys
	    mount -o bind /tmp ${CHROOT_ENV_PATH}/tmp
	    mount -o bind /dev ${CHROOT_ENV_PATH}/dev
	    mount -o bind /dev/pts ${CHROOT_ENV_PATH}/dev/pts
	    mount -o bind /dev/shm ${CHROOT_ENV_PATH}/dev/shm

	    mkdir -p ${CHROOT_ENV_PATH}/lib/modules/${kernel_version}
	    mount -o bind /lib/modules/${kernel_version}/ ${CHROOT_ENV_PATH}/lib/modules/${kernel_version}/
	    mount -o remount,ro ${CHROOT_ENV_PATH}/lib/modules/${kernel_version}/
	    mount -o bind /var/run/dbus/ ${CHROOT_ENV_PATH}/var/run/dbus
	    mount -o remount,ro ${CHROOT_ENV_PATH}/var/run/dbus

	    # OPTIONAL : bind the local user folders to the corresponding folders inside the chrooted environment
	    mount -o bind /home/eugen/svn ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/svn 2>/dev/null
	    mount -o bind /home/eugen/git/cubiquelicadmin ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/workspace/java/CubiqueLicAdmin/ 2>/dev/null
	    mount -o bind /home/eugen/git/cubiquelicadminj ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/workspace/java/CubiqueLicAdminJ/ 2>/dev/null
	    mount -o bind /home/eugen/git/cubiquelicadminphp ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/workspace/java/CubiqueLicAdminPHP/ 2>/dev/null
	    mount -o bind /home/eugen/git/cubiquelicmngr ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/workspace/java/CubiqueLicMngr/ 2>/dev/null
	    mount -o bind /home/eugen/Dev/bash.scripts ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/Dev/bash.scripts 2>/dev/null
	    mount -o remount,ro ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/Dev/bash.scripts 2>/dev/null
	    mount -o bind /usr/src/linux ${CHROOT_ENV_PATH}/usr/src/linux/ 2>/dev/null
	    mount -o remount,ro ${CHROOT_ENV_PATH}/usr/src/linux/ 2>/dev/null
	    echo -e "\E[1;32m[1] Done.\033[0m"

	    # MANDATORY : copy the local system security files/settings to the corresponding files inside the chrooted environment
	    echo -e "\E[1;31m[2] Copying neccessary files for chrooted environment...\033[0m"
	    cp -pf /etc/resolv.conf ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    cp -pf /etc/passwd ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    cp -pf /etc/shadow ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    cp -pf /etc/group ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    cp -pf /etc/gshadow ${CHROOT_ENV_PATH}/etc 2>/dev/null 
	    cp -pf /etc/hosts ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    cp -Ppf /etc/localtime ${CHROOT_ENV_PATH}/etc 2>/dev/null
	    echo -e "\E[1;32m[2] Done.\033[0m"
    fi
}

# Function for unmounting the 
stop() {
    multiple_chroot="`who|grep \"(:0.0)\"|awk '{print $NF}'`"
    if [ "$is_mounted" = "" ];then # if the volume was mounted by other parallel chroot session then don't touch the mount points
    	echo -e "\E[1;31m[*] Unmounting chrooted dirs...\033[0m"
	    # MANDATORY : unmount the chrooted environment system folder bindings
	    umount -l ${CHROOT_ENV_PATH}/dev/{pts,shm}
	    umount -l ${CHROOT_ENV_PATH}/{dev,proc,sys,tmp}
	    umount -l ${CHROOT_ENV_PATH}/lib/modules/${kernel_version}/
    	    umount -l ${CHROOT_ENV_PATH}/var/run/dbus

	    # OPTIONAL : unmount the chrooted environment user folder bindings
	    umount -l ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/workspace/java/{CubiqueLicAdmin,CubiqueLicAdminJ,CubiqueLicAdminPHP,CubiqueLicMngr}
	    umount -l ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/Dev/bash.scripts
	    umount -l ${CHROOT_ENV_PATH}/home/${CHROOT_USR}/svn
	    umount -l ${CHROOT_ENV_PATH}/usr/src/linux
	    umount -l ${CHROOT_ENV_PATH}
	    echo -e "\E[1;32m[*] Done.\033[0m"
    fi
}

# Switch to root profile if running as normal user
if [ "$(whoami)" != "root" ]; then
	echo -e "\E[1;34m"
	params=""
	if [ "${SERVICE}" != "" ];then
		params+=" -s ${SERVICE}"
	fi
        if [ "${COMMAND}" != "" ];then
                params+=" -c ${COMMAND}"
        fi
        if [ "${VT}" != "" ];then
                params+=" -d ${VT}"
        fi
        if [ "${CHROOT_USR}" != "" ];then
                params+=" -u ${CHROOT_USR}"
        fi

        sudo -p "Enter root password for entering into chrooted environment : " -u root $0 ${params}
	echo -e "\033[0m"
        err=$?
	exit $err
else
        ${SERVICE}
	err=0
fi

# Run the chrooted environment, login to it as  then run the  on display 
if [ "$err" == "0" ];then
        if [ "$SERVICE" == "start" ];then
		echo -e "\E[1;31m[3] Entering to chroot environment...\033[0m"
		prepare_bashrc "${COMMAND}" "${VT}"
		linux32 chroot ${CHROOT_ENV_PATH} /bin/bash -c "echo -e 'Login as \E[1;35m${CHROOT_USR}\033[0m within \E[1;34mchroot-ed\033[0m environment...' && login ${CHROOT_USR}"
		echo -e "\E[1;32m[4] Exited from chroot environment.\033[0m"
		stop
        fi
fi

Note: in the above script (1) /gentoo32> should be your linux folder where you have installed the chrooted environment.

When you will run the above script it will ask you for root password (mount requires root authentification), will open automatically the 32-bit chroot-ed environment, will ask you the password for the and then will launch Xfce session for you. When you will logoff from the X session within the chroot-ed environment, the same script will take care of exiting from the chroot-ed environment, unmounting previously mounted folders. So everything is lean and clean...

Usage : /usr/sbin/gentoo32 [OPTION]...
Login to a chrooted environment as  then imediately run the  command on the specified  display.

Mandatory arguments to long options are mandatory for short options too.

  -s, --service 	mount|unmount necessary folders and start|stop chroot-ed environment
  -c, --command 	run the  command immediately after loging in the chroot-ed environment
  -d, --display 	the virtual terminal used to display the  command
  -u, --user 	the user used to login in the chroot-ed environment

Report bugs to 

Examples:

  • launch Xfce session in the chrooted environment:

gentoo32 --service=start --command="startxfce4"--":1" --user=myname

  • launch Eclipse application without starting a separate 32-bit Xfce session, on the same display (eg: display 0) as the main Xfce 64-bit session:

gentoo32 --service=start --command="eclipse" -d 0 --user=myname

  • launch Skype application without starting a separate 32-bit Xfce session, on the same display (eg: display 0) as the main Xfce 64-bit session:

gentoo32 --service=start --command="skype" -d 0 --user=myname

Now, if you think that this article was interesting don't forget to rate it. It shows me that you care and thus I will continue write about these things.

 
The following two tabs change content below.
Gentoo 32-bit chroot environment on amd64 no-multilib

Eugen Mihailescu

Founder/programmer/one-man-show at Cubique Software
Always looking to learn more about *nix world, about the fundamental concepts of math, physics, electronics. I am also passionate about programming, database and systems administration. 16+ yrs experience in software development, designing enterprise systems, IT support and troubleshooting.

Leave a Reply

Your email address will not be published. Required fields are marked *