View previous topic :: View next topic |
Author |
Message |
sirro Veteran
Joined: 20 Jul 2003 Posts: 1472 Location: aachen.nrw.de.eu
|
Posted: Thu Oct 21, 2004 4:50 pm Post subject: Portage in 20MB (create-portage-squash) |
|
|
Einleitung
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
Bedienung
- 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"
Skript
Code: | #!/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 0 |
Ergebnis
Bei 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] https://forums.gentoo.org/viewtopic.php?t=225745
[2] https://forums.gentoo.org/viewtopic.php?t=173433
[3] https://forums.gentoo.org/viewtopic.php?p=969443#969443
[4] http://squashfs.sourceforge.net
Changelog
2006/01/14: Das Skript in den Text gepackt.
Last edited by sirro on Sat Jan 14, 2006 12:27 pm; edited 1 time in total |
|
Back to top |
|
|
lolli78 Apprentice
Joined: 14 Jan 2004 Posts: 162 Location: Europe
|
Posted: Thu Oct 21, 2004 5:20 pm Post subject: |
|
|
hallo sirro,
danke dafür. ich hab mir sowas auch mal überlegt, aber ich wusste nicht, how to... demnächst muss ich mal squashfs installieren.
hast du zufällig auch so eine lösung für /var/db/pkg? bei mir liegen da 74mb drin, die sich sicher auch gut komprimieren lassen.
danke,
lorenz _________________ frag' doch deinadmin.de |
|
Back to top |
|
|
sirro Veteran
Joined: 20 Jul 2003 Posts: 1472 Location: aachen.nrw.de.eu
|
Posted: Thu Oct 21, 2004 5:23 pm Post subject: |
|
|
lolli78 wrote: | hast du zufällig auch so eine lösung für /var/db/pkg? bei mir liegen da 74mb drin, die sich sicher auch gut komprimieren lassen. |
Da /var/db ja recht dynamisch bleiben muss, ist squashfs keine geeignete Loesung. Es sein dann man will auf jegliches Installieren verzichten
Die IMO beste Moeglichkeit ist IMO ein ext2 .iso mit ganz kleiner Blockgroesse zu erzeugen und das zu mounten. So grosse Einsparungen wie mit squashfs sind damit natuerlich nicht moeglich, aber bei vielen kleinen Dateien sind auch schonmal 50% drin und man bleibt recht flexibel. (siehe auch [1])
[1] https://forums.gentoo.org/viewtopic.php?p=1567001#1567001 |
|
Back to top |
|
|
c07 Veteran
Joined: 25 Oct 2002 Posts: 1091
|
Posted: Tue Dec 14, 2004 7:33 am Post subject: |
|
|
sirro wrote: | Die IMO beste Moeglichkeit ist IMO ein ext2 .iso mit ganz kleiner Blockgroesse zu erzeugen und das zu mounten. |
Allerdings kann ext2 keine kleinen Blockgrößen (Minimum ist 1024) und braucht für 1 Byte (was hier sehr häufig ist) mindestens 1152 Bytes (inkl. Inode).
Ich hab es aber mal mit ein paar Dateisystemen ausprobiert. Zunächst die Daten (Ausgaben gekürzt):
Code: | ~ # dd if=/dev/zero of=/tmp/pkg bs=64M count=1
~ # losetup /dev/loop0 /tmp/pkg
~ # du -sk /var/db/pkg
32972 /var/db/pkg
~ # mkfs.ext2 -b4096 -m0 -i6144 /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 64152 62056 2096 97% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -f /dev/loop0
/dev/loop0: 10277/10944 files (0.0% non-contiguous), 15860/16384 blocks
~ # mkfs.ext2 -b1024 -m0 -i6144 /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 64141 32983 31158 52% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -f /dev/loop0
/dev/loop0: 10277/10944 files (0.1% non-contiguous), 34378/65536 blocks
~ # mkfs.minix -i10944 -v /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
(35 Dateien und 1 Ordner (gut 57 KB) wegen zu langem Namen gescheitert)
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 64840 33123 31717 52% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -fv /dev/loop0
10231 inodes used (93%)
33819 zones used (51%)
~ # mkfs.vfat -F32 -s1 -f1 -r160 -v /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 65012 27976 37037 44% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck /dev/loop0
/dev/loop0: 10266 files, 55951/130024 clusters
~ # mkfs.reiserfs -qb1024 -s513 /dev/loop0
~ # mount -treiserfs /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 65527 25875 39652 40% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck.reiserfs /dev/loop0
Leaves 2048
Internal nodes 54
Directories 427
Other files 9840
Data block pointers 23196 (0 of them are zero)
Safe links 0 |
Inodes hab ich äußerst knapp vergeben, dafür bei FAT auch nur 1 FAT. Bei ext2 spart eine Blockgröße von 1024 Bytes gegenüber den geläufigen 4096 fast die Hälfte. Allerdings muss man bei einem Loop-Device natürlich etwas Reserve einrechnen.
Bei Minix ist die maximale Länge der Dateinamen ein Problem. Die alte Version ist noch ein bisschen sparsamer, aber bei 64 MB am Limit. Ähnlich wär bei FAT bis 32 MB noch FAT16 mit 512-Byte-Clustern möglich, was auch etwas sparsamer ist. Reiser (3.6) ist von den getesteten Systemen am sparsamsten. Womöglich würden 512-Byte-Blocks noch was bringen, aber die funktionieren nicht.
Beim Kopieren in das frische Loop-Dateisystem ist der Geschwindigkeitsverlust gegenüber normalem Kopieren nicht groß, wobei Reiser deutlich langsamer als die Anderen ist und dabei auch noch mehr CPU braucht. 1024er-ext2 ist spürbar schneller, aber das könnte auch dran liegen, dass 1024 meine echte Blockgröße ist.
JFS und XFS hab ich nicht im Kernel, aber für diesen Zweck könnten sie durchaus interessant sein, weil sie sehr kleine Dateien direkt im Inode speichern können. Der ist bei JFS allerdings schon 512 Bytes groß, bei XFS einstellbar ab 256 Bytes.
Eigentlich bräuchte man aber ein spezialisiertes Dateisystem, das auch seine Größe dynamisch ändern kann, was aber wahrscheinlich gar nicht über ein normales Loop-Device möglich ist. |
|
Back to top |
|
|
moe Veteran
Joined: 28 Mar 2003 Posts: 1289 Location: Potsdam / Germany
|
Posted: Tue Dec 14, 2004 9:31 am Post subject: |
|
|
Habs mal mit xfs probiert, wusste allerdings nicht mit den ganzen Optionen etwas anzufangen:
Code: |
# du -sk /var/db/pkg
137884 /var/db/pkg
# dd if=/dev/zero of=vardbpkg bs=150M count=1
# mkfs.xfs -b size=512 vardbpkg
# cp -a /var/db/pkg/* /mnt/floppy
# df
/root/vardbpkg 151128 69331 81797 46% /mnt/floppy
|
aber das mit dem Squashfs ist wirklich nicht schlecht, und readonly ist zwar etwas umständlicher beim syncen, dafür aber zusätzliche Sicherheit im laufenden Betrieb..
Gruss Maurice |
|
Back to top |
|
|
c07 Veteran
Joined: 25 Oct 2002 Posts: 1091
|
Posted: Tue Dec 14, 2004 5:13 pm Post subject: |
|
|
Ich hab es jetzt auch noch mal mit JFS und XFS probiert. Die Werte sind zu den obigen vergleichbar, weil ich /var/db/pck gesichert hab, vor ich jfsutils und xfsprogs emergt hab.
JFS war für diesen Zweck ein Griff ins Klo. Lässt sich freiwillig nur mit 4KB-Blöcken formatieren und passt dann nicht mehr in die 64 MB (braucht ungefähr 70 MB). Zwar ist mkfs.jfs auf die Blockgrößeneinstellung vorbereitet (2-Zeilen-Patch), aber mit 512 Bytes lässt es sich nicht mehr mounten. Da ist scheinbar der Support im Kernel noch nicht vorhanden.
Bei XFS kann man an sehr vielen Stellen schrauben, wobei die Auswirkungen enorm sind. Ich hab eigentlich nur alle Blockgrößen auf das Minimum gedreht:
Code: | ~ # mkfs.xfs -fbsize=512 -isize=256 -lsize=927b -nsize=512 /dev/loop0
meta-data=/dev/loop0 isize=256 agcount=4, agsize=32768 blks
= sectsz=512
data = bsize=512 blocks=131072, imaxpct=25
= sunit=0 swidth=0 blks, unwritten=1
naming =version 2 bsize=512
log =internal log bsize=512 blocks=927, version=1
= sectsz=512 sunit=0 blks
realtime =none extsz=65536 blocks=0, rtextents=0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg-old/* /mnt/tmp
~ # df /mnt/tmp
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 65073 30662 34411 48% /mnt/tmp |
Das ist auch ziemlich platzsparend, aber die Performance lässt sehr zu wünschen übrig (braucht für das Kopieren ungefähr dreimal so lang wie 1024er-ext2 und doppelt so lang wie Reiser). Wobei natürlich die Performance im laufenden Betrieb ganz anders ausschaun könnte. Theoretisch kann man noch das Journal mit "norecovery" abschalten, aber praktisch lehnt das mount ab. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|