【问题标题】:Need to create a orphan process in perl需要在perl中创建一个孤儿进程
【发布时间】:2020-06-04 17:49:36
【问题描述】:

您好,我正在尝试通过分叉子进程来执行代码。

我有使用系统调用的 ruby​​ 代码 a.rb

system("perl abc.pl -subroutine='a' -command='b' -status='c' -logfile='d' -start_datetime='e'")

现在在 abc.pl 我正在这样做

my $pid = fork;
if (!$pid) {
    print "[INFO] in the child process \n ";    
    print "[INFO] forking worked, child process id: ($$) \n";
    while (1) { 
    if ( -d "$ENV{OUT_HOME}" ) {
        print "[INFO] $ENV{OUT_HOME} is available now to write $seq \n";
        open(my $FH,'>',"$ENV{OUT_HOME}/SEQ") or die "cannot open file to write $seq into $ENV{OUT_HOME}/SEQ";
        print $FH "$seq";
        close $FH; 
        print "[INFO] exiting from forked child process id: ($$)  \n";
        exit; # exit the while loop
    } 
    else {
        sleep (2);  
    }
  }
} else {
    print "[INFO] I am parent Process exiting from here \n";
    exit;
}

现在我正在尝试获取不依赖于父进程的子进程(这里是 abc.pl) 当我运行脚本时,它执行正在运行 perl 脚本的系统命令,我看到了 perl 脚本在进程树中。但我一直挂在那里。我不确定为什么父级完成后系统命令不会终止?任何建议或 cmets 表示赞赏。

【问题讨论】:

  • 请提供 ruby​​ 和 perl 的 minimum, reproducible example,并让我们知道您的期望和观察到的内容。例如,当我做ruby -e 'system(*ARGV); puts "bye rb:#{$$}"' perl -E 'sleep 3 unless fork; say "bye pl:$$"' 时……它起作用了!我看到子 perl 退出,父 ruby​​ 退出,以及后来它的“孤立”孙子 perl 退出。不管你有什么问题,我都没有。
  • Re "但我一直挂在那里。我不确定为什么系统命令在 parent 完成后没有终止?",这不太可能。最佳猜测:孩子的 STDIN、STDOUT 或 STDERR 是一个管道,管道另一端的任何进程都在等待它关闭。那是挂着的,不是system
  • 守护进程时,你想做很多事情,包括:双叉,关闭所有句柄,并创建一个新会话。 Daemon::Daemonize 可用于执行此操作。

标签: ruby perl fork orphan-process


【解决方案1】:

您需要为新独立的分叉进程创建一个新的 POSIX 会话。

试试这个(假设环境变量OUT_HOME在调用perl之前已经设置为一个文件夹):

my $pid = fork;
if (!$pid) {
    print "[INFO] in the child process \n ";    
    print "[INFO] forking worked, child process id: ($$) \n";
    require POSIX;
    POSIX::setsid();
    while (1) { 
    if ( -d "$ENV{OUT_HOME}" ) {
        print "[INFO] $ENV{OUT_HOME} is available now to write $seq \n";
        open(my $FH,'>',"$ENV{OUT_HOME}/SEQ") or die "cannot open file to write $seq into $ENV{OUT_HOME}/SEQ";
        print $FH "$seq";
        close $FH; 
        print "[INFO] exiting from forked child process id: ($$)  \n";
        exit; # exit the while loop
    } 
    else {
        sleep (2);  
    }
  }
} else {
    print "[INFO] I am parent Process exiting from here \n";
    exit;
}

【讨论】:

    【解决方案2】:

    perlfaq8 解决了这个问题:

    如何派生一个守护进程?

    如果您所说的守护进程是指一个已分离(与其 tty 解除关联)的进程,则报告以下进程可在大多数 Unixish 系统上运行。非 Unix 用户应该检查他们的 Your_OS::Process 模块是否有其他解决方案。

    打开 /dev/tty 并在其上使用 TIOCNOTTY ioctl。有关详细信息,请参阅 tty(1)。或者更好的是,您可以只使用POSIX::setsid() 函数,因此您不必担心进程组。

    将目录更改为 /

    重新打开 STDIN、STDOUT 和 STDERR,这样它们就不会连接到旧的 tty。

    背景是这样的:

    fork && exit;
    

    CPAN 提供的Proc::Daemon 模块提供了一个函数来为您执行这些操作。

    正如常见问题解答所述,Proc::Daemon 模块可以为您简化此操作,尽管这只是可用于此任务的几个模块之一。

    【讨论】:

      猜你喜欢
      • 2012-10-17
      • 2020-09-09
      • 2014-01-08
      • 2014-12-06
      • 1970-01-01
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      • 2017-01-18
      相关资源
      最近更新 更多