为什么安装带有 perl 模块的程序硬编码 perl 版本?
Why installed programs with perl modules hardcode perl version?
当我们安装模块时,该模块可以发送安装到 local/bin
目录中的可执行文件。
如果我们窥探已安装的脚本,我们会注意到 perl 版本是硬编码的:
/home/user/t/local/bin/mojo
#!/home/user/perl5/perlbrew/perls/perl-5.35.1/bin/perl5.35.1
为什么perl版本是硬编码的?
我希望它应该是 /usr/bin/env perl
:
$ which cpanm
/home/user/perl5/perlbrew/bin/cpanm
$ cat $(which cpanm) | less
#!/usr/bin/env perl
I expect it should be /usr/bin/env perl:
在这种情况下,它将采用当前路径中的 Perl 安装。与用于安装应用程序模块的安装相比,这可能是一个不同的 Perl 安装。在这种情况下 运行ning 应用程序可能会由于缺少模块而失败。或者它可能会显示奇怪的行为,因为安装的模块的版本与应用程序预期的版本不同,因此可能会显示不同的行为。
例如,假设您的系统中安装了两个 perl。当您使用第一个 perl 安装脚本时,您不能 运行 使用第二个 perl,因为第二个 perl 缺少第一个可用的模块。
它应该有安装它的 Perl 的路径。
- 这是
perl
已安装其依赖项。
- 这是测试过的
perl
。
如果像您建议的那样使脚本依赖于环境,它可能会选择不同的 perl
,这很可能会导致它失败。
例如,让我们使用一个 shebang 行为
的工具
#!/home/ikegami/usr/perlbrew/perls/5.34.0t/bin/perl -w
无论环境如何,都可以正常工作。
$ /home/ikegami/usr/perlbrew/perls/latest/bin/tpage \
--define USER=World \
<<<'Hello, [% USER %]!'
Hello, World!
现在让我们模拟以下 shebang 行:
#!/usr/bin/env perl -w
尽管正确安装了工具,但它还是失败了。
$ /usr/bin/env perl -w /home/ikegami/usr/perlbrew/perls/latest/bin/tpage \
--define USER=World \
<<<'Hello, [% USER %]!'
Can't locate Template.pm in @INC (you may need to install the Template module) (@INC contains: /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/site_perl/5.28.2/x86_64-linux-thread-multi /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/site_perl/5.28.2 /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/5.28.2/x86_64-linux-thread-multi /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/5.28.2) at /home/ikegami/usr/perlbrew/perls/latest/bin/tpage line 27.
BEGIN failed--compilation aborted at /home/ikegami/usr/perlbrew/perls/latest/bin/tpage line 27.
这是一个受远距离影响的不可靠解决方案。出于同样的原因,我们将变量范围化,我们应该避免 env
.
自包含脚本的情况有所不同,但是不会使用 ExtUtils::MakeMaker 或 Module::Build(设置 shebang 行的模块)安装自包含脚本,因此此类脚本与此处无关。
似乎我的问题的正确问题是:How to prevent perl from hard coding its version at shebang?
TLDR;
export PERL_MM_SHEBANG=relocatable
阅读@Håkon Hægland 的文章后建议阅读 #38
现在我看到有两种情况:
- 当脚本安装到系统中时
- 当脚本安装到应用程序
local/bin
目录时。
我的情况是第二。
所以对于这种情况,当我将当前 perl 设置为路径
时,我应该同时将环境变量 PERL_MM_SHEBANG
设置为 relocatable
此 env 变量已实现 here
当我们安装模块时,该模块可以发送安装到 local/bin
目录中的可执行文件。
如果我们窥探已安装的脚本,我们会注意到 perl 版本是硬编码的:
/home/user/t/local/bin/mojo
#!/home/user/perl5/perlbrew/perls/perl-5.35.1/bin/perl5.35.1
为什么perl版本是硬编码的?
我希望它应该是 /usr/bin/env perl
:
$ which cpanm
/home/user/perl5/perlbrew/bin/cpanm
$ cat $(which cpanm) | less
#!/usr/bin/env perl
I expect it should be /usr/bin/env perl:
在这种情况下,它将采用当前路径中的 Perl 安装。与用于安装应用程序模块的安装相比,这可能是一个不同的 Perl 安装。在这种情况下 运行ning 应用程序可能会由于缺少模块而失败。或者它可能会显示奇怪的行为,因为安装的模块的版本与应用程序预期的版本不同,因此可能会显示不同的行为。
例如,假设您的系统中安装了两个 perl。当您使用第一个 perl 安装脚本时,您不能 运行 使用第二个 perl,因为第二个 perl 缺少第一个可用的模块。
它应该有安装它的 Perl 的路径。
- 这是
perl
已安装其依赖项。 - 这是测试过的
perl
。
如果像您建议的那样使脚本依赖于环境,它可能会选择不同的 perl
,这很可能会导致它失败。
例如,让我们使用一个 shebang 行为
的工具#!/home/ikegami/usr/perlbrew/perls/5.34.0t/bin/perl -w
无论环境如何,都可以正常工作。
$ /home/ikegami/usr/perlbrew/perls/latest/bin/tpage \
--define USER=World \
<<<'Hello, [% USER %]!'
Hello, World!
现在让我们模拟以下 shebang 行:
#!/usr/bin/env perl -w
尽管正确安装了工具,但它还是失败了。
$ /usr/bin/env perl -w /home/ikegami/usr/perlbrew/perls/latest/bin/tpage \
--define USER=World \
<<<'Hello, [% USER %]!'
Can't locate Template.pm in @INC (you may need to install the Template module) (@INC contains: /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/site_perl/5.28.2/x86_64-linux-thread-multi /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/site_perl/5.28.2 /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/5.28.2/x86_64-linux-thread-multi /home/ikegami/usr/perlbrew/perls/5.28.2t/lib/5.28.2) at /home/ikegami/usr/perlbrew/perls/latest/bin/tpage line 27.
BEGIN failed--compilation aborted at /home/ikegami/usr/perlbrew/perls/latest/bin/tpage line 27.
这是一个受远距离影响的不可靠解决方案。出于同样的原因,我们将变量范围化,我们应该避免 env
.
自包含脚本的情况有所不同,但是不会使用 ExtUtils::MakeMaker 或 Module::Build(设置 shebang 行的模块)安装自包含脚本,因此此类脚本与此处无关。
似乎我的问题的正确问题是:How to prevent perl from hard coding its version at shebang?
TLDR;
export PERL_MM_SHEBANG=relocatable
阅读@Håkon Hægland 的文章后建议阅读 #38
现在我看到有两种情况:
- 当脚本安装到系统中时
- 当脚本安装到应用程序
local/bin
目录时。
我的情况是第二。
所以对于这种情况,当我将当前 perl 设置为路径
时,我应该同时将环境变量PERL_MM_SHEBANG
设置为 relocatable
此 env 变量已实现 here