Skip to content

Commit

Permalink
Initial cut of a script that installs chroot environment. This can for
Browse files Browse the repository at this point in the history
example be used to have an accurate 32bit build and test environment when
otherwise working on a 64bit machine.

This script only works on Debian-derived systems.

BUG=none
TEST=none
Review URL: http://codereview.chromium.org/3272004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57962 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
markus@chromium.org committed Aug 31, 2010
1 parent c80549f commit 47b1675
Showing 1 changed file with 221 additions and 0 deletions.
221 changes: 221 additions & 0 deletions build/install-chroot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
#!/bin/bash -e

# Copyright (c) 2010 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This script installs Debian-derived distributions in a chroot environment.
# It can for example be used to have an accurate 32bit build and test
# environment when otherwise working on a 64bit machine.
# N. B. it is unlikely that this script will ever work on anything other than a
# Debian-derived system.

# Check that we are running as a regular user
[ "$(id -nu)" = root ] && {
echo "Run this script as a regular user and provide your \"sudo\"" \
"password if requested" >&2
exit 1
}
mkdir -p "$HOME/chroot/"

# Error handler
trap 'exit 1' INT TERM QUIT
trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT

# Install any missing applications that this script relies on. If these packages
# are already installed, don't force another "apt-get install". That would
# prevent them from being auto-removed, if they ever become eligible for that.
# And as this script only needs the packages once, there is no good reason to
# introduce a hard dependency on things such as dchroot and debootstrap.
dep=
for i in dchroot debootstrap; do
[ -d /usr/share/doc/"$i" ] || dep="$dep $i"
done
[ -n "$dep" ] && sudo apt-get -y install $dep
sudo apt-get -y install schroot

# Create directory for chroot
sudo mkdir -p /var/lib/chroot

# Find chroot environments that can be installed with debootstrap
targets="$(cd /usr/share/debootstrap/scripts
ls | grep '^[a-z]*$')"

# Ask user to pick one of the available targets
echo "The following targets are available to be installed in a chroot:"
j=1; for i in $targets; do
printf '%4d: %s\n' "$j" "$i"
j=$(($j+1))
done
while :; do
printf "Which target would you like to install: "
read n
[ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev/null && break
done
j=1; for i in $targets; do
[ "$j" -eq "$n" ] && { distname="$i"; break; }
j=$(($j+1))
done

# On x86-64, ask whether the user wants to install x86-32 or x86-64
archflag=
arch=
if [ "$(uname -m)" = x86_64 ]; then
while :; do
echo "You are running a 64bit kernel. This allows you to install either a"
printf "32bit or a 64bit chroot environment. %s" \
"Which one do you want (32, 64) "
read arch
[ "${arch}" == 32 -o "${arch}" == 64 ] && break
done
[ "${arch}" == 32 ] && archflag="--arch i386" || archflag="--arch amd64"
arch="${arch}bit"
fi
target="${distname}${arch}"

# Don't overwrite an existing installation
[ -d /var/lib/chroot/"${target}" ] && {
echo "This chroot already exists on your machine." >&2
echo "Delete /var/lib/chroot/${target} if you want to start over." >&2
exit 1
}
sudo mkdir -p /var/lib/chroot/"${target}"

# Remove stale entry from /etc/schroot/schroot.conf. Entries start
# with the target name in square brackets, followed by an arbitrary
# number of lines. The entry stops when either the end of file has
# been reached, or when the beginning of a new target is encountered.
# This means, we cannot easily match for a range of lines in
# "sed". Instead, we actually have to iterate over each line and check
# whether it is the beginning of a new entry.
sudo sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
/etc/schroot/schroot.conf

# Download base system. This takes some time
grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null &&
mirror="http://archive.ubuntu.com/ubuntu" ||
mirror="http://ftp.us.debian.org/debian"
sudo debootstrap ${archflag} "${distname}" /var/lib/chroot/"${target}" \
"$mirror"

# Add new entry to /etc/schroot/schroot.conf
grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null &&
brand="Ubuntu" || brand="Debian"
sudo sh -c 'cat >>/etc/schroot/schroot.conf' <<EOF
[${target%bit}]
description=${brand} ${distname} ${arch}
type=directory
directory=/var/lib/chroot/${target}
priority=3
users=root
groups=admin
root-groups=admin
personality=linux$([ "${arch}" != 64bit ] && echo 32)
script-config=script-${target}
EOF

# Set up a special directory that changes contents depending on the target
# that is executing.
sed '/^FSTAB=/s,/mount-defaults",/mount-'"${target}"'",' \
/etc/schroot/script-defaults |
sudo sh -c 'cat >/etc/schroot/script-'"${target}"
sudo cp /etc/schroot/mount-defaults /etc/schroot/mount-"${target}"
echo "$HOME/chroot/.${target} $HOME/chroot none rw,bind 0 0" |
sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
mkdir -p "$HOME/chroot/.${target}"

# Install a helper script to launch commands in the chroot
sudo sh -c 'cat >/usr/local/bin/'"${target%bit}" <<EOF
#!/bin/bash
if [ \$# -eq 0 ]; then
exec schroot -c ${target%bit} -p
else
p="\$1"; shift
exec schroot -c ${target%bit} -p "\$p" -- "\$@"
fi
exit 1
EOF
sudo chown root:root /usr/local/bin/"${target%bit}"
sudo chmod 755 /usr/local/bin/"${target%bit}"

# Add a few more repositories to the chroot
[ -r /var/lib/chroot/${target}/etc/apt/sources.list ] &&
sudo sed -i 's/ main$/ main restricted universe multiverse/
p
t1
d
:1;s/^deb/deb-src/
t
d' /var/lib/chroot/${target}/etc/apt/sources.list

# Update packages
sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
apt-get update; apt-get -y dist-upgrade' || :

# Install a couple of missing packages
for i in debian-keyring ubuntu-keyring locales sudo; do
[ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] ||
sudo schroot -c "${target%bit}" -p -- apt-get -y install "$i" || :
done

# Configure locales
sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
l='"${LANG:-en_US}"'; l="${l%%.*}"
[ -r /etc/locale.gen ] &&
sed -i "s/^# \($l\)/\1/" /etc/locale.gen
locale-gen $LANG en_US en_US.UTF-8' || :

# Configure "sudo" package
sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
egrep '"'^$(id -nu) '"' /etc/sudoers >/dev/null 2>&1 ||
echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers'

# Install a few more commonly used packages
sudo schroot -c "${target%bit}" -p -- apt-get -y install \
autoconf automake1.9 dpkg-dev g++-multilib gcc-multilib gdb less libtool \
strace

# If running a 32bit environment on a 64bit machine, install a few binaries
# as 64bit.
if [ "${arch}" = 32bit ] && file /bin/bash 2>/dev/null | grep -q x86-64; then
sudo schroot -c "${target%bit}" -p -- apt-get -y install \
lib64expat1 lib64ncurses5 lib64readline6 lib64z1
dep=
for i in binutils gdb strace; do
[ -d /usr/share/doc/"$i" ] || dep="$dep $i"
done
[ -n "$dep" ] && sudo apt-get -y install $dep
sudo cp /usr/bin/gdb /var/lib/chroot/${target}/usr/local/bin/
sudo cp /usr/bin/ld /var/lib/chroot/${target}/usr/local/bin/
for i in libbfd libpython; do
lib="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } |
grep "$i" | awk '{ print $3 }')"
if [ -n "$lib" -a -r "$lib" ]; then
sudo cp "$lib" /var/lib/chroot/${target}/usr/lib64/
fi
done
for lib in libssl libcrypt; do
sudo cp /usr/lib/$lib* /var/lib/chroot/${target}/usr/lib64/ || :
done
fi

# Clean up package files
sudo schroot -c "${target%bit}" -p -- apt-get clean
sudo apt-get clean

# Let the user know what we did
trap '' INT TERM QUIT
trap '' EXIT
cat <<EOF
Successfully installed ${distname} ${arch}
You can run programs inside of the chroot by invoking the "${target%bit}"
command.
Your home directory is shared between the host and the chroot. But I configured
$HOME/chroot to be private to the chroot environment. You can use it
for files that need to differ between environments.
EOF

0 comments on commit 47b1675

Please sign in to comment.