【问题标题】:Odd behavior with Perl system() commandPerl system() 命令的奇怪行为
【发布时间】:2012-10-22 10:17:18
【问题描述】:

请注意,我知道这可能不是最好或最优化的方法,但我以前在某个地方遇到过这个问题,我很好奇答案。

我有一个 perl 脚本,它从一个运行并偶尔死掉的 init 中调用。为了快速调试,我整理了一个快速包装 perl 脚本,该脚本基本上由

#$path set from library call.    
while(1){
  system("$path/command.pl " . join(" ",@ARGV) . " >>/var/log/outlog 2>&1");
  sleep 30; #Added this one later. See below...
}

从命令行启动它,它运行良好且符合预期。 command.pl 被调用,脚本基本上停在那里,直到子进程死亡然后再次运行。

但是,当从启动脚本(实际上是通过 start-stop-daemon)调用时,系统命令会立即返回,让 command.pl 继续运行。然后它又转了一圈。一次又一次。 (如果没有 sleep 命令,这并不好玩。)。 ps 显示(许多)command.pl 的父级为 1,而不是包装脚本的 id(当我从命令行运行时)。

有人知道发生了什么吗?

【问题讨论】:

  • 看起来 init 脚本中的某些内容将 & 作为 @ARGV 的一部分传递。这似乎是初始化脚本中的错误,可能是剪切和粘贴错误。接下来我需要弄清楚修复这个是否会破坏其他任何东西(因为 command.pl 本身也做了类似的事情)。

标签: perl system infinite-loop init.d


【解决方案1】:

也许从守护进程运行时,“系统”命令使用的 shell 与您自己运行时使用的 shell 不同。可能守护进程使用的 shell 无法识别 >& 构造。

【讨论】:

  • 乔尔,这是我正在考虑的一件事。我知道 >&1 语法在我第一次开始编写脚本时不可用,所以它可能将其解释为 & 事物。应该注意路径,因为我使用 findbin 生成它(它在同一目录中)。我可以保证程序不会自行分叉。
  • 可能 command.pl 不可执行或不以“#!/usr/bin/perl”开头
  • 你也说你用过 findbin 但我没看到你用 $Bin
  • 对不起,实际代码使用的是 Findbin 之前设置的 $path。验证这是 command.pl 实际上正在运行,因为在添加 sleep() 之前,它的多个实例导致 OOM 错误。
【解决方案2】:

如果适合您,请尝试使用 exec("...") 函数,而不是 system("...")

【讨论】:

    【解决方案3】:

    可能command.pl 没有成功运行。也许文件没有执行权限(你需要说perl command.pl吗?)。也许您正在从与您想象的不同的目录运行命令,并且找不到 command.pl 文件。

    您至少可以检查三件事:

    1. 命令的标准错误输出。现在你通过说2>&1 吞下它。删除该部分并观察system 命令产生的错误。
    2. system 的返回值。该命令可能会运行,system 可能仍会返回退出代码,但如果 system 返回 0,则表明该命令成功。
    3. Perl 的错误变量$!。如果有问题,Perl 会设置$!,这可能有用也可能没用。

    总结一下,试试:

    my $ec = system("command.pl >> /var/log/outlog");
    if ($ec != 0) {
        warn "exit code was $ec, \$! is $!";
    }
    

    更新:如果该命令的多个实例不断出现在您的ps 输出中,那么听起来该程序正在分叉并在后台自行运行。如果这确实是该命令应该执行的操作,那么您想要做的就是在无限循环中运行此命令。

    【讨论】:

      猜你喜欢
      • 2012-04-05
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 2012-06-21
      • 2022-01-05
      • 2015-12-07
      • 2015-01-11
      • 2019-01-18
      相关资源
      最近更新 更多