我正在使用Linux
而.sh
位于tcsh
。
我已经制作了一个非常基本的fork和exec,但我需要帮助实现安全性。
基本上我的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}
答案 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
如果父母在孩子出现之前退出,那就没问题了。
如果父母在孩子出生后不久退出,则没有问题。
如果父母在孩子出生后退出很长时间,你会想要收获他们。您可以使用wait
或waitpid
(可能来自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");