为什么安装带有 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