使用Perl将参数作为单独的参数提供给系统调用是否有用?

时间:2010-10-04 11:22:11

标签: perl

在Unix上,所有这三个都会产生相同的结果

system("top -H -p $pid -n 1");             #ver1
system("top", "H", "p $pid", "n 1");       #ver2
system("top", "-H", "-p $pid", "-n 1");    #ver3
  • ver2 ver3 有什么区别?

  • 有什么理由我应该使用 ver2 ver3 ,而不是 ver1

  • 他们甚至不支持管道结果,例如,是否有以下呼叫的 ver2 ver3 等价物?

    system("top -H -p $pid -n 1 | grep myprocess | wc -l");
    

4 个答案:

答案 0 :(得分:5)

即使它看起来一样也不一样:

$ perl -e 'system("./test.pl -H -p $$ -n 1");system("./test.pl", "H", "p $$", "n 1");system("./test.pl", "-H", "-p $$", "-n 1");'
-H,-p,10497,-n,1
H,p 10497,n 1
-H,-p 10497,-n 1
$ cat ./test.pl 
#!/usr/bin/perl
$\="\n";
$,=",";
print @ARGV;

top实现,它的工作原理相同。其他应用程序可能无法正常工作。

答案 1 :(得分:3)

system的Quoth perlfunc:

  

请注意,参数处理因参数数量而异。如果有多个参数   在LIST中,或者如果LIST是具有多个值的数组,则启动由第一个元素给出的程序   列表其余部分给出的参数列表。如果只有一个标量参数,则检查参数是否为shell元字符,如果有,则将整个参数传递给系统的命令shell进行解析(这在Unix平台上是/ bin / sh -c,但在其他平台)。如果参数中没有shell元字符,它将被拆分为单词并直接传递给execvp,这样效率更高。

因此,如果$pid只是数字,则所有都是等价的。

要插入包含管道的任意shell命令的结果,请使用qx和朋友。

答案 2 :(得分:3)

作为使用LIST的一个实际原因,有时您的命令行参数包含会混淆shell的空格或其他字符。

system("mplayer.exe", "--volume", "75",
       q[C:/Program Files/My Music Player/Music Library/The "Music" Song.mp3]);

答案 3 :(得分:1)

  • ver2和ver3有什么区别?

正是你传递给top的论点。我不知道top的版本会像ps的某些版本那样使用没有短划线的开关,所以你应该使用版本3.

  • 有什么理由我应该使用ver2和ver3,而不是ver1?

如果您将单个字符串传递给system,它将通过您的shell运行它。这意味着它将被shell解释。参数中的任何杂散空格或shell元字符(引号,美元符号等)都将被解释,并可能使事情变得混乱。这也是一个潜在的安全漏洞。

例如,如果$pid类似于'10; echo pwnd; echo ',那么您将运行top -H -p 10,然后echo pwnd,然后echo -n1

因此,为了安全性和安全性,除非您需要shell处理(见下文),否则您应该向系统传递一个列表。

  • 是否有任何ver2和ver3等价物允许使用管道?

不,管道和重定向由shell完成。您必须使用system以外的其他内容。你可以用open做到这一点,但这对屁股很痛苦。最简单的方法是使用IPC::Run

use IPC::Run;

my $out;
run ["echo", "foo\nbar\nbaz"], "|",
    ["grep", "ba"],            "|",
    ["wc",   "-l"],
    \$out;
print $out;  # 2

但实际上,如果你只是在计算一些行,请使用Perl。

my $out;
run ["echo", "foo\nbar\nbaz"], '>', \$out;

my $count = grep { /ba/ } split /\n/, $out;
print $count;