当编写脚本时,#!/usr/bin/perl 和 #!/usr/bin/env perl 有什么区别?

10
显然,这同样适用于将Python、Bash、Sh等替换为Perl!Quentin下面的答案显然是正确的,所以我已经接受了它,但我想知道的实际上是“使用#!来调用解释器运行脚本的两种方法各有什么优缺点?”

这个问题实际上与特定的脚本语言无关,但我将其标记为Perl,因为标题中使用了它作为示例。 - agf
4个回答

13

一个引用了 Perl 安装的常见位置,另一个引用了 env 安装的常见位置,并询问它默认的 Perl 路径是什么。


9

以下是一些好的规则,如果您有充分的理由打破它们,请毫不犹豫地这样做:

尽可能使用#!/usr/bin/env perl来实现不同系统之间的可移植性。但这种方式是愚蠢的,因为它假设位于路径中的 Perl 也总是您想要的 Perl。这并不总是成立,通常在系统上有多个 Perl 时,它们存在于某种特定的原因。

更好的方法是将脚本打包到一个 CPAN-ready 的 distro 中。将这些 distro 分发到希望安装它们的系统中,并按照通常的方式(手动或使用 CPAN 工具链)安装它们,指定完整的路径perlcpan。在此过程中,shebang 行会被重写到正确的 Perl 路径。

示例:

tar -xvf Local-OurCompany-Scripts-1.000.tar.gz
cd Local-OurCompany-Scripts-1.000

## automated installation
/usr/bin/cpan .
# or perhaps
/opt/ourcompany/perls/perl-5.14.2/bin/cpan .

## manual installation
/usr/bin/perl Makefile.PL ; make ; make install
# or perhaps
`which perl5.14.2` Makefile.PL ; make ; make install

2
但是你忘记了,操作路径很容易 - 使用 env 允许你为不同的程序(甚至是同一个程序在不同的时间)使用不同的 Perl。使用硬编码的 Perl 路径和 CPAN 的路径重写能力假定用于安装的 Perl 是你始终想要的 Perl,我认为这比 env 做出的假设更大(也更糟),因为它需要修改源代码才能覆盖它,而不是简单的 "PATH=/path/to/other/perl:$PATH some_perl.pl"。 - Dave Sherohman
我同意这部分内容:“但这是一种愚蠢的方式,因为它假设在路径中排名第一的 Perl 也是你始终想要的 Perl。”并且我会补充说,它还假设你的脚本可以在找到的任何 Perl(和 Perl 模块)实例上正常工作。 - Gonen

5
使用env查找可执行文件,而不是自己查找,会进行额外的exec操作,但大多数情况下这并不重要。它很方便,我经常使用它。
然而,我曾经遇到人们在系统脚本中使用env的问题。有一次,安装了一个/usr/local/bin/perl,导致我的系统出现故障,直到我解决了这个问题才能更新它。另一次,安装了一个/usr/local/bin/python,使我正在使用的ID3标签编辑器出现了问题。我认为这更多是一个打包问题,而不是env本身的问题。如果你在系统上安装某些东西,为什么要仔细检查它是否有满足所有依赖关系的Python版本,如果每次运行时都会寻找任何旧版本的Python呢?

我看不出为什么env应该fork另一个进程。你是指“execs”,还是可以详细说明一下这个主题? - JB.

1

我可以给你一个具体的例子:

假设你在 /opt/(即 XAMPP)中安装了 LAMP 包,其中包括它自己的 perl 可执行文件、库和包管理器。

实际上,你想要运行该可执行文件,因此将 LAMP 可执行文件的路径添加到 PATH 环境变量中(PATH="/opt/XAMPP/bin:$PATH")。

现在,任何使用 "#!/usr/bin/env perl" 的脚本都将执行 LAMP 栈目录中的 perl 二进制文件。另一个路径将执行系统中预安装的 perl 二进制文件,即 "/usr/bin/perl"。

由你决定对于你的 perl 脚本来说哪个更好。


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