Binärupdates von Paketen

Kamikaze

Warrior of Sunlight
Teammitglied
Der ein- oder andere hat vielleicht bemerkt, dass ich in letzter Zeit nicht besonders aktiv hier war. Dafür gibt es einen Grund, der heißt pkg_upgrade und es handelt sich dabei um ein Shell-Skript (im Moment 42kb aka 1527 Zeilen groß), das dafür Gedacht ist Pakete ausschließlich binär zu aktualisieren.

Mit pkg_upgrade gehe ich Dinge an, die mich bei Binärupdates mit portupgrade -PP immer gestört haben. Nämlich erstens, dass man eine Kopie des kompletten Ports-Tree benötigt und zweitens die Abhängigkeit zu Perl.

Bei pkg_upgrade kommen alle Informationen aus einer lokalen Kopie des Index auf dem FTP-Server. Der Index wird mit UMA (Update MAnanger), eine Koproduktion mit soul_rebel, aktuell gehalten. Über netcat wird eine FTP-Verbindung mit dem Server aufgebaut und Alter und Größe der Datei mit der lokalen Kopie verglichen um unnötige Downloads zu vermeiden.

Im Moment laufen die ersten Tests des Skriptes, von dem die für 1.0 geplanten Features bis auf die Konflikt-Handhabung inzwischen vollständig implementiert sind. Beim Testen unterstützt mich ein Schweizer Webhoster, der FreeBSD einsetzt.

Für den Zukünftigen Ausbau sind eine Integration von pkg_libchk Tests, Roll-Back-Möglichkeiten und das wiederaufnehmen abgebrochener Updates geplant.

Jedenfalls bin ich guter Dinge Version 1.0 mit dem Ende des Ports-Freeze liefern zu können. Die Manual-Pages sind leider
noch nicht geschrieben, es gilt mindestens 14 Programmparameter, 11 Environment-Variablen, 10 Exit-Codes und die Interpretation der angegebenen Pakete zu dokumentieren, wobei 4 grundsätzliche Formen von Paketangaben unterschieden werden.:ugly:
 
Woohoo! Sehr schoenes Ding. Ich freue mich schon auf das Endprodukt! Danke fuer die Muehen. :-)
 
Apropos UMA, da es bei dir immer noch nicht läuft (im Gegensatz zu den Systemen eines anderen Testers), hier ist das Skript für alle die beim Fehler finden behilflich sein wollen:

Code:
#!/bin/sh -f
#
# Copyright (c) 2009
# Dominic Fandrey <kamikaze@bsdforen.de>
#
# 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.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
#

readonly version=0.9999
readonly name=uma

# Return value.
errno=0
# Allow things to fail properly by ignoring SIGINT in the main process.
trap '' int

# Used to activate debugging output.
debug=
stderr="/dev/null"
verbose=
# Will be set if files are locally available.
local=

vardir="/var"
lock="$vardir/run/$name.lock"
lockpid="$vardir/run/$name.pid"
identpid="$vardir/run/$name.ident.pid"

# Use line breaks as a delimiter.
IFS='
'
# Timezone UTC for age comparisons.
export TZ=UTC

# The bit position of errors.
readonly ERR_LOCK=0
readonly ERR_FETCH_PORTS=1
readonly ERR_FETCH_VULNDB=2
readonly ERR_FETCH_INDEX=3
readonly ERR_EXTRACT_PORTS=4
readonly ERR_UPDATE_PORTS=5

#
# Get environment variables.
#

# Local index location.
: ${PKG_INDEX="$vardir/db/uma/FTPINDEX"}
# Directory for remporary files.
: ${TMPDIR="/tmp"}

# Logic from src/usr.sbin/pkg_install/add/main.c, plus the possibility to
# override the architecture with ARCH.
: ${PACKAGEROOT="ftp://ftp.freebsd.org"}
: ${ARCH="$(uname -m)"}
branch="$(uname -r | tr '[:upper:]' '[:lower:]')"
number="${branch%%.*}"
case "$branch" in
	release)
		branch=$number-$branch
	;;
	stable | current)
		branch=${number%%.*}-$branch
	;;
	*)
		# Fallback to stable for prerelease and the like.
		branch=${number%%.*}-stable
	;;
esac
: ${PACKAGESITE="$PACKAGEROOT/pub/FreeBSD/ports/$ARCH/packages-$branch/Latest"}
packagetree="${PACKAGESITE%/*?}"
ftp="${PACKAGESITE#*://}"
ftp="${ftp%%/*}"

# Determine portsdir
portsdir=$(make -V PORTSDIR -f /usr/share/mk/bsd.port.mk)

#
# Checks weather the local index needs updating.
#
# @param PACKAGESITE
#	The source of a new index.
# @param vebose
#	If set verbose output will be created.
# @param packagetree
#	The remote directory to get the index from.
# @param PKG_INDEX
#	The local copy of the remote index.
# @return
#	Return 0 if the index needs updating, 1 if not.
#
updateRequired() {
	case "$PACKAGESITE" in
		ftp://*)
			updateRequiredFtp
			return $?
		;;
		*://*)
			errno="$((1 << $ERR_FETCH_INDEX | $errno))"
			if [ -n "$verbose" ]; then
				echo "Unsopported protocol: ${PACKAGESITE%%://*}!"
			fi
			return 1
		;;
		*)
			if [ "$(sha256 -q "$packagetree/INDEX")" \
				=  "$(sha256 -q "$PKG_INDEX")" ]; then
				if [ -n "$verbose" ]; then
					echo "Local and remote index are identical."
				fi
				return 1
			else
				if [ -n "$verbose" ]; then
					echo "Local and remote index differ."
				fi
				return 0
			fi
		;;
	esac
}

#
# This connects to an ftp and compares file age and size to the local INDEX
# file. Load balancing is a problem here, because you might get forwareded
# to an outdated server. Or you might catch an up to date server and later
# download from an outdated one.
#
# @param PKG_INDEX
#	The local copy of the remote index.
# @param packagetree
#	A derivate of PACKAGESITE.
# @param ftp
#	The hostname component of PACKAGESITE.
# @param debug
#	If this is set a lot of debugging output will occur. Including the
#	answers of the ftp server.
# @return
#	0 is returned if an update seems necessary, 1 if not.
#
updateRequiredFtp() {
	local line pid timeout connected time size

	test -e "$PKG_INDEX" || return 0

	#
	# Connect to an ftp server. This starts 3 processes, one that
	# pipes commands into netcat (nc), the netcat proccess and
	# one that reads the answers.
	# The reading process notifies the sending process of the current
	# progress by creating temporary files.
	# The reading process echos "time=..." and "size=..." commands
	# that get evaluated and can be used from outside.
	#
	# Read RFC959 to get a hang on the FTP protocol.
	#
	pid="$$"
	timeout=600
	eval "$(
		while [ $timeout -gt 0 ]; do
			if [ -e "$TMPDIR/$pid.done" ]; then
				rm "$TMPDIR/$pid.done"
				echo "QUIT"
				break
			elif [ -e "$TMPDIR/$pid.connected" ]; then
				rm "$TMPDIR/$pid.connected"
				echo "USER anonymous"
				echo "PASS anonymous@example.com"
				echo "TYPE I"
				echo "MDTM /${packagetree#*://*/}/INDEX"
				echo "SIZE /${packagetree#*://*/}/INDEX"
			fi
			sleep 0.1
			timeout=$(($timeout - 1))
		done \
		| (
			nc -w $(($timeout / 10)) "$ftp" 21 2> /dev/null \
			|| touch "$TMPDIR/$pid.done"
		) | while read line; do
			test -n "$debug" && echo "$line" 1>&2
			case "$line" in
			5*)
				# An error occured, bail out.
				touch "$TMPDIR/$pid.done"
			;;
			220*)
				test -z "$connected" \
					&& touch "$TMPDIR/$pid.connected"
				connected=1
			;;
			213*)
				if [ -z "$time" ]; then
					time=1
					line="$(
						echo "${line##* }" \
						| sed 's|[^0-9]||g'
					)"
					line="${line%??}.${line#????????????}"
					echo "time=$line"
				elif [ -z "$size" ]; then
					size=1
					echo "size=${line##* }"
				fi

				if [ -n "$time" -a -n "$size" ]; then
					touch "$TMPDIR/$pid.done"
				fi
			;;
			esac
		done
	)"

	# An ftp connection did apparently not occur. Or something went
	# wrong. Hence we assume that an update is necessary.
	test -z "$size" -o -z "$time" && return 0

	# Create a dummy file for the time comparison.
	touch -t "$time" "$TMPDIR/$pid.compare"

	if [ "$TMPDIR/$pid.compare" -nt "$PKG_INDEX" ]; then
		rm "$TMPDIR/$pid.compare"
		if [ -n "$verbose" ]; then
			echo "Local index is older than remote."
		fi
		return 0
	fi
	if [ "$TMPDIR/$pid.compare" -ot "$PKG_INDEX" ]; then
		rm "$TMPDIR/$pid.compare"
		if [ -n "$verbose" ]; then
			echo "Local index is newer than remote."
		fi
		return 1
	fi
	# Files have the same age.
	if [ -n "$verbose" ]; then
		echo "Local and remote index have the same creation time."
	fi
	rm "$TMPDIR/$pid.compare" 2> /dev/null

	# Compare the size.
	localSize="$(wc -c "$PKG_INDEX")"
	localSize="$((${localSize% *}))"
	if [ "$size" -eq "$localSize" ]; then
		# Files have the same size, no update required.
		if [ -n "$verbose" ]; then
			echo "Local and remote index have the same size."
		fi
		return 1
	else
		# Files differ in size. Update required.
		if [ -n "$verbose" ]; then
			echo "Local and remote index differ in size."
		fi
		return 0
	fi
}

#
# This function is called by a trap when the script exits in verbose mode.
# It reads errno to construct error messages.
#
# @param errno
#	The exit status of the script.
#
verbose() {
	if [ $(($errno >> $ERR_LOCK & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_LOCK))): Lock owned by someone else."
	fi
	if [ $(($errno >> $ERR_FETCH_PORTS & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_FETCH_PORTS))): Fetching the ports tree failed."
	fi
	if [ $(($errno >> $ERR_FETCH_VULNDB & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_FETCH_VULNDB))): Fetching security database failed."
	fi
	if [ $(($errno >> $ERR_FETCH_INDEX & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_FETCH_INDEX))): Fetching remote INDEX failed."
	fi
	if [ $(($errno >> $ERR_EXTRACT_PORTS & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_EXTRACT_PORTS))): Extracting the ports tree failed."
	fi
	if [ $(($errno >> $ERR_UPDATE_PORTS & 1)) -eq 1 ]; then
		echo "ERROR($((1 << $ERR_UPDATE_PORTS))): Updating the ports tree failed."
	fi
}

#
# This function spawns a process that takes over a lock.
#
# @param pid
#	The PID of the process that requested the lock.
# @param lock
#	The location of the lock file.
# @param lockpid
#	The location of the PID file for the lock holding process.
#
secureLock() {
	lockf "$lock" sh -c "
		trap 'exit 0' term
		echo '$pid' > '$lock'
		echo \"\$\$\" > '$lockpid'
		trap 'rm \"$lockpid\"; exit 0' EXIT
		while kill -0 '$pid' 2> /dev/null; do
			sleep 2
		done
	" 2> /dev/null &
}

#
# Checks weather the currently requesting process holds the lock.
#
# @param pid
#	The PID of the process that requested the lock.
# @param lock
#	The location of the lock file.
# @return
#	Returns 0 if the lock is held for the requesting process or 1
#	if the lock is missing or owned by another process.
#
hasLock() {
	test -e "$lock" && test "$pid" -eq "$(cat "$lock")"
	return $?
}

#
# Creates a lock for the requesting process.
# 
# @param pid
#	The PID of the process that requested the lock.
# @param lock
#	The location of the lock file.
# @param lockpid
#	The location of the PID file for the lock holding process.
# @param portsdir
#	The location of the FreeBSD ports tree.
# @return
#	Returns 0 on success, 1 on failure.
#
lock() {
	# The requestor already holds the lock.
	hasLock && return 0

	# The process requesting the lock does not exist.
	kill -0 "$pid" 2> /dev/null || return 1 $(errno=1)

	# Follow symlinks
	if cd "$portsdir" && portsdir="$(pwd -P)"; then
		# Portsdir exists, so we can test for make activity. This
		# does not cover all cases, but it covers a lot.
		if fstat "$portsdir" | awk '{print $2}' | grep -q make; then
			errno=1
			return 1
		fi
	fi

	# Try aquiring the lock.
	lockf -st 0 "$lock" $0 secure $pid 2> /dev/null || return 1 $(errno=1)
	# Wait until the locking process is properly set up.
	while ! [ -e "$lockpid" -a -e "$lock" ]; do
		sleep 0.1
	done
	return 0
}

#
# Frees a lock unless it is held for another process than the requestor.
# 
# @param lock
#	The location of the lock file.
# @param lockpid
#	The location of the PID file for the lock holding process.
# @return
#	Returns 0 on success, 1 on failure.
#
unlock() {
	if hasLock; then
		# Free the lock.
		kill -TERM "$(cat "$lockpid")"
		# Wait for the locking process to clean up.
		while [ -e "$lockpid" -o -e "$lock" ]; do
			sleep 0.1
		done
		return 0
	else
		errno=1
		return 1
	fi
}

#
# Prints the command and available parameters.
#
# @param name
#	The name of the script.
# @param version
#	The version of the script.
#
printHelp() {
	echo "$name v$version
usage:  $name [-h] [-d] [-v] [fetch] [extract] [update] [ports] [audit] [index]"
}

#
# Reads the parameters and creates variables that indicates the presence
# of these parameters.
#
# The last numeric value is treated as the requestor PID. It also deals
#
# @param *
#	All parameters to process.
# @param debug
#	This is set to 1 if debugging is activated.
# @param stderr
#	This is changed from /dev/null to /dev/stderr if debugging is activated.
# @param verbose
#	Set to 1 if verbose mode is activated.
# @param cmd_*
#	Set by this function to indicate the presence of a parameter.
#
readParams() {
	local flag
	for flag; {
		# A numerical parameter is the PID.
		if [ "$flag" -eq  "$flag" ] 2> /dev/null; then
			pid="${flag}"
			continue
		fi
	
		# Activate verbose mode for -v.
		case "$flag" in
			-d | --debug)
				debug=1
				stderr="/dev/stderr"
				continue
			;;
			-v | --verbose)
				trap 'verbose 1>&2' EXIT
				verbose=1
				continue
			;;
			-h | --help)
				printHelp
				continue
			;;
			-? | --*)
				continue
			;;
			-*)
				# Split parameters.
				readParams "${flag%${flag#-?}}" "-${flag#-?}"
				continue
			;;
		esac
	
		eval "cmd_${flag}=1"
	}
}

pid="$$"
cmd_lock=
cmd_unlock=
cmd_secure=
cmd_env=
cmd_fetch=
cmd_extract=
cmd_update=
cmd_ports=
cmd_audit=
cmd_index=
readParams "$@"

#
# Exclusive commands that will cause all others to be ignored, in order
# of priority.
#

if [ -n "$cmd_unlock" ]; then
	unlock
	return $?
fi

if [ -n "$cmd_secure" ]; then
	secureLock
	return $?
fi

if [ -n "$cmd_lock" ]; then
	lock
	return $?
fi

#
# Non-exclusive commands that do not require a lock.
#

if [ -n "$cmd_env" ]; then
	echo "ARCH='$ARCH'"
	echo "PACKAGEROOT='$PACKAGEROOT'"
	echo "PACKAGESITE='$PACKAGESITE'"
	echo "TMPDIR='$TMPDIR'"
	echo "PKG_INDEX='$PKG_INDEX'"
fi

# Create a local lock if need be.
localLock=
if ! hasLock; then
	localLock=1
	lock || return $?
fi

# Ports tree commands.
if [ -n "$cmd_ports" ]; then
	if [ -n "$cmd_fetch" ]; then
		portsnap fetch || errno="$((1 << $ERR_FETCH_PORTS | $errno))"
	fi
	if [ -n "$cmd_extract" ]; then
		portsnap extract || errno=$((1 << $ERR_EXTRACT_PORTS | $errno))
	fi
	if [ -n "$cmd_update" ]; then
		portsnap update || errno=$((1 << $ERR_UPDATE_PORTS | $errno))
	fi
fi

# Portaudit commands.
if [ -n "$cmd_audit" ]; then
	if [ -n "$cmd_fetch" ]; then
		portaudit -F || errno=$((1 << $ERR_FETCH_VULNDB | $errno))
	fi
fi

# Package index commands.
if [ -n "$cmd_index" ]; then
	if ! mkdir -p "${PKG_INDEX%/*}" 2> /dev/null; then
		test -n "$verbose" \
			&& echo "The directory ${PKG_INDEX%/*} does not exist and cannot be created!"
		errno=$((1 << $ERR_FETCH_INDEX | $errno))
	elif [ -n "$cmd_fetch" ]; then
		if updateRequired; then
			test -n "$verbose" \
			&& echo "Fetching index from: $packagetree"
			fetch -o "$TMPDIR/FTPINDEX.$$" "$packagetree/INDEX" \
			2>&1 \
			&& mv "$TMPDIR/FTPINDEX.$$" "$PKG_INDEX" \
			|| rm "$TMPDIR/FTPINDEX.$$" \
				$(errno=$((1 << $ERR_FETCH_INDEX | $errno))) \
			2> /dev/null
		fi
	fi
fi


# Free a local lock.
test -n "$localLock" && unlock

return $errno

Alle Anweisungen hier sind für den root-User gedacht:

Ein guter Anfang wäre es das Skript in ~/bin unter dem Namen uma anzulegen.

Dann sollten zwei Terminals geöffnet werden. Dort sollte folgendes durchgeführt werden.

Code:
1# uma -vd lock $$
2# uma -vd lock $$ (sollte mit einem Fehler quittiert werden)
1# uma -vd unlock $$
2# uma -vd lock $$
2# uma -vd lock $$
1# uma -vd unlock $$ (sollte mit einem Fehler quittiert werden)
2# uma -vd unlock $$
2# uma -vd unlock $$ (sollte mit einem Fehler quittiert werden)

Die Fehlermeldungen von UMA sind nicht besonders hilfreich, UMA ist dafür gedacht von anderen Programmen aufgerufen zu werden und kommuniziert über den Return code. Wobei der als Bitmaske betrachtet wird, es können also mehrere Fehler parallel kommuniziert werden (was die Unterscheidung leider auf 8 unterschiedliche Fehler begrenzt).

Wer Lust hat, kann auch die anderen Funktionen Testen. Ich schätze fetch index ist ganz interessant, vor allem in Kombination mit -vd.
 
Ich habe dir ja gerade geschrieben, dass es bei mir läuft. Bei deinem Test sollte aber jeweils die zweite Lock-Anweisung aber kein $$ haben, oder? Mit $$ gibt es keinen Fehler, denn die pid ist ja gleich.
 
Die Ziffer vor dem # soll eigentlich das Terminal bezeichnen in dem die Aufrufe ausprobiert werden sollen. Zwischen 1 und 2 unterscheidet sich die PID dann natürlich.

Übrigens ist pkg_upgrade jetzt (hinsichtlich 1.0) feature complete (1818 Zeilen, 51kB) und bei mir läuft der erste große Test (ein pkg_upgrade -a auf einer Maschine, die lange nicht mehr aktualisiert wurde). Im Moment macht das Skript nur Downloads, aber wenn die fertig sind kommt die Stunde der Wahrheit. Entweder alles klappt wie geplant oder das System wird vom Konflikt-Handling geschreddert (alles Andere wurde schon getestet).
 
Zuletzt bearbeitet:
So, ich habe jetzt mit dem eigentlichen Update-Versuch begonnen. Zwei kleine Probleme habe ich noch Gefunden und behoben.

Ein paar Probleme sind wohl zu erwarten da die Ports nicht immer korrekte Konflikt-Informationen haben. Da kann ich aber von meiner Seite aus nichts dran ändern.

-- update --
Noch ein kleines Problem gefunden und gefixt, 167 von 402 Updates durchgeführt.

-- update --
Inzwischen habe ich noch einen Fehler beim -o Parameter (Pakete ersetzen) gefixt. Leider kann ich das große Update nicht mehr weiterlaufen lassen. Der INDEX wurde zwischenzeitlich aktualisiert und Listet Pakete die nicht vorhanden sind. Damit scheitert natürlich der Download. Das Update wird jedoch erst durchgeführt, wenn alle benötigten Pakete vorhanden sind, damit also im Moment gar nicht. :(

Ich betrachte das als Bug in Tinderbox, soul_rebel hat auch einen entsprechenden PR eingereicht, der leider bislang ignoriert wurde.
 
Zuletzt bearbeitet:
So, ich habe jetzt mit dem eigentlichen Update-Versuch begonnen. Zwei kleine Probleme habe ich noch Gefunden und behoben.

Ein paar Probleme sind wohl zu erwarten da die Ports nicht immer korrekte Konflikt-Informationen haben. Da kann ich aber von meiner Seite aus nichts dran ändern.

-- update --
Noch ein kleines Problem gefunden und gefixt, 167 von 402 Updates durchgeführt.

-- update --
Inzwischen habe ich noch einen Fehler beim -o Parameter (Pakete ersetzen) gefixt. Leider kann ich das große Update nicht mehr weiterlaufen lassen. Der INDEX wurde zwischenzeitlich aktualisiert und Listet Pakete die nicht vorhanden sind. Damit scheitert natürlich der Download. Das Update wird jedoch erst durchgeführt, wenn alle benötigten Pakete vorhanden sind, damit also im Moment gar nicht. :(

Ich betrachte das als Bug in Tinderbox, soul_rebel hat auch einen entsprechenden PR eingereicht, der leider bislang ignoriert wurde.

prid?
 
ports/131439[1] und ports/131440[2]. Du hattest die aber schon relativ schnell an portmgr übertragen (danke!), der anscheinend aber nicht ganz so schnell ist :/

[1] http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/131439
[2] http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/131440

Ok :)

//edit (zu schnelle finger)
Kurz vor dem Freeze wird sowas nicht mehr angegangen. Ich werde mal sehen ob wir ne chance haben das relativ zeit nah nach dem freeze hinbekommen. Natuerlich waeren patches hilfreicher um die Sache zu beschleunigen.
 
Um ehrlich zu sein habe ich keine Erfahrung im Betreiben eines Build-Servers. Nicht, dass ich mir das nicht zutraue, aber mir mangelt es schlicht an der Ressource Zeit um das ganze zu durchschauen und entsprechende Patches zu basteln. Also denke ich wir werden mit den Problemen leben, bis es nicht mehr erträglich ist und wir uns doch selbst darum kümmern, oder eine mitfühlende Seele (bzw. eine die gerne unsere Software verwendet) nimmt sich der Sache an.

Sehen wir der Sache mal ins Auge. Binärpakete installieren geht super. Alles Andere (was Binärpakete betrifft) ist unter FreeBSD aber ziemlich Murks. Alle, die regelmäßig updaten bauen aus den Ports. Selbst portupgrade -PP ist keine gute Lösung, da es im Grunde genommen auch Ports-zentrisch ist und nicht damit arbeitet was tatsächlich zur Verfügung steht.

Die Möglichkeit Binärpakete zu verwenden wird zwar stets beworben aber ist im echten Einsatz kaum zu gebrauchen. Die Werkzeuge an denen wir arbeiten könnten daran etwas ändern, aber solche Kinderkrankheiten zeigen einfach, dass es bisher tatsächlich noch niemand wirklich gemacht hat. Die Möglichkeit ist nur theoretisch vorgesehen.

Sollten die Tools entsprechenden Zulauf finden, würde es natürlich auch unserem Murren in den PRs und auf der Mailingliste Gewicht verleihen. Falls es jeweils so weit kommt, toll. Wenn nicht, dann ist die Lösung der Probleme nicht wirklich wichtig.
 
Auf meine Wunschliste kommt noch eine MOVED Datei auf dem gleichen Stand wie der Index. Mein Test ist inzwischen vollständig und ich bin ganz zufrieden. Aber eine MOVED Datei hätte mir bei 2 Paketen nachträgliches Hand anlegen erspart.
 
Ich verstehe gerade was ihr da macht und finde das gut. Wenig hilfreich bei eurer Arbeit, aber Applaus für euer/dein Vorhaben. Find ich gut!
 
Nein, gar nicht. Wir freuen uns über jeden der unsere Arbeit zu schätzen weiß! Das ist sehr motivierend und damit quasi implizit auch hilfreich.
 
Juchei, super - das hat wirklich gefehlt! Nachdem ich mich ein halbes Jahr mit einem Built-Jail und ewigen pkg_delete -f / pkg_add rumgeschlagen habe (und das ohne funktionierendes Werkzeug zur Update-Prüfung) hab ich resigniert und bin zu Ports in jedem Jail zurückgekehrt (und das sind pro Server so um die 20).

Mit Deinem / Eurem Skript könnte ich wieder zu einer sinnvollen Organisation meiner Built-Ressourcen zurückkehren. Vielen Dank dafür!

Dabei fällt mir grade ein, wo ich das lese: kann ich mit dem Skript auch auf lokale Paket-Repositories zurückgreifen (die wo mit make package erzeugt werden ;)), ohne den Umweg über FTP? Die könnte ich dann einfach mit nullfs read-only in die diversen Jails reinschießen...
 
Um nochmal in die Motivationskerbe zu hauen: die lediglich "theoretische Verfuegbarkeit" von Binaerupdates ist fuer mich die Hauptmotivation eben *nicht* alle meine Produktivkisten mit FreeBSD (oder irgendeinem anderen BSD) zu betreiben. Von dieser Warte aus gesehen ist diese Anstrengung, sollte sie echte Fruechte tragen, DAS Argument fuer mich, Linux endlich komplett aussen vor lassen zu koennen. Von dem her hoffe ich dass ihr weiter so gut vorankommt. :-)
 
Eigentlich bin ich ja sogar fertig, aber ich finde doch immer wieder noch kleine Fehler, also verzögere ich die Veröffentlichung weiter.

Das nächste Problem ist, dass man Pakete gelegentlich neu installieren muss, obwohl sich die Versionsnummer nicht geändert hat. Ein -fR für alle aktualisierten Pakete zu erzwingen wäre aber totaler Overkill.
Nun zum Glück passiert so etwas selten und in den Meisten fällen, kann man es mit pkg_libchk diagnostizieren.

Ich könnte auch noch einbauen, dass alte Versionen vom Libraries wie bei portupgrade in /usr/local/lib/compat landen. Aber das schmeckt mir von Sicherheitsaspekten her gar nicht.
 
Wäre es möglich, fetch(1) anstatt nc(1) zu nehmen? Die ganzen pkg_ tools benutzen fetch und damit ist auch problemlos ein Betrieb über einen Proxy-Server mit Authentifizierung möglich (HTTP_PROXY Variable).

Wie erfolgreich war dein Test denn, was die Verfügbarkeit der Binärpakete angeht? Wurden alle Pakete aktualisiert?
 
Zum download wird fetch verwendet. Mit nc wird bloß geprüft ob die Datei wirklich geladen werden muss. Wenn die Prüfung scheitert, wird der INDEX neu geladen. Das heißt durch einen Proxy wird der INDEX bei jedem Aufruf neu geladen, weil das Programm blind ist.

Der Test verlief sehr vielversprechend. Das Programm ignoriert allerdings installierte Pakete, die nicht im INDEX des Build-Servers gelistet sind einfach. Um die muss man sich dann selbst kümmern. Es wurden ca. 400 Pakete aktualisiert. Damit ist der Rechner nicht auf dem neusten Stand im Sinne der Ports, aber im Sinne verfügbarer Binärpakete schon.

Insofern ist die Frage recht zwecklos. Was nicht als Binärpaket verfügbar ist, existiert für das Programm überhaupt nicht. Wie denn auch, der Index listet ja bloß, was es gibt. Und ein Ports-Tree wird weder benötigt, noch wird er irgendwie verwendet, wenn er vorhanden ist.
 
Zuletzt bearbeitet:
Danke für die Info mit fetch. Das Ganze Projekt klingt sehr interessant, ich bin bin gespannt, es mal auszuprobieren.
 
Wenn ein Proxy für dich ein kritisches Szenario ist, solltest du vielleicht an folgendem PR von soul_rebel Interesse anmelden: http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/131440

Ich schätze früher oder später müssen wir selbst die Patches liefern, die die gewünschten Features implementieren, aber es schadet sicher nicht die vorhandene Nachfrage kund zu tun.

--edit--
Ich habe gerade fetch -m entdeckt. Autsch.
 
Zuletzt bearbeitet:
Hier mal was für's Auge, Konfliktbehandlung:
Code:
[root@tinderbox ~]# pkg_upgrade -v apsfilter
Synchronize the local index copy with the package server.
Synchronizing index with: ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-7-stable
Make a list of outdated packages.
Perform dependency checks.                           
Sort packages by dependency.             
Downloaad missing and damaged packages.    
Install 3 package(s).                          
===> Install <psutils-letter-1.17_2> (print/psutils-letter)
pkg_upgrade: The package <psutils-letter-1.17_2> will not be installed in favour of <psutils-a4-1.17_2>, because they conflict.
===> Install <a2ps-letter-4.13b_4> (print/a2ps-letter)
pkg_upgrade: The package <a2ps-letter-4.13b_4> will not be installed in favour of <a2ps-a4-4.13b_4>, because they conflict.
===> Update <apsfilter-7.2.8_5> to <apsfilter-7.2.8_5> (print/apsfilter)
pkg_add: package 'psutils-letter-1.17_2' conflicts with psutils-a4-1.17_2
pkg_add: please use pkg_delete first to remove conflicting package(s) or -f to force installation
pkg_add: autoload of dependency '/usr/ports/packages/All/psutils-letter-1.17_2.tbz' failed (proceeding anyway)
pkg_add: package 'a2ps-letter-4.13b_4' conflicts with a2ps-a4-4.13b_4
pkg_add: please use pkg_delete first to remove conflicting package(s) or -f to force installation
pkg_add: autoload of dependency '/usr/ports/packages/All/a2ps-letter-4.13b_4.tbz' failed (proceeding anyway)
pkg_add: can't open dependency file '/var/db/pkg/psutils-letter-1.17_2/+REQUIRED_BY'!
dependency registration is incomplete
pkg_add: can't open dependency file '/var/db/pkg/a2ps-letter-4.13b_4/+REQUIRED_BY'!
dependency registration is incomplete

========================================================
************ Post Installation Tasks *******************
========================================================
*** Printer installation / apsfilter setup         ***  
    root# cd /usr/local/share/apsfilter; ./SETUP               
--------------------------------------------------------
*** In any case of trouble please read             ***  
    the apsfilter handbook: handbook.html                
    (FAQ included), HOWTO-BUGREPORTS                            
    under /usr/local/share/doc/apsfilter/apsfilter/                 
--------------------------------------------------------
*** Support only over apsfilter mailinglists       ***  
    please don't contact authors directly !!!
    For more infos see:
    http://www.apsfilter.org/support.html
    http://www.apsfilter.org/

pkg_upgrade: Add dependency <psutils-a4-1.17_2> (print/psutils-a4).
pkg_upgrade: Add dependency <a2ps-a4-4.13b_4> (print/a2ps-a4).
=> Update <apsfilter-7.2.8_5> to <apsfilter-7.2.8_5> (print/apsfilter) succeeded
Diese Ausgabe ist auf dem Dual-Quadcore entstanden, der mir zum Testen zur Verfügung steht. Ich habe alleine heute morgen noch 3 Bugs gefunden, einer davon ziemlich kritisch.
 
Ach ja, wie's aussieht bin ich fertig. Will jemand Beta-Testen? Wenn ja, PM mit der E-Mail Adresse an mich.
 
Zurück
Oben