Perl 的 system() 的使用

28 August 2013

Perl 语言 system 函数。

官方文档,点这里,或者终端执行:

1
perldoc -f system

如果只是用 system 来简单地执行终端命令很简单,就不多说了。想说说其返回值的使用。因为在严谨的程序中,要考虑执行失败的情况,或者使用失败原因来控制流程。最近在做的测试框架就用到了这点。

简单来说,Perl 的 system 与 C 标准库的 system 是相似的。稍微复杂了一点。

(1)单个参数且不是数组的情况。未必会通过 shell 来运行其参数。要看这个参数里有无 shell 的元字符(美元符号,分好,竖线(管道)等),如果没有,则通过 shell 来运行,否则直接通过 execvp 函数(效率较高)。

A:内部实现时不通过 shell 的情况:

1
2
my $command "ifconfig";
my $ret = system($command);

B:由 shell 来执行 $command :

1
2
my $command "ifconfig | grep inet";
my $ret = system($command);

下面重点说说 system 的返回值。先说 B ,这个和 C 的 system 是一样的。成功返回 0。无法执行返回 -1。如果 shell 运行失败则返回 127(例如命令不存在)。其他情况返回整个 command 的退出值。当然,这里说的返回值并不是 $ret ,而是处理过的 $ret。对于 C 使用 WEXITSTATUS() 宏,而对于 Perl ,直接右移 8 位。这是因为 Perl 使用了低 8 位来记录中止执行的信号和是否 coredump 的信息。

1
my $exit_code $ret >> 8;

对于 A 的情况,如果 $command 实际是系统没有的命令,就会返回 -1。这是一个很大的缺陷。因为命令不存在或者写错命令的情况很经常发生。这时应该能够准确地提醒用户。不过有一个小技巧,就是给 command 加一个分号。使得 Perl 通过 shell 来运行该命令,而不是 execvp 函数。

1
2
my $command "ifconfig | grep inet";
my $ret system("$command;");

(2)参数为数组或者有个多个参数的情况。如果数组只有一个元素,情况和(1)一样。剩下的情况都不会通过 shell 来运行命令。这就和 exec 函数有点像了。

 

2013-08-28-杰良

上一篇: 打开思路,寻找解决问题的办法

下一篇: 格雷厄姆的《Writing and Speaking》