【问题标题】:Is there any use in providing arguments as separate parameters to a system call using Perl?使用 Perl 将参数作为单独的参数提供给系统调用有什么用?
【发布时间】:2011-04-20 18:20:48
【问题描述】:

在 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
  • ver2ver3有什么区别?

  • 我有什么理由应该使用 ver2ver3 而不是 ver1

  • 它们甚至不支持管道结果,例如,是否有任何 ver2ver3 等效于以下调用?

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

【问题讨论】:

  • closevoter,这不是重复的。至少在打分之前阅读问题。 @PP:你的意思是说它是重复的?
  • 不,我提到了链接,因为问题是相关的。
  • 我在安全一章的Mastering Perl 中解释了很多。不过,这也都在文档中。
  • @brian,你能链接文档的相关部分吗?没有提及here

标签: perl


【解决方案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 处理(见下文),否则您应该向系统传递一个列表。

  • 是否有任何允许管道的版本 2 和版本 3?

不,管道和重定向是由 shell 完成的。您必须使用system 以外的其他内容。你可以用open 来做,但这很麻烦。最简单的方法是使用IPC::Run

use IPC::Run;

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

但实际上,如果您只是 grepping 和计算几行代码,请使用 Perl。

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      $ 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 的实现,它的工作方式相同。其他应用程序可能无法正常工作。

      【讨论】:

        【解决方案4】:

        system 的 Quoth perlfunc:

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

        所以如果$pid 只是数字,那么所有都是等价的。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多