The exec
函数执行系统命令并且永远不会返回; 如果您希望它返回,请使用 system
而不是 exec
。 它只在命令不存在并且直接执行而不是通过系统的命令 shell 执行时才会失败并返回 false(见下文)。
由于使用 exec
而不是 system
是一个常见的错误,因此如果 exec
在空上下文调用,并且后面跟着一个不是 die
、warn
或 exit
的语句,Perl 会发出警告(如果启用了 警告 - 但您总是这样做,对吧?)。 如果您真的想在 exec
后面跟着其他语句,可以使用以下几种风格来避免警告
exec ('foo') or print STDERR "couldn't exec foo: $!";
{ exec ('foo') }; print STDERR "couldn't exec foo: $!";
如果 LIST 中有多个参数,则调用 execvp(3),并将 LIST 中的参数传递给它。如果 LIST 中只有一个元素,则会检查该参数是否包含 shell 元字符。如果有,则将整个参数传递给系统的命令 shell 进行解析(在 Unix 平台上,这是 /bin/sh -c
,但在其他平台上可能有所不同)。如果参数中没有 shell 元字符,则将其拆分为单词并直接传递给 execvp
,这更有效。示例
exec '/bin/echo', 'Your arguments are: ', @ARGV;
exec "sort $outfile | uniq";
如果您不想真正执行第一个参数,而是想对您正在执行的程序撒谎,告诉它自己的名称,您可以将您实际要运行的程序指定为“间接对象”(没有逗号)放在 LIST 的前面,例如 exec PROGRAM LIST
。(这始终强制将 LIST 解释为多值列表,即使列表中只有一个标量。)示例
my $shell = '/bin/csh';
exec $shell '-sh'; # pretend it's a login shell
或者,更直接地说:
exec {'/bin/csh'} '-sh'; # pretend it's a login shell
当参数通过系统 shell 执行时,结果会受到其怪癖和功能的影响。有关详细信息,请参阅 perlop 中的“`STRING`”。
使用间接对象与 exec
或 system
也是更安全的。这种用法(也适用于 system
)强制将参数解释为多值列表,即使列表只有一个参数。这样,您就可以免受 shell 展开通配符或将包含空格的单词拆分的困扰。
my @args = ( "echo surprise" );
exec @args; # subject to shell escapes
# if @args == 1
exec { $args[0] } @args; # safe even with one-arg list
第一个版本,没有间接对象的版本,运行了 echo 程序,并将 "surprise"
作为参数传递给它。第二个版本没有这样做;它试图运行一个名为 "echo surprise" 的程序,但没有找到它,并将 $?
设置为一个非零值,表示失败。
在 Windows 上,只有 exec PROGRAM LIST
间接对象语法才能可靠地避免使用 shell;exec LIST
,即使有多个元素,如果第一个生成失败,也会回退到 shell。
Perl 尝试在 exec 之前刷新所有打开以供输出的文件,但这在某些平台上可能不受支持(请参阅 perlport)。为了安全起见,您可能需要设置 $|
(在 English 中为 $AUTOFLUSH
)或在任何打开的句柄上调用 IO::Handle
的 autoflush
方法,以避免丢失输出。
请注意,exec
不会调用您的 END
块,也不会调用您对象的 DESTROY
方法。
可移植性问题:perlport 中的“exec”。