Ingvar's RPM tips and tricks

Here I have collected som rpm tips and tricks I have found useful over the years

More documentation

This page is crap! Where is the real info?

For a good starting point on using rpm and creating rpm packages, have a look at Eric Foster-Johnson's RPM Guide at http://fedora.redhat.com/docs/drafts/rpm-guide-en/.

For more system (fedora) related info, try Fedora's packaging guidelines at http://fedoraproject.org/wiki/Packaging/Guidelines.

Building packages without using the root account

When building rpm packages from source rpms, people often uses the root account, simply because the standard settings for rpmbuild has /usr/src/redhat or /usr/src/rpm or some similar path as it's default build environment. This is of course abuse of root's power, as it's trivial make rpmbuild work on a normal user's home directory instead. Here's a quick receipe:
mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/BUILD  ~/rpmbuild/SPECS ~/rpmbuild/RPMS
echo '
%_topdir /home/user/rpmbuild
%_tmppath /home/user/rpmbuild/BUILD
%_buildroot /home/user/rpmbuild
' > ~/.rpmmacros

Change /home/user to your user account's home directory. If you don't want to build debug-packages, add a final line

%debug_package %{nil}

You may also want to set %_tmppath to /var/tmp or some other place with lots of disk space if you want to save space on your home directory during building.

That's all. Now you can do 'rpm --rebuild' as yourself. You probably already guessed where the packages are finally saved.

Getting rid of pesky perl dependencies

When designing rpm packages from scratch, and using perl CPAN packages, you may have noticed that rpmbuild does a lot of automagic to find perl dependencies. From time to time, this is very annoying. Let's say you want to include some example scripts that uses some Oracle bindings eg under /usr/share/doc/mypackage-0.1/examples You probably don't want to include perl dependencies for this script for the package you are making, but rpmbuild adds them while scanning through the files.

The solution simple. Just make the scripts non-executable during the installation, and add the executable bit after installation if necessary. rpmbuild only parses executable perl scripts.

%install
(...)
chmod -x %{buildroot}%{_docdir}/mypackage/examples/example1.pl

%post
(...)
chmod +x %{buildroot}%{_docdir}/mypackage/examples/example1.pl

Fix a totally broken rpm database (rhel4)

From time to time, on older systems like rhel4, the rpm database breaks. It is just like that. The quick fix is

pkill -9 up2date
pkill -9 rpmq
pkill -9 rpm
rm /var/lib/rpm/__db.*
rpm --rebuilddb
Now, there are times when this is not enough. The package database is completely broken, and rebuilddb fails or leaves you with a broken database. If you are lucky, you discover this before /var/log/rpmpkgs.* are all rotated out. If you have such a file, this approach may help: First move the old database away and install a new one
mv /var/lib/rpm /var/lib/rpm.broken
rpm --initdb
Then manually download the correct redhat-release package from RHN, install it, and import the GPG key
rpm -Uvh --nodeps redhat-release-4ES-9.i386.rpm
rpm --import /usr/share/doc/redhat-release-4ES/RPM-GPG-KEY
Now check if you are able to install a package
up2date --justdb --install bash
If your up2date cache is broken (may happen from time to time), scratch it
rm -rf /var/spool/up2date
mkdir /var/spool/up2date
If you had to clear out the cache, the next time you run up2date may take a long time. I've seen systems using 15-20 minutes on this.
up2date --justdb --install bash
Now update the kernel packages and any other kernel related packages, as those are usually prohibited in the up2date config from being automatically dragged in by dependencies.
up2date --justdb --install --force kernel-smp kernel-utils
If that went well, update the system with metadata from the repo, using the latest working rpmpkgs log file, in this example rpmpkgs.1 was intact:
sed 's/\(.*\)-.*-.*/\1/' < /var/log/rpmpkgs.1 | sort -u | xargs up2date --install --justdb
The scenario above fetched all packages from the active repos in /etc/sysconfig/rhn/sources. If the system has been broken over time, the packages in the repo may be newer than the content you have got on disk. That may lead to confusion, since you only updated the database with the latest versions, and not the actual package content. So finally, you must find and fix everything that went wrong
diff -u <(sort /var/log/rpmpkgs.1) <(rpm -qa --qf "%{name}-%{version}-%{release}.%{arch}.rpm\n" | sort)
If some newly installed packages are newer, you have to reinstall them with content (ie. without --justdb). Packages can be downloaded and reinstalled with
cd /var/spool/up2date
up2date --get packagename
rpm -Uvh --replacepkgs packagename-ver-rel.arch.rpm

Maintain a complete rpm redhat package mirror using up2date

Sometimes, It's impossible to use up2date for downloading and installing rpm packages from RedHat, even using a web proxy. Under such circumstances, it would be appropriate to maintain a local mirror of all packages available from the subscribed channel. Let's say you want to keep all packages in /var/mirror/rhel3. Then, just add this to you crontab:

up2date --nox --showall | sed 's/\(.*\)-.*-.*/\1/' | xargs up2date --get --tmpdir /var/mirror/rhel3

Note that here, we (ab)use RedHat's strong naming policy. Alle packages in RedHat's up2date repositories are named like this:

name-version-patchlevel.arch.rpm
If you are downloading packages from a vendor breaking this policy, the sed filter above would have to be changed.

Using an APT repository with up2date

up2date now supports apt and yum repositories in addition to RedHat's up2date mirrors. Adding a new apt repo is quite strightforward: Add a line looking like the following to your /etc/sysconfig/rhn/sources :
apt citrus http://apt.repo.server/path/to somedistro/i386 orange lemon
Note that the first name (citrus) is just a label, and has no effect on the result. 'orange' and 'lemon' are two different repositories. You can add more if you like.

Also note that you can NOT have two repos with the same name, although they have different labels. This means that adding two repos like this:
apt citrus-i386 http://apt.repo.server/path/to somedistro/i386 orange
apt citrus-noarch http://apt.repo.server/path/to somedistro/noarch orange
will NOT work. up2date will try to pull all packages from the first repo. The reason for this is probably some bug in up2date, see Bugzilla Bug #206634

Run a RedHat kernel on Debian

There are at least two problems with running RedHat kernels on Debian:

Here follows a sort-of receipe. Something similar was done with a RHEL4 kernel on Debian Sarge and on Ubuntu Breezy.

  1. On a system with a well-working rpm: Repack the kernel rpm to a cpio archive
    rpm2cpio < kernel-smp-2.6.9-22.EL.i686.rpm > kernel-smp-2.6.9-22.EL.i686.cpio
    
  2. Copy the cpio archive onto the target system
  3. Unpack the cpio archive, and update module dependencies
    cd /
    cpio --verbose --extract --make-directories /path/to/kernel-smp-2.6.9-22.EL.i686.cpio
    depmod -a -v 2.6.9-22.ELsmp
    
  4. Build a standard Debian initrdimage for your kernel using yaird (older debian) or mkinitramfs (newer debian/ubuntu)

    Skip the rest of this paragraph if you have the more modern mkinitramfs installed. Just run

    VERSION=2.6.9-22.ELsmp
    mkinitramfs -o /boot/initrd.img-$VERSION $VERSION
        
    ... and skip to 5.

    Else, you need yaird. Add backports to your sources.list as described here: http://backports.org/dokuwiki/doku.php?id=instructions

    On Ubuntu, you may have to add the backport's gpg-key:

    gpg --keyserver www.keyserver.net --recv-keys EA8E8B2116BA136C  
    gpg --export --armor EA8E8B2116BA136C | apt-key add -
    

    Then do the actual install:

    apt-get -t sarge-backports install yaird
    

    Create the new initrd image:

    yaird --test 2.6.9-22.ELsmp # Check that you get no errors
    yaird --output /boot/initrd.img-2.6.9-22.ELsmp 2.6.9-22.ELsmp
    
  5. Make the system ready for boot
    update-grub
    
  6. Drink a cup of coffee

Comments? Send them to [email protected]