|
Got ports? Here is THE way to upgrade them!
11 December 2001
|
|
There are many articles on ports in this Diary.
Only a few deal specifically with upgrading your ports. This article beats them all!
Imagine, if you will, a command which allows you to upgrade all of your ports. Stop thinking
about make install distclean . No, I mean one command to upgrade each
and every port!
This isn't fantasy or fiction. It's real. And it's called portupgrade . I first heard
about this great new tool a few months ago, but I never used it until
Michael Lucas wrote
an article about it
in O'Reilly. This was the first time I've read about portupgrade .
Coincidentally, I was just starting to install some new ports on my laptop in preparation
for a talk I was going to give at a local Linux User Group.
It wouldn't do if I gave my presentation on a Windows box....
What I will be giving here will be an overview. You really should read Michael's article first.
|
|
The problem
|
The ports tree is one of the best FreeBSD features I can think of.
It's a great way to install software. Fortunately, software gets updated. Unfortunately, some ports expect
a certain version of software. When they don't find it, they can sometimes get very uncooperative and refuse
to run. When you upgrade a port and force the install (I'll provide an example later), sometimes other ports
which depend on that newly upgraded port will break. It can become a vicious cycle, upgrading one port after
another as they dependencies flow outwards. Fortunately, portupgrade does this for you.
pkg_version is your friend when it comes to seeing what ports are up to date. Of course, that does depend
upon a recent cvsup of your ports tree. This is pretty easy to do:
# cvsup /usr/share/examples/cvsup/ports-supfile -h cvsup.yourhost.org
where cvsup.yourhost.org is your favorite cvsup mirror. Please
refer to Using CVSup
in the FreeBSD Handbook.
Here's an example of [manually] upgrading a port upon which other ports are dependant. In this case, I've tried to upgrade
devel/glib12 and I'm not upgrading a port, I'm just reinstalling the same
version of an already installed port. Not very useful, but it does illustrate part of the problem.
===> Installing for glib-1.2.10_4
===> glib-1.2.10_4 is already installed - perhaps an older version?
If so, you may wish to ``make deinstall'' and install
this port again by ``make reinstall'' to upgrade it properly.
If you really wish to overwrite the old port of glib-1.2.10_4
without deleting it first, set the variable "FORCE_PKG_REGISTER"
in your environment or the "make install" command line.
*** Error code 1
Stop in /usr/ports/devel/glib12.
*** Error code 1
Stop in /usr/ports/devel/glib12.
[root@laptop:/usr/ports/devel/glib12] #
You could try doing a pkg_delete , but then you'd get this:
# pkg_delete glib-1.2.10_4
pkg_delete: package `glib-1.2.10_4' is required by these other packages
and may not be deinstalled:
xchat-1.7.8
imlib-1.9.11
fnlib-0.5
gtk-1.2.10
enlightenment-0.16.5_5
ORBit-0.5.7
And you could do a pkg_delete -f glib-1.2.10_4 , but that would mess with the
port database (/var/db/pkg ). The ports listed above
would then be referencing a version of glib which is no longer installed.
If we were actually installing a new version of the port, the dependant ports would
be pointing at glib-1.2.10_4 instead of the newly installed version.
|
|
Installing portupgrade
|
To install portupgrade, I did this:
# cd /usr/ports/sysutils/portupgrade/
# make install distclean
My environment does not include /usr/local/sbin (the install location
for the portupgrade tools ) so
I had to prefix all my commands with that directory. This install actually gives you a collection
of tools. Read man portupgrade for details.
|
|
Backup your data
|
Backup your package database before you start!
# cd /var/db
# tar cvfz var.db.pkg.tgz pkg
Keep that file safe....
|
|
Two versions of the same port
|
Sometimes you can wind up with two versions of the same port installed. For example:
# pkg_info | grep m4
m4-1.4 GNU's m4
m4-1.4_1 GNU's m4
/usr/local/sbin/pkgdb -F is your friend. For simplicity, I'll only show the interesting bits.
# /usr/local/sbin/pkgdb -F
[Rebuilding the pkgdb in /var/db/pkg ... - 34 packages found (-0 +34)
.................................. done]
Checking the origin of BitchX-1.0c18
Checking the origin of apache-1.3.14_1
Checking the origin of autoconf-2.13
Checking the origin of autoconf213-2.13.000227
Checking the origin of bash-2.04
Missing origin.
Guessing... [Updating the ports database in /usr/ports ... -
6077 port entries found .........1000.........2000........
.3000.........4000.........5000.........6000 (...) done]
shells/bash2 (bash-2.05a): Use this? [yes]
Fixed. (-> shells/bash2)
It couldn't find bash . So it went through /user/ports/INDEX and found the right one and
updated the database. For more information on using pkgdb, see
pkgdb - packages database tool.
Checking the origin of lynx-2.8.4d9
Missing origin.
Guessing...
www/lynx (lynx-2.8.4.1): Use this? [yes]
Fixed. (-> www/lynx)
Then it did similar for lynx .
Duplicated origin: devel/m4 - m4-1.4 m4-1.4_1
Remove any of them? [no] y
Remove the package record of m4-1.4 ? [no] y
-> m4-1.4_1 is kept.
--> Saving the m4-1.4's +CONTENTS file as /var/db/pkg/m4-1.4_1/+CONTENTS.m4-1.4
--> Removing the m4-1.4's record
--> Done
[Updating the pkgdb in /var/db/pkg ... - 33 packages found (-1 +0) (...) done]
Then I was asked about the duplicated port. So I removed the old one, keeping the new one.
Then the ports database was updated with the changed information. But that's not the end.
Now that a port has been removed, let's go through the dependencies, because that change
probably affects another port.
Stale dependency: autoconf-2.13 -> m4-1.4:
m4-1.4_1 (score:100%) ? ([y]es/[n]o/[a]ll) [yes] a
Fixed. (-> m4-1.4_1)
Here, autoconf requires m4 but it's looking for the old version. pkgdb can update
this for you. If you answer y it will be updated for this port. If you answer a , it will
update this stale dependency for all ports (i.e. change all m4-1.4 references to be m4-1.4_1 ).
|
|
Updating all the ports!
|
I know this is the command you've been waiting for. It is very powerful. So be careful.
# /usr/local/sbin/portupgrade -ra
** The port directory for 'net/cvsup-bin' does not exist.
** No need to upgrade 'screen-3.9.10' (>= screen-3.9.10).
** No need to upgrade 'libtool-1.3.4_2' (>= libtool-1.3.4_2).
[snip]
Here you can see that the installed port screen-3.9.10
is at least as new as the one in the ports tree: screen-3.9.10 .
So the port is not upgraded.
** No need to upgrade 'autoconf213-2.13.000227' (>= autoconf213-2.13.000227).
** No need to upgrade 'bzip2-1.0.1' (>= bzip2-1.0.1).
** No need to upgrade 'gmake-3.79.1' (>= gmake-3.79.1).
===> Cleaning for XFree86-4.1.0_10
In this case, we're upgrading XFree86-4.1.0_10.
When I did this on another box, these were the ports waiting to be upgraded:
$ pkg_version -L =
apache <
autoconf <
bash *
bind <
cclient <
cvsup-bin ?
gettext *
lynx *
majordomo <
mkisofs <
nslint <
qpopper <
rsync <
screen <
siege <
sudo <
After running portupgrade -ar overnight, this is what portupgrade
had to say:
Updating the pkgdb in /var/db/pkg ... - 34 packages found (-0 +1) . done]
** The following packages were not installed or upgraded (-:skipped / !:failed)
! (cvsup-bin-16.1) (missing origin)
- lang/pm3-base (pm3-base-1.1.15)
- lang/pm3-net (pm3-net-1.1.15)
- lang/ruby (ruby-1.6.5.2001.11.23)
- net/ruby-uri (ruby-uri-0.9,1)
- devel/ruby-fnmatch (ruby-fnmatch-1.1b_1)
- editors/joe (joe-2.8_3)
! net/bind8 (bind-8.2.3) (checksum mismatch)
- devel/libtool (libtool-1.3.4_2)
- devel/gettext (gettext-0.10.35)
- www/lynx (lynx-2.8.4d9)
- irc/bitchx (BitchX-1.0c18)
- misc/pkg_tarup (pkg_tarup-1.2_3)
- devel/ruby-optparse (ruby-optparse-0.8.4)
- sysutils/portupgrade (portupgrade-20011118)
- net/p5-Net (p5-Net-1.0703)
- security/logcheck (logcheck-1.1.1)
- devel/m4 (m4-1.4_1)
- devel/autoconf213 (autoconf213-2.13.000227)
- archivers/bzip2 (bzip2-1.0.1)
- devel/gmake (gmake-3.79.1)
- mail/cclient (cclient-2001,1)
Two ports did mot upgrade:
cvsup-bin because it could not be found in the tree.
net/bind8 because of a checksum mismatch. The downloaded tarball did not match
that expected by the port.
I will show you how to get around that bind problem, but you should note that the example I provide
below for bind8 is generic and could be applied to any other port. But also realize
that bind8 is supplied with the base system in FreeBSD. Upgrading it from ports is possible
but you need to follow slightly different instructions. That said, have a read of the
following but keep in mind that I will be installing bind8 again just after this example.
I won't be upgrading cvsup-bin as it's an old port an no longer used on this box.
# cd /usr/ports/net/bind8/
# make distclean
That removed the existing tarball from /usr/ports/distfiles . Then I tried again:
# /usr/local/sbin/portupgrade bind
===> Cleaning for bind-8.2.5
>> bind-src.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
>> Attempting to fetch from ftp://ftp.isc.org/isc/bind/src/8.2.5/.
Receiving bind-src.tar.gz (1329713 bytes): 100%
1329713 bytes transferred in 15.2 seconds (85.61 kBps)
>> bind-doc.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
>> Attempting to fetch from ftp://ftp.isc.org/isc/bind/src/8.2.5/.
Receiving bind-doc.tar.gz (1486296 bytes): 100%
1486296 bytes transferred in 15.0 seconds (96.83 kBps)
===> Extracting for bind-8.2.5
>> Checksum OK for bind-src.tar.gz.
>> Checksum OK for bind-doc.tar.gz.
===> Patching for bind-8.2.5
[snip]
===> Compressing manual pages for bind-8.2.5
===> Registering installation for bind-8.2.5
===> Cleaning for bind-8.2.5
[Updating the pkgdb in /var/db/pkg ... - 34 packages found (-0 +1) . done]
That correctly installed the port. However, it did not install bind the way
bind was included with the base system. The above will run, but it won't
replace the built-in bind. To properly replace bind, I followed the
instructions here.
|
|
Out of date ports
|
Even after I cvsup'd my ports, ran portupgrade, one port was still
out of date.
# cd /usr/ports/devel/ruby-optparse
# make fetch
>> optparse-0.8.5.tar.gz is not in /usr/ports/devel/ruby-optparse/distinfo.
>> Either /usr/ports/devel/ruby-optparse/distinfo is out of date, or
>> optparse-0.8.5.tar.gz is spelled incorrectly.
*** Error code 1
Stop in /usr/ports/devel/ruby-optparse.
*** Error code 1
Stop in /usr/ports/devel/ruby-optparse.
*** Error code 1
Stop in /usr/ports/devel/ruby-optparse.
I think this means that the tarball optparse-0.8.5.tar.gz
(which will have been downloaded to /usr/ports/distfiles )
wasn't what the port expected. To be sure I had the latest and greatest, I deleted
the tarball and did another cvsup . Then I did a
# /usr/local/sbin/portupgrade -ra
...and everything upgraded fine.
|
|
One port did a bad thing
|
There was one problem I encountered, but this wasn't the fault of portupgrade .
It was the fault of the apache port which added a www:www user/group combination to my box. But
it overwrote what I already had. Bad port! BAD BAD PORT!
By the time you read this, I'm sure this bug will be fixed.
The problem was many of my webpages could not be read. They were chgrp www , but the group ID (GID) for
www had changed in /etc/group , but the values on disk were the old value.
Here's what it looked like:
-rw-r--r-- 1 dan 99 39229 Nov 2 2000 marc_dan.jpg
drwxr-xr-x 2 dan 99 512 Oct 16 2000 pics
-rw-r--r-- 1 dan 99 19057 Nov 30 2000 proposed_db.gif
See that 99? That is the group ID. That should be a name. The fact
that it is a number means there is no entry in /etc/groups for this group.
This is a result of www being removed and then
added again, but with a different ID.
If the problem were just these three files I wanted changed, I could do it easily.
But here's a script that did the whole disk. Instead of using 99 here,
be sure to use the value used on your system.
find / -user 99 -exec chown www {} \;
find / -group 99 -exec chgrp www {} \;
That fixed up the permissions.
|
|
Interactive ports
|
Another item to be aware of is ports that require interaction during their build.
You might leave portupgrade running over night and come
back and find that a port is waiting for input. For example, mail/majordomo
will display a message at the end of the install and wait for you to hit enter.
And www/mod_php4 asks for configuration values at the start.
|
|
Or you can use packages
|
portupgrade will also install packages, where available, if you
use the -P option. And -PP will use
packages only, never ports.
|
|
env: /usr/local/bin/ruby_s: No such file or directory
|
For details on this problem, please see what Akinori MUSHA had to say.
This was a rather annoying problem. Right after I tried upgrading a series of ports, I was
greeted with this error message.
# /usr/local/sbin/portupgrade -r jpeg
env: /usr/local/bin/ruby_s: No such file or directory
I encountered it more than once. This time it was right after having issued this command:
# /usr/local/sbin/portupgrade -r jpeg ruby ruby-optparse cvsweb autoconf automake expat
I found
it went away if I reinstalled portupgrade.
# cd /usr/ports/devel/linux_devtools]
# pkg_info | grep portupgrade
portupgrade-20011118 Very powerful FreeBSD ports/packages upgrading tool and more
# pkg_delete portupgrade-20011118
# make install
Then it worked fine.
Actually, I may have had to do a make install -DFORCE_PKG_REGISTER .
I'm not sure about this point. I didn't keep notes for that step.
|
|