如何提取rpm文件的内容?

195

我有一个rpm包,想要像对待tarball一样处理它。我希望将其内容提取到一个目录中,以便检查内容。我熟悉未安装软件包的查询命令。我不仅仅需要列出rpm包的内容。

$ rpm -qpl foo.rpm

我想检查rpm中包含的多个文件的内容。我不想安装rpm。我也知道rpm在%post部分进行其他修改的能力,以及如何检查这些修改。例如:

$ rpm -qp --scripts foo.rpm

然而在这种情况下,那对我来说并不重要。

19个回答

235

你尝试过使用rpm2cpio命令吗?请参考以下示例:

$ rpm2cpio php-5.1.4-1.esp1.x86_64.rpm | cpio -idmv

/etc/httpd/conf.d/php.conf  
./etc/php.d  
./etc/php.ini  
./usr/bin/php  
./usr/bin/php-cgi  
etc 

41
我很惊讶Linux发行版没有提供一个包装器可执行文件来使这个过程更容易(例如rpmextract bla.rpm),因为这是一个非常常见的操作。用户不应该需要关心中间的cpio格式。 - Alan Evangelista
3
不要惊讶,@AlanEvangelista,这是很常见的事情。 - ngreen
15
我很惊讶rpm格式如此糟糕。与像deb这样的其他格式相比,后者只是简单地遵循UNIX哲学的归档文件。 - Trismegistos
7
在我的情况下,我使用这个命令时遇到了“cpio: Malformed number”错误。对我有用的是运行“rpm2archive xorg-x11-server-1.20.11-1.fc33.src.rpm”,然后使用“tar -xzvf xorg-x11-server-1.20.11-1.fc33.src.rpm.tgz”将其解压缩到当前目录中。 - Hi-Angel
4
@Hi-Angel这是因为RHEL 9使用了有效载荷压缩(zstd),我添加了一个答案,这是另一种提取它的方法: rpm2cpio foo.rpm | zstd -d | cpio -idmv - G. C.
显示剩余6条评论

90
$ mkdir packagecontents; cd packagecontents
$ rpm2cpio ../foo.rpm | cpio -idmv
$ find . 

供参考:cpio 参数为:

-i = extract
-d = make directories
-m = preserve modification time
-v = verbose

我在这里找到了答案:lontar的回答


2
"rpm2cpio foo.rpm | cpio -idmv" 对我来说很有效。它足以在当前路径下提取rpm的内容。 - parasrish

38
对于那些没有 rpm2cpio 的人,这里提供一个古老的 rpm2cpio.sh 脚本,它可以从 *.rpm 包中提取有效载荷。
为了保存和传承,我们重新发布这个脚本。
使用方法如下: ./rpm2cpio.sh .rpm | cpio -dimv
#!/bin/sh

pkg=$1
if [ "$pkg" = "" -o ! -e "$pkg" ]; then
    echo "no package supplied" 1>&2
    exit 1
fi

leadsize=96
o=`expr $leadsize + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "sig il: $il dl: $dl"

sigsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $sigsize + \( 8 - \( $sigsize \% 8 \) \) \% 8 + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "hdr il: $il dl: $dl"

hdrsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $hdrsize`
EXTRACTOR="dd if=$pkg ibs=$o skip=1"

COMPRESSION=`($EXTRACTOR |file -) 2>/dev/null`
if echo $COMPRESSION |grep -q gzip; then
        DECOMPRESSOR=gunzip
elif echo $COMPRESSION |grep -q bzip2; then
        DECOMPRESSOR=bunzip2
elif echo $COMPRESSION |grep -iq xz; then # xz and XZ safe
        DECOMPRESSOR=unxz
elif echo $COMPRESSION |grep -q cpio; then
        DECOMPRESSOR=cat
else
        # Most versions of file don't support LZMA, therefore we assume
        # anything not detected is LZMA
        DECOMPRESSOR=`which unlzma 2>/dev/null`
        case "$DECOMPRESSOR" in
            /* ) ;;
            *  ) DECOMPRESSOR=`which lzmash 2>/dev/null`
             case "$DECOMPRESSOR" in
                     /* ) DECOMPRESSOR="lzmash -d -c" ;;
                     *  ) DECOMPRESSOR=cat ;;
                 esac
                 ;;
        esac
fi

$EXTRACTOR 2>/dev/null | $DECOMPRESSOR

我在使用Alpine Linux时遇到了“unlzma: bad lzma header”错误。尝试了多个RPM包,但问题依旧存在。 - jekennedy

32

有时你可能会遇到中间RPM存档的问题:

cpio:格式错误的数字
cpio:格式错误的数字
cpio:格式错误的数字
. . .
cpio:存档过早结束

这意味着它可能已被打包,如今通常使用LZMA2压缩,由xz执行:

rpm2cpio <file>.rpm | xz -d | cpio -idmv

否则,您可以尝试:

rpm2cpio <file>.rpm | lzma -d | cpio -idmv

2
非常有用。谢谢您,先生! - ILIV
1
救命稻草。@LasseHalbergHaarbye 我已将其添加到被接受的答案中。 - Joseph Farah
我曾经遇到“格式错误的数字”和“归档文件过早结束”的错误,但是贴出来的解决方案都没有起作用。我不得不使用rpm2cpio <file>.rpm | bsdtar -xf -(没有cpio)才能解决问题。 - jackkamm
1
中间存档文件以gzip格式结束,因此我使用了gunzip而不是xzlzma,这很好地解决了问题。 - jayhendren
2
对于更新的软件包(RHEL 9),请使用 zstd -d,例如:rpm2cpio <file>.rpm | zstd -d | cpio -idmv - Andrea Di Stefano

13

大多数发行版都安装了GUI应用程序 file-roller,它可以解压tar、zip、rpm等多种格式的文件。

file-roller --extract-here package.rpm

这将提取当前目录中的内容。


7

7-zip 能够支持大多数归档文件的解压,包括rpm和其内置的cpio格式。


我已经尝试过使用7 zip,而且它完美地运行了。 - Anshul Singhal

6
您可以直接使用命令 tar -xvf <rpm 文件>

1
无法使用.rpm软件包重现该问题。您可能需要更正您的答案。 - gvlasov
11
这适用于OS X或任何使用libarchive作为核心的tar变体的系统。 - Glenjamin
4
我收到了错误提示:这似乎不是一个tar归档文件。 - hostingutilities.com
这对我在MacOS 10.14.1上使用bsdtar 2.8.3 - libarchive 2.8.3有效。这可能取决于所使用的压缩类型。rpm2cpio.sh脚本似乎会检查多种压缩类型,然后将其传递给正确的工具进行提取。 - 2xj
1
由于SO的编辑功能不允许我添加3个字符来修复答案,因此应该补充说明这需要使用libarchive的bsdtar。Mac上的Homebrew默认将tar链接到它,但在其他操作系统上,tar表示GNU tar。 - Atemu

6

5

强大的基于文本的文件管理器mc(午夜指挥官,模糊地提醒着旧版DOS时代的Norton指挥官)具有内置的检查和解压.rpm和.rpms文件的功能,只需在mc中“打开”.rpm(s)文件并选择CONTENTS.cpio:对于.rpm,您可以访问安装树,对于.rpms,您可以访问.spec文件和所有源包。


4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接