perl fork()exec(),子进程变得狂野

时间:2012-09-26 18:24:40

标签: linux perl process exec fork

我正在使用Linux.sh位于tcsh

我已经制作了一个非常基本的forkexec,但我需要帮助实现安全性。

基本上我的perl脚本在子进程中调用.sh脚本。但当我Ctrl+c杀死父母时,孩子会忽略信号。

1)如何捕获子进程的SIGINT

2)运行.sh脚本的子进程仍然是STDOUT到xterm的屏幕。我该如何删除?我在考虑在后台运行脚本

 exec("shell.sh args &");  

但是我没有经过测试,因为我需要弄清楚如何防止孩子先疯狂。

3)父进程(perl脚本)不等待子进程(.sh脚本)。所以我已经读了很多关于孩子成为僵尸 ???脚本完成后会发生吗?我怎么能阻止它?

$pid = fork();
if($pid < 0){
    print "Failed to fork process... Exiting";
    exit(-1);
    }
elsif ($pid ==0) {
    #child process
    exec("shell.sh args");
    exit(1);
    }
else { #execute rest of parent}

2 个答案:

答案 0 :(得分:10)

  

但是当我按ctrl + c来杀死父母时,孩子会忽略该信号。

信号被发送给父母和孩子两个。

$ perl -E'
   if (my $pid = fork()) {
      local $SIG{INT} = sub { say "Parent got SIGINT" };
      sleep;
      waitpid($pid, 0);
   } else {
      local $SIG{INT} = sub { say "Child got SIGINT" };
      sleep;
   }
'
^CParent got SIGINT
Child got SIGINT

如果那个孩子忽略它,那是因为它启动了一个新会话,或者因为它明确地忽略了它。

  

子进程运行.sh脚本仍然STDOUT到xterm的屏幕。我该如何删除?

在致电exec之前,请在孩子中执行以下操作:

open(STDOUT, '>', '/dev/null');
open(STDERR, '>', '/dev/null');

实际上,我会使用open3来进行错误检查。

open(local *CHILD_STDIN,  '<', '/dev/null') or die $!;
open(local *CHILD_STDOUT, '>', '/dev/null') or die $!;
my $pid = open3(
   '<&CHILD_STDIN',
   '>&CHILD_STDOUT',
   '>&CHILD_STDOUT',
   'shell.sh', 'args',
);
  

父进程(perl脚本)不等待子进程(.sh脚本)。所以我已经读过很多关于孩子变成僵尸的事了?

当父母退出时,或者在父母退出后,孩子会自动退出。

$ perl -e'
   for (1..3) {
      exec(perl => (-e => 1)) if !fork;
   }
   sleep 1;
   system("ps");
' ; ps
  PID TTY          TIME CMD
26683 pts/13   00:00:00 bash
26775 pts/13   00:00:00 perl
26776 pts/13   00:00:00 perl <defunct>       <-- zombie
26777 pts/13   00:00:00 perl <defunct>       <-- zombie
26778 pts/13   00:00:00 perl <defunct>       <-- zombie
26779 pts/13   00:00:00 ps
  PID TTY          TIME CMD
26683 pts/13   00:00:00 bash
26780 pts/13   00:00:00 ps
                                             <-- all gone

如果父母在孩子出现之前退出,那就没问题了。

如果父母在孩子出生后不久退出,则没有问题。

如果父母在孩子出生后退出很长时间,你会想要收获他们。您可以使用waitwaitpid(可能来自SIGCHLD处理程序)执行此操作,也可以使用$SIG{CHLD} = 'IGNORE';自动获取它们。请参阅perlipc

答案 1 :(得分:0)

在父线程中使用waitpid:http://perldoc.perl.org/functions/waitpid.html

waitpid($pid, 0);

您还可以将exec的stdout重定向到/ dev / null:

exec("shell.sh args > /dev/null");