2012-09-26 44 views
3

我使用的是Linux.shtcshperl fork()exec(),子進程狂放

我做了一個非常基本的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} 

回答

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

+0

改進了最後一個問題的答案。 – ikegami

+0

首先我想感謝您的幫助! – user1539348

+0

回到第一個問題。如果我們用ctrl + C來殺死子進程,如果它們仍然收到signit? 我把這個放在父$ SIG {INT} = sub {kill -9 $ pid}; ? 也是一個相關的問題如果一個孩子在父執行waitpid($ pid,0)之前已經完成了什麼?在多個孩子同時分岔的情況下(有一個循環),然後等待最後。 – user1539348