svn commit: r187371 - head/tools/tools/sysbuild

Poul-Henning Kamp phk at FreeBSD.org
Sat Jan 17 12:30:08 PST 2009


Author: phk
Date: Sat Jan 17 20:30:06 2009
New Revision: 187371
URL: http://svn.freebsd.org/changeset/base/187371

Log:
  Release the evil twin of nanobsd.sh: sysbuild.sh
  
  quoth the README:
  
  I have been running -current on my laptop since before FreeBSD 2.0 was
  released and along the way developed this little trick to making the
  task easier.
  
  sysbuild.sh is a way to build a new FreeBSD system on a computer from
  a specification, while leaving the current installation intact.
  
  sysbuild.sh assume you have two partitions that can hold your rootfs
  and can be booted, and roughly speaking, all it does is build a new
  system into the one you don't use, from the one you do use.
  
  A partition named /freebsd is assumed to be part of your layout, and
  that is where the sources and ports will be found.
  
  If you know how nanobsd works, you will find a lot of similarity.

Added:
  head/tools/tools/sysbuild/
  head/tools/tools/sysbuild/README   (contents, props changed)
  head/tools/tools/sysbuild/sysbuild.sh   (contents, props changed)

Added: head/tools/tools/sysbuild/README
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/sysbuild/README	Sat Jan 17 20:30:06 2009	(r187371)
@@ -0,0 +1,153 @@
+$FreeBSD$
+
+About sysbuild.sh
+=================
+
+I have been running -current on my laptop since before FreeBSD 2.0 was
+released and along the way developed this little trick to making the
+task easier.
+
+sysbuild.sh is a way to build a new FreeBSD system on a computer from
+a specification, while leaving the current installation intact.
+
+sysbuild.sh assume you have two partitions that can hold your rootfs
+and can be booted, and roughly speaking, all it does is build a new
+system into the one you don't use, from the one you do use.
+
+A partition named /freebsd is assumed to be part of your layout, and
+that is where the sources and ports will be found.
+
+If you know how nanobsd works, you will find a lot of similarity.
+
+HOWTO
+=====
+
+In all likelyhood, it is easier if we imagine you start with a blank
+computer.
+
+Grab a FreeBSD install ISO and boot it.
+
+Create four disk slices:
+
+	ad0s1 = 5GB
+	ad0s2 = 5GB
+	ad0s3 = 5GB
+	ad0s4 = the rest
+
+Create a root filesystem in s1a filling the entire ad0s1 slice.
+
+Create a swap partition, if you want one, in ad0s4b.
+
+Install the boot0 bootmanager.
+
+Install the "Minimal" FreeBSD system into ad0s1a.
+
+Reboot from the newly installed system.
+
+Run these commands to set up the other partitions sysbuild.sh cares about:
+
+	# /freebsd filesystem
+	newfs -b 4096 -f 512 -O2 -U /dev/ad0s3
+	echo "/dev/ad0s3 /freebsd ufs rw 2 2" >> /etc/fstab
+	mkdir /freebsd
+	mount /freebsd
+
+	# deputy rootfilesystem
+	bsdlabel -B -w /dev/ad0s2
+	newfs -O2 -U /dev/ad0s2a
+
+Next, install ports and sources:
+
+	cd /usr
+	rm -rf ports src
+	ln -s /freebsd/src
+	ln -s /freebsd/ports
+	cd /freebsd
+	mkdir ports src packages
+
+	# Or use svn if you prefer
+	csup -h cvsup.???.freebsd.org /usr/share/examples/cvsup/ports-supfile
+	csup -h cvsup.???.freebsd.org /usr/share/examples/cvsup/stable-supfile
+
+And we should be ready to try a shot:
+
+	cd /root
+	cp /usr/src/tools/tools/sysbuild/sysbuild.sh
+	sh sysbuild.sh |& tee _.sb
+
+If it succeeds, you should be able to:
+
+	boot0cfg -s 2 -v /dev/ad0
+	reboot
+
+And come up with your newly built system.
+
+	Next time you want a new system, you just run sysbuild.sh again
+	and boot slice 1 when it's done.
+
+TWEAKS
+======
+
+The sysbuild.sh script takes various parameters:
+
+	-c specfile	# configure stuff, see below.
+	-w		# skip buildworld, assume it was done earlier.
+	-k		# skip buildkernel, ---//---
+	-b		# skip both buildworld & buildkernel
+	-p		# install cached packacges if found.
+
+The specfile is a shellscript where you can override or set a number of
+shell variables and functions.
+
+A partial example:
+
+	# use a kernel different from GENERIC
+	KERNCONF=SMP
+
+	# Cache built packages, so we can use -p
+	PKG_DIR=/freebsd/packages
+
+	# Mount ports distfiles from another machine
+	REMOTEDISTFILES=fs:/rdonly/distfiles
+
+	# Fetch distfiles through a proxy
+	FTP_PROXY=http://127.0.0.1:3128/
+	HTTP_PROXY=http://127.0.0.1:3128/
+	export FTP_PROXY HTTP_PROXY
+
+	# We want these ports
+	PORTS_WE_WANT='
+		/usr/ports/archivers/unzip
+		/usr/ports/archivers/zip
+		/usr/ports/cad/linux-eagle
+		/usr/ports/comms/lrzsz
+		/usr/ports/databases/rrdtool 
+		/usr/ports/devel/subversion-freebsd
+	'
+
+	# Files to move over
+	CONFIGFILES='
+		/root/.ssh
+		/etc/X11/xorg.conf
+		/etc/ssh/ssh_host*
+		/etc/rc.conf
+		/etc/rc.local
+	'
+
+	# Shell functions to tweak things
+	# (This makes commits to /etc mostly painless)
+	final_chroot() (
+		chpass -p "\$1\$IgMjWs2L\$Nu12OCsjfiwHHj0I7TmUN1" root
+
+		pw useradd phk -u 488 -d /home/phk -c "Poul-Henning Kamp" \
+		    -G "wheel,operator,dialer" -s /bin/csh -w none
+
+		chpass -p "\$1\$VcM.9Ow8\$IcXHs0h9jsk27b8N64lOm/" phk
+
+		sed -i "" -e 's/^DS/DSorigo.freebsd.dk/' /etc/mail/sendmail.cf
+		sed -i "" -e '/console/s/^/#/' /etc/syslog.conf
+		echo "beastie_disable=YES" >> /boot/loader.conf
+		touch /root/.hushlogin
+	)
+
+

Added: head/tools/tools/sysbuild/sysbuild.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/sysbuild/sysbuild.sh	Sat Jan 17 20:30:06 2009	(r187371)
@@ -0,0 +1,528 @@
+#!/bin/sh
+#
+# Copyright (c) 1994-2009 Poul-Henning Kamp.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+set -e
+
+exec < /dev/null
+
+if [ `uname -m` = "i386" ] ; then
+	TARGET_PART=`df / | sed '
+	1d
+	s/[    ].*//
+	s,/dev/,,
+	s,s1a,s3a,
+	s,s2a,s1a,
+	s,s3a,s2a,
+	'`
+
+	# Where our build-bits are to be found
+	FREEBSD_PART=`echo $TARGET_PART | sed 's/s[12]a/s3/'`
+else
+	TARGET_PART=unknown
+	FREEBSD_PART=unknown
+fi
+
+# Relative to /freebsd
+PORTS_PATH=ports
+SRC_PATH=src
+# OBJ_PATH=obj
+
+# Name of kernel
+KERNCONF=GENERIC
+
+# srcconf
+#SRCCONF="SRCCONF=/usr/src/src.conf"
+
+# -j arg to make(1)
+
+ncpu=`sysctl -n kern.smp.cpus`
+if [ $ncpu -gt 1 ] ; then
+	JARG="-j $ncpu"
+fi
+
+# serial console ?
+SERCONS=false
+
+# Remotely mounted distfiles
+# REMOTEDISTFILES=fs:/rdonly/distfiles
+
+# Proxy
+#FTP_PROXY=http://127.0.0.1:3128/
+#HTTP_PROXY=http://127.0.0.1:3128/
+#export FTP_PROXY HTTP_PROXY
+
+PORTS_WE_WANT='
+'
+
+PORTS_OPTS="BATCH=YES MAKE_IDEA=YES A4=yes"
+
+CONFIGFILES='
+'
+
+cleanup() (
+)
+
+before_ports() (
+)
+
+before_ports_chroot() (
+)
+
+final_root() (
+)
+
+final_chroot() (
+)
+
+#######################################################################
+#######################################################################
+
+usage () {
+	(
+        echo "Usage: $0 [-b/-k/-w] [-c config_file]"
+        echo "  -b      suppress builds (both kernel and world)"
+        echo "  -k      suppress buildkernel"
+        echo "  -w      suppress buildworld"
+        echo "  -p      used cached packages"
+        echo "  -c      specify config file"
+        ) 1>&2
+        exit 2
+}
+
+#######################################################################
+#######################################################################
+
+if [ ! -f $0 ] ; then
+	echo "Must be able to access self ($0)" 1>&2
+	exit 1
+fi
+
+if grep -q 'Magic String: 0`0nQT40W%l,CX&' $0 ; then
+	true
+else
+	echo "self ($0) does not contain magic string" 1>&2
+	exit 1
+fi
+
+#######################################################################
+
+set -e
+
+log_it() (
+	set +x
+	a="$*"
+	set `cat /tmp/_sb_log`
+	TX=`date +%s`
+	echo "$1 $TX" > /tmp/_sb_log
+	DT=`expr $TX - $1 || true`
+	DL=`expr $TX - $2 || true`
+	echo -n "### `date +%H:%M:%S`"
+	printf " ### %5d ### %5d ### %s\n" $DT $DL "$a"
+)
+
+#######################################################################
+
+
+ports_recurse() (
+	set +x
+	for d
+	do
+		if [ ! -d $d ] ; then
+			echo "Missing port $d" 1>&2
+			exit 2
+		fi
+		if grep -q "^$d\$" /tmp/_.plist ; then
+			true
+		else
+			(
+			cd $d
+			ports_recurse `make -V _DEPEND_DIRS`
+			)
+			echo $d >> /tmp/_.plist
+		fi
+	done
+)
+
+ports_build() (
+	set +x
+
+	true > /tmp/_.plist
+	ports_recurse $PORTS_WE_WANT 
+
+	# Now build & install them
+	for p in `cat /tmp/_.plist`
+	do
+		t=`echo $p | sed 's,/usr/ports/,,'`
+		pn=`cd $p && make package-name`
+		if [ "x${PKG_DIR}" != "x" -a -f ${PKG_DIR}/$pn.tbz ] ; then
+			if [ "x$use_pkg" = "x-p" ] ; then
+				log_it "install $p from ${PKG_DIR}/$pn.tbz"
+				pkg_add ${PKG_DIR}/$pn.tbz
+			fi
+		fi
+		i=`pkg_info -qO $t`
+		if [ -z "$i" ] ; then
+			log_it "build $p"
+			b=`echo $p | tr / _`
+			(
+				set -x
+				cd /usr/ports
+				cd $p
+				set +e
+				make clean
+				if make install ${PORTS_OPTS} ; then
+					if [ "x${PKG_DIR}" != "x" ] ; then
+						make package ${PORTS_OPTS}
+						mv *.tbz ${PKG_DIR}
+					fi
+				else
+					log_it FAIL build $p
+				fi
+				make clean
+			) > _.$b 2>&1 < /dev/null
+			date
+		fi
+	done
+)
+
+ports_prefetch() (
+	(
+	set +x
+	ports_recurse $PORTS_WE_WANT
+
+	# Now checksump/fetch them
+	for p in `cat /tmp/_.plist`
+	do
+		b=`echo $p | tr / _`
+		(
+			cd $p
+			if make checksum $PORTS_OPTS ; then
+				true
+			else
+				make distclean
+				make checksum $PORTS_OPTS || true
+			fi
+		) > /mnt/_.prefetch.$b 2>&1
+	done
+	) 
+)
+
+#######################################################################
+
+do_world=true
+do_kernel=true
+use_pkg=""
+c_arg=""
+
+set +e
+args=`getopt bc:hkpw $*`
+if [ $? -ne 0 ] ; then
+	usage
+fi
+set -e
+
+set -- $args
+for i
+do
+	case "$i"
+	in
+	-b)
+		shift;
+		do_world=false
+		do_kernel=false
+		;;
+	-c)
+		c_arg=$2
+		if [ ! -f "$c_arg" ] ; then
+			echo "Cannot read $c_arg" 1>&2
+			usage
+		fi
+		. "$2"
+		shift
+		shift
+		;;
+	-h)
+		usage
+		;;
+	-k)
+		shift;
+		do_kernel=false
+		;;
+	-p)
+		shift;
+		use_pkg="-p"
+		;;
+	-w)
+		shift;
+		do_world=false
+		;;
+	--)
+		shift
+		break;
+		;;
+	esac
+done
+
+#######################################################################
+
+if [ "x$1" = "xchroot_script" ] ; then
+	set +x
+	set -e
+
+	shift
+
+	before_ports_chroot
+
+	ports_build
+
+	exit 0
+fi
+
+if [ "x$1" = "xfinal_chroot" ] ; then
+	final_chroot
+	exit 0
+fi
+
+if [ $# -gt 0 ] ; then
+        echo "$0: Extraneous arguments supplied"
+        usage
+fi
+
+#######################################################################
+
+T0=`date +%s`
+echo $T0 $T0 > /tmp/_sb_log
+
+log_it Unmount everything
+(
+	( cleanup )
+	umount /freebsd/distfiles || true
+	umount /mnt/freebsd/distfiles || true
+	umount /dev/${FREEBSD_PART} || true
+	umount /mnt/freebsd || true
+	umount /mnt/dev || true
+	umount /mnt || true
+	umount /dev/${TARGET_PART} || true
+) # > /dev/null 2>&1
+
+log_it Prepare running image
+mkdir -p /freebsd
+mount /dev/${FREEBSD_PART} /freebsd
+
+#######################################################################
+
+if [ ! -d /freebsd/${PORTS_PATH} ] ;  then
+	echo PORTS_PATH does not exist 1>&2
+	exit 1
+fi
+
+if [ ! -d /freebsd/${SRC_PATH} ] ;  then
+	echo SRC_PATH does not exist 1>&2
+	exit 1
+fi
+
+log_it TARGET_PART $TARGET_PART
+sleep 5
+
+rm -rf /usr/ports
+ln -s /freebsd/${PORTS_PATH} /usr/ports
+
+rm -rf /usr/src
+ln -s /freebsd/${SRC_PATH} /usr/src
+
+if $do_world ; then
+	if [ "x${OBJ_PATH}" != "x" ] ; then
+		rm -rf /usr/obj
+		mkdir -p /freebsd/${OBJ_PATH}
+		ln -s /freebsd/${OBJ_PATH} /usr/obj
+	else
+		rm -rf /usr/obj
+		mkdir -p /usr/obj
+	fi
+fi
+
+#######################################################################
+
+for i in ${PORTS_WE_WANT}
+do
+	if [ ! -d $i ]  ; then
+		echo "Port $i not found" 1>&2
+		exit 2
+	fi
+done
+
+export PORTS_WE_WANT
+export PORTS_OPTS
+
+#######################################################################
+
+log_it Prepare destination partition
+newfs -O2 -U /dev/${TARGET_PART} > /dev/null
+mount /dev/${TARGET_PART} /mnt
+mkdir -p /mnt/dev
+mount -t devfs devfs /mnt/dev
+
+if [ "x${REMOTEDISTFILES}" != "x" ] ; then
+	rm -rf /freebsd/${PORTS_PATH}/distfiles
+	ln -s /freebsd/distfiles /freebsd/${PORTS_PATH}/distfiles
+	mkdir -p /freebsd/distfiles
+	mount  ${REMOTEDISTFILES} /freebsd/distfiles
+fi
+
+log_it "Start prefetch of ports distfiles"
+ports_prefetch &
+
+if $do_world ; then
+	(
+	cd /usr/src
+	log_it "Buildworld"
+	make ${JARG} -s buildworld ${SRCCONF} > /mnt/_.bw 2>&1
+	)
+fi
+
+if $do_kernel ; then
+	(
+	cd /usr/src
+	log_it "Buildkernel"
+	make ${JARG} -s buildkernel KERNCONF=$KERNCONF > /mnt/_.bk 2>&1
+	)
+fi
+
+
+log_it Installworld
+(cd /usr/src && make ${JARG} installworld DESTDIR=/mnt ${SRCCONF} ) \
+	> /mnt/_.iw 2>&1
+
+log_it distribution
+(cd /usr/src/etc && make distribution DESTDIR=/mnt ${SRCCONF} ) \
+	> /mnt/_.dist 2>&1
+
+log_it Installkernel
+(cd /usr/src && make ${JARG} installkernel DESTDIR=/mnt KERNCONF=$KERNCONF ) \
+	> /mnt/_.ik 2>&1
+
+if [ "x${OBJ_PATH}" != "x" ] ; then
+	rmdir /mnt/usr/obj
+	ln -s /freebsd/${OBJ_PATH} /mnt/usr/obj
+fi
+
+log_it Wait for ports prefetch
+wait
+
+log_it Move filesystems
+
+if [ "x${REMOTEDISTFILES}" != "x" ] ; then
+	umount /freebsd/distfiles
+fi
+umount /dev/${FREEBSD_PART} || true
+mkdir -p /mnt/freebsd
+mount /dev/${FREEBSD_PART} /mnt/freebsd
+if [ "x${REMOTEDISTFILES}" != "x" ] ; then
+	mount  ${REMOTEDISTFILES} /mnt/freebsd/distfiles
+fi
+
+rm -rf /mnt/usr/ports || true
+ln -s /freebsd/${PORTS_PATH} /mnt/usr/ports
+
+rm -rf /mnt/usr/src || true
+ln -s /freebsd/${SRC_PATH} /mnt/usr/src
+
+log_it Build and install ports
+
+# Make sure fetching will work in the chroot
+if [ -f /etc/resolv.conf ] ; then
+	log_it copy resolv.conf
+	cp /etc/resolv.conf /mnt/etc
+	chflags schg /mnt/etc/resolv.conf
+fi
+
+if [ -f /etc/localtime ] ; then
+	log_it copy localtime
+	cp /etc/localtime /mnt/etc
+fi
+
+log_it copy ports config files
+(cd / ; find var/db/ports -print | cpio -dumpv /mnt )
+
+log_it ldconfig in chroot
+chroot /mnt sh /etc/rc.d/ldconfig start
+
+log_it before_ports
+( 
+	before_ports 
+)
+
+log_it build ports
+pwd
+cp $0 /mnt/root
+cp /tmp/_sb_log /mnt/tmp
+b=`basename $0`
+if [ "x$c_arg" != "x" ] ; then
+	cp $c_arg /mnt/root
+	chroot /mnt sh /root/$0 -c /root/`basename $c_arg` $use_pkg chroot_script 
+else
+	chroot /mnt sh /root/$0 $use_pkg chroot_script
+fi
+cp /mnt/tmp/_sb_log /tmp
+
+log_it fixing fstab
+sed "/[ 	]\/[ 	]/s;^[^ 	]*[ 	];/dev/${TARGET_PART}	;" \
+	/etc/fstab > /mnt/etc/fstab
+
+log_it create all mountpoints
+grep -v '^[ 	]*#' /mnt/etc/fstab | 
+while read a b c
+do
+	mkdir -p /mnt/$b
+done
+
+if [ "x$SERCONS" != "xfalse" ] ; then
+	log_it serial console
+	echo " -h" > /mnt/boot.config
+	sed -i "" -e /ttyd0/s/off/on/ /mnt/etc/ttys
+	sed -i "" -e /ttyu0/s/off/on/ /mnt/etc/ttys
+	sed -i "" -e '/^ttyv[0-8]/s/	on/	off/' /mnt/etc/ttys
+fi
+
+log_it move config files
+(cd / && find ${CONFIGFILES} -print | cpio -dumpv /mnt)
+
+log_it final_root
+( final_root )
+log_it final_chroot
+cp /tmp/_sb_log /mnt/tmp
+if [ "x$c_arg" != "x" ] ; then
+	chroot /mnt sh /root/$0 -c /root/`basename $c_arg` final_chroot
+else
+	chroot /mnt sh /root/$0 final_chroot
+fi
+cp /mnt/tmp/_sb_log /tmp
+log_it "Check these messages (if any):"
+grep '^Stop' /mnt/_* || true
+log_it DONE


More information about the svn-src-head mailing list