1. Overview

RPM is a package management system used in several Linux distributions. It stands for Red Hat Package Manager. We can install RPM packages using the rpm command.

Sometimes, we may need to extract the contents of a package to a local directory. In this tutorial, we’ll discuss how to extract the contents of an RPM package without installing it.

2. The cpio and rpm2cpio Commands

The rpm command has many options to build, install, update, verify, query, and erase RPM packages. However, it doesn’t have an option for extracting the contents of a package without installing it.

An RPM package contains a cpio archive. This archive consists of the files in the package. In addition to the cpio archive, the package also has an RPM header containing the metadata information.

We’ll use the cpio and rpm2cpio commands to extract an RPM package without installation.

First, let’s understand each command separately.

2.1. The cpio Command

cpio is a tool for copying files to or from an archive file. Its name stands for “copy in and out”.

It supports several archive formats such as bin, crc, old tr, and POSIX.1 tar. It isn’t used as widely as the tar command, but it is useful for our purpose as RPM uses it.

We use the -o option of cpio to create an archive file:

$ pwd
/home/alice/work
$ ls
$ touch file1 file2
$ mkdir out_directory
$ ls
file1 file2 out_directory
$ ls file* | cpio –o > archive.cpio
1 block
$ ls
archive.cpio file1 file2 out_directory

We first created two files, file1 and file2, in the /home/alice/work directory using touch file1 file2. Similarly, we created a directory, out_directory, using mkdir out_directory. Finally, we created the archive file, archive.cpio, by using ls file* | cpio -o > archive.cpio. We passed the output of the ls file* command, namely file1 and file2, to the cpio command using a pipe. The command cpio -o > archive.cpio added file1 and file2 to the archive file archive.cpio.

Now, we’ll extract the contents of the archive file to out_directory. We use the -i option of cpio to extract the archive file:

$ cpio –D out_directory –i < archive.cpio
1 block
$ ls out_directory/
file1 file2

The -D option of cpio specifies the directory into which we want to extract the contents of the archive file. We successfully extracted the contents of the archive file to out_directory.

2.2. The rpm2cpio Command

rpm2cpio extracts the cpio archive within an RPM package. Let’s use it for the RPM package file, iperf3-3.5-6.el8.x86_64.rpm:

$ pwd
/home/alice/work
$ ls
iperf3-3.5-6.el8.x86_64.rpm
$ rpm2cpio iperf3-3.5-6.el8.x86_64.rpm > iperf3.cpio
$ ls
iperf3-3.5-6.el8.x86_64.rpm iperf3.cpio

We passed iperf3-3.5-6.el8.x86_64.rpm as an argument to rpm2cpio. The > iperf3.cpio part of the command just directed the output to the cpio file iperf3.cpio.

2.3. Using cpio and rpm2cpio Together

Before extracting the contents of the RPM package iperf3-3.5-6.el8.x86_64.rpm, let’s inspect it using the rpm command:

$ rpm –ql iperf3-3.5-6.el8.x86_64.rpm
/usr/bin/iperf3
/usr/lib/.build_id
/usr/lib/.build_id/4b
/usr/lib/.build_id/4b/b84b4b8c5dc25f1aec204287149d0ff186a181
/usr/lib/.build_id/c9
/usr/lib/.build_id/c9/8a6bb3a2169d18cdea91ef96364bb3651a11cf
/usr/lib64/libiperf.so.0
/usr/lib64/libiperf.so.0.0.0
/usr/share/doc/iperf3
/usr/share/doc/iperf3/LICENSE
/usr/share/doc/iperf3/README.MD
/usr/share/doc/iperf3/RELEASE_NOTES
/usr/share/man/man1/iperf3.1.gz
/usr/share/man/man3/libiperf.3.gz

The -q option of rpm specifies that we want to use rpm for a query. The -l option, on the other hand, requests to list the files in the package. The output shows that the files in the package will be installed in several directories if we install the package using rpm. For example, the utility iperf3 will be installed to /usr/bin.

Now, let’s extract its contents using rpm2cpio and cpio. As we saw in the previous sections, we can first extract the cpio archive from the RPM package file using rpm2cpio. Then, we can extract the cpio archive file using cpio:

$ rpm2cpio iperf3-3.5-6.el8.x86_64.rpm > iperf3.cpio
$ cpio –idmv < iperf3.cpio
./usr/bin/iperf3
./usr/lib/.build_id
./usr/lib/.build_id/4b
./usr/lib/.build_id/4b/b84b4b8c5dc25f1aec204287149d0ff186a181
./usr/lib/.build_id/c9
./usr/lib/.build_id/c9/8a6bb3a2169d18cdea91ef96364bb3651a11cf
./usr/lib64/libiperf.so.0
./usr/lib64/libiperf.so.0.0.0
./usr/share/doc/iperf3
./usr/share/doc/iperf3/LICENSE
./usr/share/doc/iperf3/README.MD
./usr/share/doc/iperf3/RELEASE_NOTES
./usr/share/man/man1/iperf3.1.gz
./usr/share/man/man3/libiperf.3.gz
463 blocks

We used several new options of cpio. The -d option specifies to create the leading directories if needed. For example, it created the usr directory and its subdirectories in the current working directory.

The -m option lets us preserve the modification times of the files in the package. Otherwise, the files have the extraction time of the package as the modification times.

Finally, the -v option is for listing the processed files during extraction.

Now, we have all the files in the package extracted to the usr directory in the current working directory.

Instead of extracting the package in two steps, we can do it once using a pipe:

$ rpm2cpio iperf3-3.5-6.el8.x86_64.rpm | cpio –idmv
./usr/bin/iperf3
./usr/lib/.build_id
./usr/lib/.build_id/4b
./usr/lib/.build_id/4b/b84b4b8c5dc25f1aec204287149d0ff186a181
./usr/lib/.build_id/c9
./usr/lib/.build_id/c9/8a6bb3a2169d18cdea91ef96364bb3651a11cf
./usr/lib64/libiperf.so.0
./usr/lib64/libiperf.so.0.0.0
./usr/share/doc/iperf3
./usr/share/doc/iperf3/LICENSE
./usr/share/doc/iperf3/README.MD
./usr/share/doc/iperf3/RELEASE_NOTES
./usr/share/man/man1/iperf3.1.gz
./usr/share/man/man3/libiperf.3.gz
463 blocks

This is the preferred solution as there’s no need for an intermediate cpio file like iperf3.cpio.

Therefore, we were able to extract the contents of an RPM package locally without installing it.

3. Using the Extracted Package

Having extracted the package in the previous section, we’ll try to use it now. However, a question might arise here. If we wanted to use a package, we could install it using rpm. Why do we need to extract it to a local directory?

An answer to this question might be to test the locally extracted package without affecting other users. We may want to test a package first in our local directory. Later, we may install it with rpm if we’re satisfied with the test results and we want it available to every user.

Therefore, let’s run the extracted iperf3 command. It’s a tool for performing network throughput tests:

$ pwd
/home/alice/work
$ ./usr/bin/iperf3 –s
./usr/bin/iperf3: error while loading shared libraries: libiperf.so.0: cannot open shared object file: No such file or directory

We tried to run the tool as a server using its -s option. However, we got an error. It couldn’t load the shared library libiperf.so.0. This is also one of the extracted files in the package.

One solution is to set LD_PRELOAD to the path of the shared library before running the utility:

$ LD_PRELOAD=/home/alice/work/usr/lib64/libiperf.so.0 ./usr/bin/iperf3 –s
----------------------------------------------------------
Server listening on 5201
----------------------------------------------------------

We were successful in running iperf3 this time. LD_PRELOAD lets us load the specified libraries before any other libraries.

Another method might be adding the path of the required shared library to the LD_LIBRARY_PATH environment variable:

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/alice/work/usr/lib64
$ ./usr/bin/iperf3
----------------------------------------------------------
Server listening on 5201
----------------------------------------------------------

We appended the path of the shared library to the existing LD_LIBRARY_PATH using the command export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/alice/work/usr/lib64/. We were successful in running iperf3 again.

In summary, we may need to set the environment accordingly to use the software extracted to a local directory.

4. Conclusion

In this article, we discussed how to extract the contents of an RPM package without installation.

Firstly, we discussed the cpio and rpm2cpio commands. We saw that cpio is a tool for creating and extracting an archive file of several archive types. It’s especially useful if we’re dealing with an RPM package as RPM uses it. rpm2cpio is useful for extracting a cpio archive from an RPM package.

Secondly, we discussed how we could use these two commands together to extract the contents of a package without installing it.

Finally, we discussed a few points about how to use a locally extracted package.


« 上一篇: 理解SSHFS