Better late than never. This is the first “real” article in the Packaging Software series. It’s long, but hopefully it’ll help someone out. Enjoy!
So what’s an RPM?
In it’s distilled form, a big ball of files that hopefully make up something useful, like software. But wait, there’s more! It’s not just a file format for installing, uninstalling, updating, verifying software, it’s also the system for creating those bundles and doing all the installing, etc. Confused? What we have is two parts: The files commonly referred to as RPM, aka the software bundles, and rpm set of commands for creating and managing those bundles.
History and the Soap Opera
RPM was birthed by Red Hat as the Red Hat Package Manager, later becoming the RPM Package Manager as it became building block of more and more non-Red Hat Linux distributions. It’s grown to be used in innumerable Linux distros, large and small, popular and not.
I don’t want to get the drama wrong, so I’m just going to quote Wikipedia
As of the 31st of May, 2007, there are two versions of RPM in development. The first is led by long-time (since 1999) RPM maintainer, Jeff Johnson (‘JBJ’), who continued his development efforts after departing Red Hat. It has combined recently with efforts of OpenPKG and added a new website rpm5 tine of the fork. The ‘JBJ’ variant is used by Mandriva, PLD Linux Distribution and supported by OpenPKG. Jeff Johnson formerly worked for Red Hat before a controversy.
The other effort is led by Red Hat recent hire (2007) staff member Panu Matilainen. The Red Hat RPM tine of the fork which issued its first major code revision in July 2007, is used by Fedora, Red Hat Enterprise Linux, Novell’s openSUSE and CentOS. Matilainen has also worked on an apt-like front end for package management for RPM previously; apt-get is a Debian Linux management tool.
The displaced former RPM website content is archived by its long time maintainer at oldrpm web archive. On December 14, 2006, Red Hat decided to take complete control of editorial content at the formerly community maintained website which content was maintainted in an ‘open to the community’ process manner.
Does it matter to you? Probably not, just be aware there are currently two major forks of RPM and there may be slight differences in the API standards or tools that are available.
The simple things
So let’s do something useful. I’m working on a Red Hat system, so if you’re not it’s possible things will be a little different.
What do we have installed?
List them all
Good for grep’ing through when you don’t know what you’re looking for.
[jro@localhost ~]$ rpm -qa
libgcc-3.4.6-8.i386
filesystem-2.3.0-1.i386
glibc-common-2.3.4-2.36.i386
bzip2-libs-1.0.2-13.EL4.3.i386
...
Find a specific package
Good when you know it’s there, but just need the version.
[jro@localhost ~]$ rpm -q rmt
rmt-0.4b39-3.EL4.2.i386
Find out what RPM owns a file
Good for.. where the hell did that come from?
[jro@localhost ~]$ rpm -qf /etc/snmp/snmpd.conf
net-snmp-5.1.2-11.EL4.10.i386
Get some basic info on an installed package.
[jro@localhost ~]$ rpm -qi hdparm
Name : hdparm Relocations: (not relocatable)
Version : 5.7 Vendor: Red Hat, Inc.
Release : 2 Build Date: Tue 21 Sep 2004 05:23:51 AM CDT
Install Date: Wed 27 Jun 2007 04:10:31 PM CDT Build Host: tweety.build.redhat.com
Group : Applications/System Source RPM: hdparm-5.7-2.src.rpm
Size : 64075 License: BSD
Signature : DSA/SHA1, Wed 05 Jan 2005 05:18:55 PM CST, Key ID 219180cddb42a60e
Packager : Red Hat, Inc.
Summary : A utility for displaying and/or setting hard disk parameters.
Description :
Hdparm is a useful system utility for setting (E)IDE hard drive
parameters. For example, hdparm can be used to tweak hard drive
performance and to spin down hard drives for power conservation.
List all the files installed as part of a package
Good for where the hell did that config file get put?
[jro@localhost ~]$ rpm -ql rmt
/etc/rmt
/sbin/rmt
/usr/share/man/man8/rmt.8.gz
Installing and Upgrading RPMs
Installing a single RPM
[jro@localhost ~]$ rpm -i nginx-0.5.31-1.vp.i386.rpm
error: can't create transaction lock on /var/lock/rpm/transaction
Hrmm.. maybe I need to do this as root
[jro@localhost ~]$ sudo rpm -i nginx-0.5.31-1.vp.i386.rpm
Password: *****
[jro@localhost ~]$
Yep. Not a lot of output tho
[jro@localhost ~]$ sudo rpm -iv nginx-0.5.31-0.vp.i386.rpm
Preparing packages for installation...
nginx-0.5.31-0.vp
Better.
[jro@localhost ~]$ sudo rpm -ivh nginx-0.5.31-0.vp.i386.rpm
Preparing... ########################################### [100%]
1:nginx ########################################### [100%]
There we go.
Installing multiple packages at the same time
[jro@localhost ~]$ sudo rpm -ivh nginx-contrib-0.5.31-0.vp.i386.rpm
error: Failed dependencies:
nginx = 0.5.31 is needed by nginx-contrib-0.5.31-0.vp.i386
[jro@localhost ~]$ sudo rpm -ivh nginx-0.5.31-0.vp.i386.rpm
Preparing... ########################################### [100%]
1:nginx ########################################### [100%]
[jro@localhost ~]$ sudo rpm -ivh nginx-contrib-0.5.31-0.vp.i386.rpm
Preparing... ########################################### [100%]
1:nginx-contrib ########################################### [100%]
So our first package required another, and installing them one by one worked well enough but it’s a pain.
[jro@localhost ~]$ sudo rpm -ivh nginx-contrib-0.5.31-0.vp.i386.rpm nginx-0.5.31-0.vp.i386.rpm
Preparing... ########################################### [100%]
1:nginx ########################################### [ 50%]
2:nginx-contrib ########################################### [100%]
It’s way easier just to put them all together on one line. Or go c-razy and use file globbing ( rpm -ivh *.rpm ).
Upgrading RPMs
[jro@localhost ~]$ sudo rpm -Uvh nginx-contrib-0.5.31-1.vp.i386.rpm nginx-0.5.31-1.vp.i386.rpm
Preparing... ########################################### [100%]
1:nginx ########################################### [ 50%]
2:nginx-contrib ########################################### [100%]
It’s not too much different than installing, just that the -i turns into a -U. HOWEVER, you can also use the -U to install a package. So why bother using -i? It’s simple. Don’t. Always use -U, unless you specifically don’t want to upgrade a package you might have installed. It sounds silly, but you might end up in that situation one day if you have an RPM that restarts a service, etc.
Uninstalling.. er Erasing RPMs
[jro@localhost ~]$ sudo rpm -e nginx
Password:
error: Failed dependencies:
nginx = 0.5.31 is needed by (installed) nginx-contrib-0.5.31-1.vp.i386
[jro@localhost ~]$ sudo rpm -e nginx-contrib nginx
[jro@localhost ~]$
Pretty much what you’d expect at this point.
Useful Magic
See the architecture of a package
If you’re running a 64-bit machine, it’s VERY useful to know which packages are 32-bit and which are 64-bit. As on some distros it’s possible to have both versions installed, and then things start to get very confusing.
[jro@localhost ~]$ rpm -qa | head -5
libgcc-3.4.6-8
filesystem-2.3.0-1
glibc-common-2.3.4-2.36
bzip2-libs-1.0.2-13.EL4.3
ethtool-1.8-4
[jro@localhost ~]$ echo "%_query_all_fmt %%{name}-%%{version}-%%{release}.%%{arch}" >> ~/.rpmmacros
[jro@localhost ~]$ rpm -qa | head -5
libgcc-3.4.6-8.i386
filesystem-2.3.0-1.i386
glibc-common-2.3.4-2.36.i386
bzip2-libs-1.0.2-13.EL4.3.i386
ethtool-1.8-4.i386
We’ll talk more about the rpmmacros files when we get to building packages, but I recommend adding this even if you’re not running a system with packages from differing architectures.
See the changelog for a package
Installed package
[jro@localhost ~]$ rpm -q --changelog nginx
* Wed Sep 19 2007 0.5.31-1.vp
- add condrestart
* Wed Sep 19 2007 0.5.31-0.vp
- upgrade to latest stable
* Mon Sep 17 2007 0.5.26-3.vp
....
Package not yet installed
[jro@localhost ~]$ rpm -qp nginx-0.5.26-0.vp.i386.rpm --changelog
* Mon Jul 02 2007 0.5.26-0.vp
- new nginx version - 0.5.26
- start fork of package
* Wed May 23 2007 0.5.20-0
- new nginx version - 0.5.20
* Thu Apr 26 2007 0.5.19-0
Muck with the output format of RPM without making it semi-permanent
[jro@localhost ~]$ rpm -qa --queryformat "%{NAME}\n" | head -3
libgcc
filesystem
glibc-common
[jro@localhost ~]$ rpm -qa --queryformat "%{NAME}_%{VERSION}\n" | head -3
libgcc_3.4.6
filesystem_2.3.0
glibc-common_2.3.4
[jro@localhost ~]$ rpm -qa --queryformat "%{NAME}_%{VERSION}_%{DISTRIBUTION}\n" | head -3
libgcc_3.4.6_Red Hat (RHEL-4)
filesystem_2.3.0_Red Hat Linux
glibc-common_2.3.4_Red Hat (RHEL-4)
It’s not super intuitive, but thankfully there’s some info in the rpm man page, and it can be handy when writing scripts to report on your packages, create lists to mirror systems from, etc.
Resources
- The RPM Guide at The Fedora Project - This used to be a book that’s no longer in print. This is the best resource outside of looking at what other people have done.
- The RPM HOWTO at The Linux Documentation Project - It’s a bit dated but there’s still some relevant information there.
- RPM.org wiki - Links to other resources.