【问题标题】:Is it possible to use array version of Perls system function to return immediately?是否可以使用数组版本的 Perls 系统函数立即返回?
【发布时间】:2015-01-24 03:49:58
【问题描述】:

是否可以使用 perls system 命令的数组版本(即,将第一个元素作为命令,将数组的其余部分作为 cmd 参数的版本),同时还可以使用 Linux 生成一个新进程,以便system 命令立即返回,例如运行如下命令:

mycmd arg1 arg2 &

我尝试过使用 system( ('mycmd', 'arg1', 'arg2', '&') ),但它只是将 & 符号从字面上解释为第三个参数。

我知道我可以将整个命令作为标量传递给system,但我特别想知道是否可以使用数组版本,因为此命令的参数将来自 CGI 脚本中的用户选项。

【问题讨论】:

  • system 派生一个新进程并在那里执行你的 shell 命令。您在 shell 命令中传递的任何参数都会在这个其他进程中执行,因此您可以传递 & 以使其在后台工作;这确实是另一个进程的背景,而不是您当前的进程。

标签: linux perl


【解决方案1】:

shell 命令的& 部分告诉shell 在后台运行进程,因此使用system 的多参数形式绕过shell 是没有意义的。

解决方案 1:使用 String::ShellQuote 引用。

use String:ShellQuote qw( shell_quote );
system(shell_quote('mycmd', 'arg1', 'arg2').' &');

解决方案 2:使用 shell 插值引用。

system('sh', '-c', '"$@" &', 'sh', 'mycmd', 'arg1', 'arg2');

解决方案 3:自己在后台启动程序。

use IPC::Open3 qw( open3 );

{
   open(local *CHILD_IN, '<', '/dev/null') or die $!;
   local $SIG{CHLD} = 'IGNORE';
   open3(
      '<&CHILD_IN', '>&STDOUT', '>&STDERR',
      'mycmd', 'arg1', 'arg2',
   );
}

【讨论】:

  • 这些解决方案都不适合我。我可以运行该命令,它确实会立即返回,但脚本最后仍会等待底层命令完成。我发布了一个单独的问题,希望更合适:stackoverflow.com/questions/28126351/…
  • 我意识到我的问题不只是 Perl 问题,因为如果我直接从终端运行我的 perl 脚本,这里的解决方案就可以工作。尽管我的 Web 服务器和 CGI​​ 脚本设置会导致“某些事情”等到底层系统命令完成后再返回对 Web 请求的响应,这就是另一个 Q 的含义。
【解决方案2】:

由于您对执行程序的命运不感兴趣,您可以使用 fork/exec。而你在 Linux 上,它允许使用 $SIG{CHLD} = 'IGNORE' 来避免等待子进程。

sub background { 
    local $SIG{CHLD} = 'IGNORE';
    # fork and then exec if we are the child
    exec(@_) or die($!) unless fork; 
}
background( 'mycmd', 'arg1', 'arg2' );

【讨论】:

  • 这个解决方案对我不起作用。我可以运行该命令,它确实会立即返回,但脚本最后仍会等待底层命令完成。我发布了一个单独的问题,希望更合适:stackoverflow.com/questions/28126351/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多