Add scripts to setup 32-bit chroots for building.

This commit is contained in:
Steve Hill
2016-11-10 11:54:08 -05:00
parent 176da99558
commit 8b8658bd72
10 changed files with 342 additions and 0 deletions
+2
View File
@@ -17,6 +17,8 @@ if [ -f "$devtoolset_enable" ]; then
fi
export CHROOT_DIR=/var/chroot/centos_i386
export SSL_CERT_DIR=/etc/pki/tls/certs
export SSL_CERT_FILE=/etc/pki/tls/cert.pem
+50
View File
@@ -0,0 +1,50 @@
#!/bin/bash
# Copyright 2016 Google Inc. All Rights Reserved.
# Author: cheesy@google.com (Steve Hill)
#
# This script emulates the behavior of schroot, which:
# - Invokes chroot(2) as root (schroot is setuid).
# - setuids back to the uid it was run as.
# - chdirs to the directory it was run from.
# - execs the command supplied as arguments, or starts an interactive shell.
#
# Trying to write a single command that can be passed to sudo that will do the
# su, chdir, exec combination without breaking arg tokenisation is nigh
# impossible. Instead, once the chrooting and setuiding (via sudo) has been
# taken care of, the script execs itself with --chroot_done. This takes care
# of the chdir and exec.
# This comes from build_env.sh.
if [ -z "${CHROOT_DIR:-}" ]; then
echo "This must be run via os_redirector.sh!" >&2
exit 1
fi
# When we re-invoke the script, it's called with:
# --chroot_done <directory> [CMD]
# It then chdirs to <directory> and invokes CMD or an interactive $SHELL
if [ "${1-}" = "--chroot_done" ]; then
if [ $# -lt 2 ]; then
echo "Do not run this directly with --chroot_done" >&2
exit 1
fi
cd "$2"
shift 2
if [ $# -eq 0 ]; then
set -- "$SHELL" -l
fi
eval exec "$@"
exit 1 # NOTREACHED
fi
# We need the absolute path to re-exec the script after the chroot.
this_script="$0"
if [[ "$this_script" != /* ]]; then
this_script="$PWD/$this_script"
fi
# Note that here $0 is expected to be a symlink to os_redirector.sh.
exec setarch i386 sudo /usr/sbin/chroot "$CHROOT_DIR" sudo -u "$USER" -i -- \
"$this_script" --chroot_done "$PWD" "$@"
+120
View File
@@ -0,0 +1,120 @@
#!/bin/bash
# Copyright 2016 Google Inc. All Rights Reserved.
# Author: cheesy@google.com (Steve Hill)
#
# Setup a 32-bit chroot for CentOS.
# This comes from build_env.sh.
if [ -z "${CHROOT_DIR:-}" ]; then
echo "This must be run via os_redirector.sh!" >&2
exit 1
fi
if [ -d "$CHROOT_DIR" ]; then
"$install_dir/run_in_chroot.sh" /bin/true >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo chroot already setup, nothing to do.
exit 0
else
echo "$CHROOT_DIR exists but doesn't seem to be setup correctly." >&2
echo "You're going to have to clean up manually." >&2
exit 1
fi
fi
if [ "$UID" != 0 ]; then
echo "This script needs to run as root, re-running with sudo"
exec sudo $0 "$@"
exit 1 # NOTREACHED
fi
# TODO(cheesy): The release_rpm stuff below is not especially robust, but
# scraping the site is a pain. If this is a problem we can fix it later.
centos_version="$(lsb_release -rs)"
git_pkg=
if version_compare "$centos_version" -lt 6; then
# CentOS 5
release_rpm_url=http://mirror.centos.org/centos/5/os/i386/CentOS/centos-release-5-11.el5.centos.i386.rpm
elif version_compare "$centos_version" -lt 7; then
# CentOS 6
release_rpm_url=http://mirror.centos.org/centos/6/os/i386/Packages/centos-release-6-8.el6.centos.12.3.i686.rpm
# TODO(cheesy): Once gclient is gone, we may be able to use the git rpm.
else
# CentOS 7
release_rpm_url=http://mirror.centos.org/altarch/7/os/i386/Packages/centos-release-7-2.1511.el7.centos.2.9.i686.rpm
git_pkg=git
fi
release_rpm="$(basename "$release_rpm_url")"
wget -O "$release_rpm" "$release_rpm_url"
mkdir -p "$CHROOT_DIR/var/lib/rpm"
# Required to run the chroot in 32-bit mode.
yum -y install setarch
function cleanup_etc_rpm_platform() {
if [ -s /etc/rpm/platform.real ]; then
mv -f /etc/rpm/platform.real /etc/rpm/platform
elif [ -f /etc/rpm/platform.real ]; then
# Only do this if platform.real exists, otherwise we could delete a
# perfectly valid file.
rm -f /etc/rpm/platform /etc/rpm/platform.real
fi
}
# To force install a different architecture, we must put a fake arch into
# /etc/rpm/platform. Older CentOSes will have the file, newer may not. Either
# way, it's important that we don't leave the fake one lying around.
trap 'cleanup_etc_rpm_platform' EXIT
if [ -e /etc/rpm/platform ]; then
mv /etc/rpm/platform /etc/rpm/platform.real
else
touch /etc/rpm/platform.real
fi
echo i686-redhat-linux > /etc/rpm/platform
rpm --root="$CHROOT_DIR" --rebuilddb
rpm --root="$CHROOT_DIR" --nodeps -i "$release_rpm"
yum -y --installroot="$CHROOT_DIR" update
# redhat-lsb and sudo are required for run_in_chroot.sh
yum -y --installroot="$CHROOT_DIR" install yum sudo redhat-lsb
cleanup_etc_rpm_platform
trap - EXIT
for x in passwd shadow group gshadow hosts sudoers resolv.conf; do
ln -f "/etc/$x" "$CHROOT_DIR/etc/$x"
done
cp -p /etc/yum.repos.d/* "$CHROOT_DIR/etc/yum.repos.d/"
# These don't work for 32-bit.
if version_compare "$centos_version" -ge 6; then
rm -f "$CHROOT_DIR/etc/yum.repos.d"/CentOS-SCLo-scl[.-]*
fi
for dir in /proc /sys /dev /selinux /etc/selinux /home; do
[ -d "$dir" ] || continue
chroot_dir="${CHROOT_DIR}$dir"
if [ ! -d "$chroot_dir" ]; then
mkdir -p "$chroot_dir"
chown --reference "$dir" "$chroot_dir"
chmod --reference "$dir" "$chroot_dir"
fi
echo "$dir $chroot_dir none bind 0 0" >> /etc/fstab
done
echo "none $CHROOT_DIR/dev/shm tmpfs defaults 0 0" >> /etc/fstab
mount -a
# The previous yum install above probably did all the updates,
# but it doesn't hurt to ask.
install/run_in_chroot.sh yum -y update
install/run_in_chroot.sh yum -y install which redhat-lsb curl wget $git_pkg
if [ -z "$git_pkg" ]; then
install/run_in_chroot.sh install/install_from_source.sh git
fi
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# Copyright 2016 Google Inc. All Rights Reserved.
# Author: cheesy@google.com (Steve Hill)
#
# Trivial wrapper for shell function that installs a package from source
# tarball.
source "$(dirname "$BASH_SOURCE")/build_env.sh" || exit 1
install_from_src "$@"
+1
View File
@@ -0,0 +1 @@
os_redirector.sh
+1
View File
@@ -0,0 +1 @@
os_redirector.sh
+66
View File
@@ -83,3 +83,69 @@ function run_with_log() {
fi
return $rc
}
# Compare version numbers in dotted notation.
# Usage: version_compare <version_a> <comparator> <version_b>
# For instance:
# if version_compare $version -lt 4.2; then echo "Too old!"; fi
#
function version_compare() {
if [ $# -ne 3 ]; then
echo "Usage: version_compare <version_a> <comparator> <version_b>" >&2
exit 1
fi
local a=$1
local comparator=$2
local b=$3
if [[ "$a" == *[^.0-9]* ]]; then
echo "Non-numeric version: $a" >&2
exit 1
fi
if [[ "$b" == *[^.0-9]* ]]; then
echo "Non-numeric version: $b" >&2
exit 1
fi
# The computed difference. 0 means a == b, -1 means a < b, 1 means a > b.
local difference=0
while [ $difference -eq 0 ]; do
if [ -z "$a" -a -z "$b" ]; then
break
elif [ -z "$a" ]; then
# a="" and b != "", therefore a < b
difference=-1
break
elif [ -z "$b" ]; then
# a != "" and b="", therefore a > b
difference=1
break
fi
# $a is N[.N.N]. Extract the first N from the beginning into $a_tok
local a_tok="${a%%.*}"
# Make $a any remaining N.N.
a="${a#*.}"
[ "$a" = "$a_tok" ] && a="" # Happens when there are no dots in $a
# Same for $b
local b_tok="${b%%.*}"
b="${b#*.}"
[ "$b" = "$b_tok" ] && b=""
# Now do the integer comparison between a and b.
if [ "$a_tok" -lt "$b_tok" ]; then
difference=-1
elif [ "$b_tok" -gt "$b_tok" ]; then
difference=1
fi
done
# Now do the actual comparison. We use the supplied comparator (say -le) to
# compare the computed difference with zero. This will return the expected
# result.
[ "$difference" "$comparator" 0 ]
}
+3
View File
@@ -14,3 +14,6 @@ if [ -x "${compiler_path}/bin/gcc" ]; then
fi
export PATH=$HOME/bin:/usr/local/bin:$PATH
# precise_i386, for instance.
CHROOT_NAME="$(lsb_release -cs)_i386"
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
# Copyright 2016 Google Inc. All Rights Reserved.
# Author: cheesy@google.com (Steve Hill)
#
# Run a single command in a chroot via schroot.
exec schroot -c "$CHROOT_NAME" -- "$@"
+82
View File
@@ -0,0 +1,82 @@
#!/bin/bash
# Copyright 2016 Google Inc. All Rights Reserved.
# Author: cheesy@google.com (Steve Hill)
#
# Setup a 32-bit chroot for Ubuntu.
install_dir="$(dirname "${BASH_SOURCE[0]}")/.."
chroot_dir="/var/chroot/$CHROOT_NAME"
if [ -d "$chroot_dir" ]; then
"$install_dir/run_in_chroot.sh" /bin/true >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo chroot already setup, nothing to do.
exit 0
else
echo "$chroot_dir exists but doesn't seem to be setup correctly." >&2
echo "You're going to have to clean up manually." >&2
exit 1
fi
fi
if [ "$UID" -ne 0 ]; then
echo This script needs to run as root. Re-execing via sudo.
exec sudo $0 "$@"
exit 1 # NOTREACHED
fi
apt-get -y update
# We have to install ssl-cert in the host because /etc/group is copied
# into the chroot.
apt-get -y install debootstrap dchroot ssl-cert
distro_name="$(lsb_release -cs)"
# Create the initial chroot.
debootstrap --variant=buildd --arch i386 \
"$distro_name" "$chroot_dir" http://archive.ubuntu.com/ubuntu/
# Stop daemons from starting in the chroot. Do this before updating any pkgs!
# https://major.io/2016/05/05/preventing-ubuntu-16-04-starting-daemons-package-installed/
cat > "$chroot_dir/usr/sbin/policy-rc.d" << EOF
#!/bin/sh
# Prevent all daemons from starting.
# Created by $(basename $0) for mod_pagespeed.
exit 101
EOF
chmod +x "$chroot_dir/usr/sbin/policy-rc.d"
# Configure schroot
cat >> /etc/schroot/schroot.conf << EOF
[$CHROOT_NAME]
description=Ubuntu $distro_name for i386
directory=$chroot_dir
type=directory
personality=linux32
preserve-environment=true
root-groups=sudo
groups=sudo
EOF
cat >> /etc/schroot/default/fstab << EOF
# Don't add /dev/shm, weird things will happen. See:
# https://bugs.launchpad.net/ubuntu/+source/schroot/+bug/1438942/comments/5
none /run/shm tmpfs rw,nosuid,nodev,noexec 0 0
EOF
cat >> /etc/schroot/default/copyfiles << EOF
/etc/apt/sources.list
EOF
# schroot is now functional, so we can use run_in_chroot.sh to complete setup
# of the chroot.
"$install_dir/run_in_chroot.sh" apt-get -y update
"$install_dir/run_in_chroot.sh" apt-get -y upgrade
"$install_dir/run_in_chroot.sh" apt-get -y install locales sudo lsb-release
"$install_dir/run_in_chroot.sh" locale-gen en_US.UTF-8
# This must be done after we install sudo or dpkg gets cranky.
echo /etc/sudoers >> /etc/schroot/default/copyfiles