perl
解释shebang本身并模仿exec*(2)
的行为。我认为它模仿了Linux在所有空白上分裂的行为,而不是BSD第一个只有空白的东西,但不要小心。
快速演示really_python.pl
#!/usr/bin/env python
# the following line is correct Python but not correct Perl
from collections import namedtuple
print "hi"
在调用perl really_python.pl
时打印hi。
此外,无论是perl program
还是./program
,以下程序都会做正确的事。
#!/usr/bin/perl
print "hi\n";
和
#!/usr/bin/env perl
print "hi\n";
我不明白为什么程序没有无限循环。在上述任何一种情况下,shebang行都是或解析为perl
解释器的绝对路径。似乎接下来应该发生的事情是perl
解析文件,注意到shebang,并委托shebang路径(在本例中为自己)。 perl
是否将shebang路径与其自己的ARGV[0]
进行比较? perl
是否会查看shebang字符串并查看它是否包含"perl"
作为子字符串?
我尝试使用符号链接来触发我期待的无限循环行为。
$ ln -s /usr/bin/perl /tmp/p
#!/tmp/p
print "hi\n";
但该程序打印了#34; hi"不论它是如何被调用的。
然而,在OS X上,我能够使用脚本将perl
欺骗为无限的shebang循环。
/tmp/pscript
#!/bin/sh
perl "$@"
perl脚本的内容
#!/tmp/pscript
print "hi\n";
这确实是无限循环(在OS X上,尚未在Linux上测试过它)。
perl
在合理的情况下正确处理shebang显然会遇到很多麻烦。它不会被符号链接混淆,也不会被正常的env
内容混淆。到底是做什么的?
答案 0 :(得分:12)
此功能的文档位于perlrun。
如果
#!
行不包含单词“perl”或单词“indir”,则执行以#!
命名的程序而不是Perl解释器。这有点奇怪,但它可以帮助那些没有#!
的机器上的人,因为他们可以告诉程序他们的SHELL是 / usr / bin / perl ,然后Perl会将程序发送给正确的解释器。
因此,如果shebang包含perl
或indir
,则不会执行shebang行的解释器。
Additionally,如果argv[0]
不包含perl
,则不执行shebang行的解释程序。这就是阻止示例中无限循环的原因。
使用perl /tmp/pscript
启动时,
perl /tmp/pscript
,perl
执行/tmp/p /tmp/pscript
。argv[0]
不包含perl
,因此shebang行不再相关。使用/tmp/pscript
启动时,
/tmp/p /tmp/pscript
。argv[0]
不包含perl
,因此shebang行不再相关。答案 1 :(得分:12)
相关代码位于toke.c,即Perl词法分析器。如果:
第1行以#!
开头(可选地以空格开头)AND
不包含perl -
AND
不包含perl
(除非后跟6
,即perl6
)AND
(在" DOSish"平台上)不包含perl
的不区分大小写的匹配(例如Perl
)和
不包含indir
AND
未在命令行AND
-c
标志
argv[0]
包含perl
使用execv
执行shebang之后的程序。否则,词法分析器就会继续; perl并不是exec
本身。
结果,你可以用shebang做一些非常奇怪的事情而不用perl试图exec
另一个翻译:
#! perl
#!foo perl
#!fooperlbar -p
#!perl 6
#!PeRl # on Windows
您的符号链接示例符合上面列出的所有条件,那么为什么没有无限循环?你可以看到strace
:
$ ln -s /usr/bin/perl foo
$ echo '#!foo' > bar
$ strace perl bar 2>&1 | grep exec
execve("/bin/perl", ["perl", "bar"], [/* 27 vars */]) = 0
execve("foo", ["foo", "bar"], [/* 27 vars */]) = 0
Perl实际上会exec
链接,但由于它在名称中不包含perl
,因此第二次不再满足最后一个条件并且循环结束。