Vor einiger Zeit [1] wurde hier das Thema Groesse des Portage, insbesondere auf kleinen Platten, angeprochen. Neben Rsync_excludes [2] (evtl. recht wenig Einsparung) und einem ISO mit besonders kleiner Blockgroesse (unflexibel, da groesse vorgplant werden muss) wurde dort auch die Moeglichkeit eines komprimierten Dateisystems angesprochen. Entscheidender Nachteil dieser Loesung ist, dass alle mir bekannten komprimierenden Dateisysteme (cloop, squashfs etc.) read-only sind, ein emerge sync auf einem solchen also unmoeglich. Also heisst es sich immer ein neues .iso zu erstellen.
Motivation
Nachdem meine geliebten hardened-dev-sources im neuen Release squashfs [4] mit drin hatte, war es fuer mich an der Zeit soetwas einmal auszuprobieren. Als fauler User habe ich natuerlich erstmal ein Skript (um)geschrieben, das mir die Sache extrem vereinfacht und dieses moechte ich nun mit euch teilen
Credits
Mein Dank geht dabei an Karl Trygve Kalleberg (karltk) fuer das uespruengliche Skript, an Christian Hartmann (Ian) fuer die modifizierte Version [3] (hauptsaechlich in der fetch_snapshot() zu finden) und an www.gentoo.de fuer die Snapshots (sorry fuer die paar MB mehr heute
Disclaimer
Eins vorweg: Anregungen, Kritik, Verbesserungen und Fehler koennen gerne hier im Thread diskutiert werden oder mir per PN geschickt werden.
Installation
- Kernel mit squashfs-Unterstuetzung kompilieren und installieren
- Skript downloaden (z.B.: /root/bin/create-portage-squash)
- Datei ausfuehrbar machen (z.B.: chmod u+x /root/bin/create-portage-squash)
- Skript starten
- Datei mounten (z.B.: mount -o loop,ro,nodev,nosuid -t squashfs /root/portage.iso)
- Datei in /etc/fstab eintragen. Altes Portage natuerlich loeschen, sonst spart es nix

- ein einfaches create-portage-squash erzeugt aus dem aktuellen Portage (in $PORTDIR) ein squashfs in /root/portage.iso
- create-portage-squash -f laedt einen kompletten Portage-Snapshot (ca. 16MB) mit dem bereits erwaehnten emerge-websync-de Code [3] und wandelt diesen in ein squashfs in /root/portage.iso
- mit dem Parameter -o stellt man die Ausgabedatei um
- -e bestimmt eine Excludes-Datei, die alle in der Datei gelisteten Dateien und Verzeichnisse auschliesst. (oder default: /etc/portage/squash_excludes)
- weitere Parameter bringt der Aufruf create-portage-squash -h"
Code: Select all
#!/bin/sh
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
# Author: Karl Trygve Kalleberg <karltk 'at` gentoo 'dot` org>
# Rewritten from the old, Perl-based emerge-webrsync script
#
# Changelog:
# emerge-webrsync for hourly snapshots at http://www.gentoo.de/pub/gentoo/snapshots/
# Christian Hartmann <ian 'at` gentoo 'dot` org>
#
# create-portage-squash-0.1 (21 Oct 2004) for creating a squashfs portage based
# on PORTDIR or the latest hourly snapshot from gentoo.de
# sirro <sirro 'at` nurfuerspam 'dot`de>
init_variables() {
SYNCPATH="/var/tmp/emerge-webrsync"
GENTOO_MIRRORS="http://www.gentoo.de/pub/gentoo"
PORTDIR="$(/usr/lib/portage/bin/portageq portdir)"
#some create-portage-squash specific settings
if [ -r "/etc/portage/squash_excludes" ]; then
SQUASH_EXCLUDEFROM="/etc/portage/squash_excludes"
else
SQUASH_EXCLUDEFROM="/dev/null"
fi
PORTAGE_ISO="/root/portage.iso"
REMOVE_SNAPSHOT=true
VERBOSE="size"
if ! which mksquashfs &>/dev/null; then
echo " !!! mksquashfs not found, please install sys-fs/squashfs-tools"
exit 1
fi
}
fetch_snapshot() {
local attempts=0
local wgetops=
if [ ! -d ${SYNCPATH} ]; then mkdir -p ${SYNCPATH}; fi
cd ${SYNCPATH}
echo " *** Fetching most recent snapshot"
while (( ${attempts} < 40 )) ; do
day=`date -d "-${attempts} day" +"%d"`
month=`date -d "-${attempts} day" +"%m"`
year=`date -d "-${attempts} day" +"%Y"`
attemptsHour=0
while (( ${attemptsHour} < 24 )) ; do
hour=`date -d "-${attemptsHour} hour" +"%H"`
SNAPSHOT_FILE="portage-${year}${month}${day}-${hour}.tar.bz2"
echo "Trying ${SNAPSHOT_FILE}"
if [ -s ${SNAPSHOT_FILE} ]; then
return 0
fi
for i in ${GENTOO_MIRRORS} ; do
url="${i}/snapshots/${SNAPSHOT_FILE}"
if (wget ${wgetops} ${url}) \
&& [ -s ${SNAPSHOT_FILE} ] ; then
echo " *** The snapshot-date (YYMMDD-HH): ${year}${month}${day}-${hour}"
cd - &>/dev/null
return 0
fi
done
attemptsHour=$[attemptsHour+1]
done
attempts=$[attempts+1]
done
cd - &>/dev/null
return 1
}
unpack_snapshot() {
cd ${SYNCPATH}
echo " *** Extracting compressed portage... (This may take a while)"
tar --exclude-from ${SQUASH_EXCLUDEFROM} -xjf ${SNAPSHOT_FILE}
if ${REMOVE_SNAPSHOT}; then
rm -f ${SNAPSHOT_FILE};
else
echo " *** ${REMOVE_SNAPSHOT} is still in ${SYNCPATH}"
fi
# Make sure user and group file ownership is root
chown -R root:root portage
cd - &>/dev/null
}
cleanup() {
echo " *** Cleaning up..."
if [ -d "${SYNCPATH}/portage" ]; then rm -rf "${SYNCPATH}/portage"; fi
if [ -f "${SYNCPATH}/${SNAPSHOT_FILE}" ] && ${REMOVE_SNAPSHOT}; then
rm -f "${SYNCPATH}/${SNAPSHOT_FILE}";
fi
}
diplay_help() {
local SCRIPT_NAME=$(basename ${0})
echo "SYNTAX: ${SCRIPT_NAME} [options]"
echo "Options are:"
echo -e "\t-e file\t exclude files listed in \"file\" (* wildcard allowed)"
echo -e "\t-f\t fetch and use snapshot from gentoo.de for the squashfs"
echo -e "\t-h\t display this help"
echo -e "\t-k\t keep snapshots in tempdir"
echo -e "\t-o file\t use \"file\" as outputfile (defaults to ${PORTAGE_ISO})"
echo -e "\t-t dir\t use \"dir\" as tempdir (defaults to ${SYNCPATH})"
echo -e "\t-v\t be verbose"
echo
echo "This script generates a squashfs-portage either from your PORTDIR or from"
echo "a recent snapshot file downloaded from gentoo.de (see options above)."
echo
echo "Config files:"
echo -e "/etc/portage/squash_excludes\tfiles/dirs listed in this file will be"
echo -e "\t\t\t\texluded from squashfs (see also: option -e)"
}
######### main starts here #########
#catch some signals
trap 'cleanup; exit 1' TERM INT
init_variables
while getopts hko:e:t:fv opt; do
case $opt in
#fetch
f) if fetch_snapshot; then
unpack_snapshot
PORTDIR="${SYNCPATH}/portage"
else
echo " !!! Failed fetching a recent snapshot"
cleanup
exit 1
fi ;;
#help
h) diplay_help
exit 0 ;;
#keep snapshots
k) REMOVE_SNAPSHOT=false;;
#output-file
o) PORTAGE_ISO="${OPTARG}" ;;
#exclude-file
e) if [ -r "${OPTARG}" ]; then
SQUASH_EXCLUDEFROM="${OPTARG}";
else
echo " !!! Could not read ${OPTARG}"
exit 1
fi ;;
#temp-file
t) SYNCPATH="${OPTARG}" ;;
#verbose
v) VERBOSE="^" ;;
esac
done
if [ ! -d ${SYNCPATH} ]; then mkdir -p ${SYNCPATH}; fi
#the local rsync is a workaround to get the squashexcludes working.
#mksquashfs seems to ignore files from my scrip without any obvious reason :(
#on commandline it is working fine...
if [ ! -d "${SYNCPATH}/portage" ]; then
echo " *** Creating a temp copy of your portage (without the specified excludes)"
mkdir -p "${SYNCPATH}/portage"
rsync -a --exclude-from=${SQUASH_EXCLUDEFROM} --exclude='distfiles' \
--exclude='packages' ${PORTDIR%%/} "${SYNCPATH}"
fi
echo " *** Building squashed portage file system to ${PORTAGE_ISO}"
if ! mksquashfs ${SYNCPATH}/portage/* ${PORTAGE_ISO} -noappend \
| grep ${VERBOSE}; then
if [ -f ${PORTAGE_ISO} ]; then rm -f ${PORTAGE_ISO}; fi
echo " !!! Failed to build squashed portage file"
fi
cleanup
exit 0Bei einem kompletten Portage ist mir eine Einsparung von ca. 95% auf 20MB moeglich. Mit den excludes bekomme ich es fuer meinen Laptop sogar auf 11MB.
Natuerlich ist das ganze nur da sinnvoll wo Plattenplatz knapp ist, da die Dekomprimiererei natuerlich zu Lasten der Performance geht...
Quellen
[1] http://forums.gentoo.org/viewtopic.php?t=225745
[2] http://forums.gentoo.org/viewtopic.php?t=173433
[3] http://forums.gentoo.org/viewtopic.php?p=969443#969443
[4] http://squashfs.sourceforge.net
Changelog
2006/01/14: Das Skript in den Text gepackt.

