我有一个 perl 脚本,希望可以在没有安装 perl 解释器的系统上使用(例如 Linux 容器)。我使用 PAR::Packer 生成了一个二进制文件,一切似乎都运行良好。
[0] [ishpeck@centbox03 /tmp/examply]$ file ./perlthing/scripts/hello.pl
./perlthing/scripts/hello.pl: Perl script, ASCII text executable
[0] [ishpeck@centbox03 /tmp/examply]$ cat ./perlthing/scripts/hello.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
print "Hello, world!\n"
[0] [ishpeck@centbox03 /tmp/examply]$ cat Makefile
CURDIR=/tmp/examply
TOPDIR=$(CURDIR)/packaging
rpm: perlbin
sh -c 'for x in packaging/BUILD packaging/RPMS/x86_64 packaging/RPMS/x86 packaging/RPMS/arm packaging/SOURCES packaging/SPECS packaging/SRPMS; do mkdir -p $$x; done'
rpmbuild --target x86_64 -bb $(TOPDIR)/SPECS/mypackage.spec --define '_topdir $(TOPDIR)' --define '_arch x86_64' --define '_working_dir $(CURDIR)'
perlbin: perlthing/binaries/hello.pl
perlthing/binaries/hello.pl: perlthing/scripts/hello.pl Makefile
/usr/local/bin/pp -M File::** -M PAR:: --clean --verbose=2 --output=$@ $<
clean:
rm perlthing/binaries/hello.pl
[0] [ishpeck@centbox03 /tmp/examply]$ make perlbin >/dev/null ; echo $?
0
[0] [ishpeck@centbox03 /tmp/examply]$ file perlthing/binaries/hello.pl
perlthing/binaries/hello.pl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=7d5b38a792018d0202a96ce8645b00591e7ea7c5, stripped
[0] [ishpeck@centbox03 /tmp/examply]$ ./perlthing/binaries/hello.pl
Hello, world!
到目前为止一切顺利。当我将二进制文件复制到没有 perl 解释器的机器上时,它甚至可以工作:
core@CoreOS-1 ~ $ which perl
which: no perl in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin)
core@CoreOS-1 ~ $ ./hello.pl
Hello, world!
我想将其打包成 RPM:
[0] [ishpeck@centbox03 /tmp/examply]$ cat packaging/SPECS/mypackage.spec
Name: ishy-mypackage
Version: 0.1
Release: 1%{?dist}
Summary: My example package
License: MIT
URL: http://ishpeck.net
%description
This is my example package that includes a perl script bundled as a binary via PAR::Packer
%prep
echo "Prepare scriptlet is empty"
%build
echo "Nothing really to do"
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/local/bin/
cp %{_working_dir}/perlthing/binaries/hello.pl $RPM_BUILD_ROOT/usr/local/bin/
%files
/usr/local/bin/hello.pl
[0] [ishpeck@centbox03 /tmp/examply]$ grep rpmbuild Makefile
rpmbuild --target x86_64 -bb $(TOPDIR)/SPECS/mypackage.spec --define '_topdir $(TOPDIR)' --define '_arch x86_64' --define '_working_dir $(CURDIR)'
[0] [ishpeck@centbox03 /tmp/examply]$ make
但是当我安装该包时,perl 二进制文件不再起作用了!
[0] [ishpeck@centbox03 /tmp/examply]$ sudo rpm -i ./packaging/RPMS/x86_64/ishy-mypackage-0.1-1.el7.x86_64.rpm
[0] [ishpeck@centbox03 /tmp/examply]$ which hello.pl
/usr/local/bin/hello.pl
[0] [ishpeck@centbox03 /tmp/examply]$ hello.pl
Usage: /usr/local/bin/hello.pl [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ]
/usr/local/bin/hello.pl [ -B|-b ] [-Ooutfile] src.par
Removing files in "/tmp/par-6973687065636b/temp-51174"
Undefined subroutine &File::Find::finddepth called at -e line 11.
END failed--call queue aborted at -e line 616.
我不认为这是我使用方式的问题页生成二进制文件,因为如果我直接复制它,它似乎可以在任何地方工作。我的大脑想把责任归咎于(我如何使用)rpm构建但我甚至不知道从哪儿开始。
我是否遗漏了一些有关 rpmbuild 的神秘细节?
答案1
rpmbuild 正在剥离它
默认的 rpmbuild 宏包含strip
干扰 PAR::Packer 所执行的任何魔法操作的命令。
如果它使用你的源代码,我可以在 CentOS 7、perl v5.16.3 上重现该问题。将其添加到你的规范顶部:
%global __os_install_post %{nil}
buildroot 中的二进制文件未经修改,程序可以运行。我不太清楚为什么,你可能需要询问 Perl rpm 维护者或其他 Perl 黑客以了解详细信息。
性能侧栏
我注意到,与实际的 perl 解释器相比,打包的二进制文件的速度始终慢了 100 倍。对于非平凡的程序,这种差异可能不那么明显。即使是这个平凡的构建,大小也只有 4 MB。
我很欣赏瑞士军用电锯对于未开化的发行版,但请注意,本机二进制文件不太可能提高性能。