3

我正在使用Linux并且.shtcsh.

我做了一个非常基本的forkexec,但我需要帮助来实施安全措施。

.sh基本上我的 perl 脚本在子进程中调用一个脚本。但是当我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}
4

2 回答 2

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

如果父母先于孩子退出,则没有问题。

如果父母在孩子离开后不久就退出了,那没有问题。

如果父母在孩子离开后很长时间才离开,你会想要收获他们。您可以使用waitor waitpid(可能来自SIGCHLD处理程序)来执行此操作,或者您可以使用$SIG{CHLD} = 'IGNORE';. 见perlipc

于 2012-09-26T18:39:06.380 回答
0

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

waitpid($pid, 0);

您还可以将 exec 的标准输出重定向到 /dev/null:

exec("shell.sh args > /dev/null");
于 2012-09-26T18:29:33.027 回答