How to upgrade packages

From NetBSD Wiki

Jump to: navigation, search

There are various techniques for upgrading packages either by using pre-built binary package tarballs or by building new packages via pkgsrc build system. This wiki page hopefully will summarize all of the different ways this can be done, with examples and pointing you to further information.

Contents

Methods using only binary packages

pkg_add -uu

pkg_add's -u option is used to update a package. Basically: it saves the package's current list of packages that depend on it (+REQUIRED_BY), installs the new package, and replaces that list of dependencies.

By using the -uu (option used twice), it will attempt to update prerequisite packages also.

See the manual page, pkg_add(1), for details.

Caveat: dependencies on shared libraries' versions are not tracked -- upgrading a package that provides a shared library may break others. See PR 27556.

pkg_chk -b

Use "-b -P URL" where URL is where the binary packages are (e.g. ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD-3.1/i386/All).

For example, to update any missing packages by using binary packages:

       pkg_chk -b -P URL -u

Or to automatically add any missing packages using just binary packages:

       pkg_chk -b -P URL -a -C pkg_chk.conf

If both -b and -P are given, no pkgsrc tree is used. If packages are on the local machine, they are scanned directly, otherwise the pkg_summary database is fetched. (Using pkg_summary for local packages is on the TODO list.)

(pkg_chk is also covered below.)

Methods that build packages from source

Note: Be sure you have an updated "pkgsrc" directory. It is recommended that you don't update just parts of the pkgsrc directory.

make update

'make update', invoked in a pkgsrc package directory, will remove the package and all packages that depend on it, keeping a list of such packages. It will then attempt to rebuild and install the package and all the packages that were removed.

It is possible, and in the case of updating a package with hundreds of dependencies, arguably even likely that the process will fail at some point. One can fix problems and resume the update by typing make update in the original directory, but the system can have unusuable packages for a prolonged period of time. Thus, many people find 'make update' too dangerous, particularly for something like glib on a system using gnome.

To use binary packages if available with "make update", use "UPDATE_TARGET=bin-install". If package tarball is not available in ${PACKAGES} locally or at URLs (defined with BINPKG_SITES), it will build a package from source.

To enable manual rollback one can keep binary packages. One method is to always use 'make package', and to have "DEPENDS_TARGET=package" in /etc/mk.conf. Another is to use pkg_tarup to save packages before starting.

make replace

The make replace target should only be used by those who understand that there may be ABI issues and can deal with fixing the resulting problems. It is possible that a replaced package will have a different binary interface and thus packages that depend on the replaced packages may not work correctly. This can be because of a shlib (shared library) version bump, where depending package binaries will no longer run, or something more subtle. In these cases, the correct fix is to 'make replace' the problematic depending package. The careful reader will note that this process can in theory require all packages that depend (recursively) on a replaced package to be replaced. See the pkg_rolling-replace section for a way to automate this process.

The "make replace" target preserves the existing +REQUIRED_BY file, uninstalls the currently installed package, installs the newly built package, reinstalls the +REQUIRED_BY file, and changes depending packages to reference the new package instead. It also marks such depending packages with the "unsafe_depends" build variable, set to YES.

It also uses the pkg_tarup tool to create a tarball package for the the currently installed package first, just in case there is a problem.

make replace should preserve the "automatic" build variable, but does not.

If you are an expert (and don't plan to share your packages publically), you can also use in your mk.conf:

 USE_ABI_DEPENDS?=no

This is for ignoring the ABI dependency recommendations and just use the required DEPENDS.

problems with make replace

Besides ABI changes (for which pkg_rolling-replace is a good solution), make replace can fail if packages are named or split. A particularly tricky case is when package foo is installed, but in pkgsrc has been split into foo and foo-libs. In this case, make replace will try to build the new foo (while the old monolithic foo is installed). The foo package depends on foo-libs, and so pkgsrc will go to build and install foo-libs. This will fail because foo-libs will conflict with the old foo. There are three approaches:

  • manually save the foo +REQUIRED_BY file, pkg_delete foo, and then make package of the new foo. Put back the +REQUIRED_BY, and pkg_admin set unsafe_depends=YES all packages in the +REQUIRED_BY.
  • pkg_delete -r foo, and make package on everything you still want. Or do make update. Note that this could delete a lot.
  • Automating the first option would be a useful contribution to pkgsrc.

In addition, any problem that can occur with building a package can occur with make replace. Usually, the solution is not make replace specific

pkg_rolling-replace

pkgtools/pkg_rolling-replace is a shell script available via pkgsrc. It makes a list of all packages that need updating, and sorts them in dependency order. Then, it invokes "make replace" on the earliest one, and repeats. A package needs updating if it is marked unsafe_depends or if it is marked rebuild (=YES). If pkg_rolling-replace is invoked with -u, a package needs updating if pkgtools/pkg_chk reports that the installed version differs from the source version. On error, pkg_rolling-replace exits. The user should remove all working directories and fix the reported problem. This can be tricky, but the same process that is appropriate for a make replace should be followed.

Because pkg_rolling-replace just invokes make replace, the problems of ABI changes with make replace apply to pkg_rolling-replace, and the system will be in a state which might be inconsistent while pkg_rolling-replace is executing. Whether it actually is inconsistent depends on whether ABI changes that matter actually happened. But, by the time pkg_rolling-replace has successfully finished, the system will be consistent because every package that has a depending package 'make replaced' out from under it will be marked unsafe_depends, and then replaced itself. This replace "rolls" up the dependency tree because pkg_rolling-replace sorts the packages by dependency and replaces the earliest needing-rebuild package first.

See the pkg_rolling-replace man page (installed by the pkg) for further details.

pkg_rolling-replace was written in 2006, but seems to work well. gdt uses it on machines that have to work without fear.

Real-world experience with pkg_rolling-replace

Even if a lot of packages need to be updated, make replace usually works very well if the interval from the last 'pkg_rolling-replace -u' run is not that long (a month or so). With a longer interval, like a year or two, the odds of package renaming/splitting are higher. Still, for those who can resolve the issues, this is a fairly low-pain and reliable way to update.

pkg_chk -g/-r/-a

Generate a list of all your installed packages with "pkg_chk -g". This list goes in ${PKGSRCDIR}/pkgchk.conf by default. (This is needed for the -a step.)

Then remove the out-dated ones with "pkg_chk -r" (or just remove them all), and then rebuild what you had before with "pkg_chk -ask" (to build packages from source).

To install from packages instead of from source, use "-b" instead of "-s". (Then no pkgsrc directory is needed.)

See the pkg_chk(8) or pkgtools/pkg_chk for details.

TODO: review above

pkg_chk -u provides a means for updating all inconsistant packages.

# pkg_chk -usk

This updates all outdated packages on the system from source. It keeps going if there is an error in a package, which would otherwise ruin the whole update. It is also a good idea to set UPDATE_TARGET=package in /etc/mk.conf and specify the -b flag, so that the results of compilation work are saved for later use and binary packages are used if they are not outdated or dependent on outdated packages.

# pkg_chk -uq

This lists all outdated packages. It must recurse through the pkgsrc tree, so it is rather slow. It is a good idea to save this list ( > pkg_chk.out ), so that the command only has to be run every so often.

pkgmanager

Pkgmanager use user defined list of wanted packages for upgrading and installing packages.

%pkgmanager show-wants

[pkgmanager] Wanted packages:
[pkgmanager]    (audio/cdparanoia . 1.0)
[pkgmanager]    (audio/gtkpod . 1.0)
[pkgmanager]    (audio/lame . 1.0)
[pkgmanager]    (audio/xmms . 1.0)
[pkgmanager]    (chat/gaim . 1.0)
[pkgmanager]    (chat/gaim-encryption . 1.0)
[pkgmanager]    (chat/gaim-otr . 1.0)
[snip]
[pkgmanager]    (wm/enlightenment . 1.0)
[pkgmanager]    (www/firefox . 1.0)
[pkgmanager]    (www/lighttpd . 1.0)
[pkgmanager]    (www/links . 1.0)
[pkgmanager]    (x11/eterm . 1.0)
[pkgmanager]    (x11/gdm . 1.0)

User can add packages to this list with "pkgmanager want/install" (add package to the list and install it) command and remove them with "unwant/unistall" (remove package from the list and deinstall it).

User can upgrade his packages with "pkgmanager sync". This command removes packages installed on system which are not listed on want list. Then upgrade all wanted packages and dependencies to new version.

delete everything

If you don't have a production environment or don't care if your packages will be missing for a while, you can just delete everything and reinstall.

This method is the easiest:

# pkg_delete -Rr '*-*'
-or-
# pkg_delete -ff '*-*'

This expands to all packages, and deletes all packages without caring about dependencies. The second version of the command should be faster, as it does not perform any dependency recursion. (The quotes around the wildcards are so it doesn't get expanded by the shell first.)

Here is one idea (from posting on pkgsrc-users):

Get a list of packages installed:

# pkg_info -Q PKGPATH -a > pkgs_i_want_to_have

Remove all the packages:

# pkg_info -a | sed 's/ .*//' | tail -r | while read p ; do pkg_delete $p ; done

(There are many ways to do this.)

Then edit your "pkgs_i_want_to_have" (created above) as needed. And reinstall just those from it:

# cat pkgs_i_want_to_have |
   (while read pp ; do cd /usr/pkgsrc/$pp ; make && make install ; done)

An alternative way to choose the packages you want installed is to create your own custom meta-package. A meta-package doesn't install any files itself, but just depends on other packages (usually within a similar topic or need). Have a look at pkgsrc/meta-pkgs category for various examples. If your new meta-package is generic enough and useful for others, please be sure to share it.

chroot environment

Nothing special here. This is really basically the same as just having a another physical system to build packages.

Manually setup a directory containing your base operating system (including compilers, libraries, shells, etc). Put a copy of your pkgsrc tree and distfiles into there or use mount to mount shared directories containing these. Then use the "chroot" command to chroot into that new directory. You can even switch users from root to a regular user in the new environment.

Then build and remove packages as you wish with out affecting your real production system. Be sure to create packages for everything.

Then use other technique from this list to install from these packages (built in chroot).

Or instead of using this manual method, use pkg_comp's chroot.

pkg_comp's chroot

Apart from the examples in the man page, it's necessary supply a list of packages you want to build. The command 'pkg_info -u -Q PKGPATH' will produce a list of packages you explicitly requested be installed; in some strong sense, it's what you want to rebuild.

After you've built new new packages, you need the list of files to reinstall. Assume that you saved the output of 'pkg_info -u -Q PKGPATH' in /etc/pkgs. The following script will produce the name of the binary packages:

   while read x
   do
        cd /usr/pkgsrc/$x && make show-var VARNAME=PKGNAME
   done </etc/pkgs

If you use PKGBASE instead of PKGNAME, you get the basename of the file.

See this BSDFreak Article for a nice tutorial on how to set up and use pkg_comp.

bulk build framework

Use the scripts in pkgsrc/mk/bulk/, e.g. as pointed out in http://www.netbsd.org/Documentation/pkgsrc/binary.html#bulkbuild

To go easy on the existing pkgsrc installation, creating a sandbox (automated chroot environment) is highly recommended here: http://www.netbsd.org/Documentation/pkgsrc/binary.html#setting-up-a-sandbox

You can later mount the pkgsrc/packages/ via NFS wherever you want and install them like:

set PKG_PATH /mnt/packages/All && pkg_add <pkg>

Or upload them on a www-site and pkg_add http://www.site/packages/All/<pkg>

wip/distbb - distributed bulk builds

Using wip/distbb you may build packages in parallel using several machines and/or chroots. Read PREFIX/share/doc/distbb/README file for the instructions.

pkgdepgraph

Look at the EXAMPLES in the man page.

TODO: how to do this using binary packages only? Put in section above.

pkg_select

alternate LOCALBASE and PKG_DBDIR

Use an alternate LOCALBASE setting to install the packages under a new location and an alternate PKG_DBDIR for your alternate database of installed packages.

You can choose the PKG_DBDIR via shell environment variable or using the -K switch with any of the standard pkg_* tools.

And set the LOCALBASE and your PKG_DBDIR in your mk.conf file.

You could also simply just have a symlink from /usr/pkg to your new LOCALBASE (and /var/db/pkg to your new PKG_DBDIR) and change this when ever you are ready.

pkgviews

Questions

How do I prevent an upgrade from apache-1.3 to apache-2.2?

Some packages like apache, php, mysql-server are available in multiple versions. When I have chosen to install apache-1.3, I probably have done so on purpose, and I don't want any of the update methods above to replace it with apache-2.2. How can I say this?

Template:TODO

Personal tools