[英]Perl fork exec, system in parent and kill child
嗨,我正在嘗試記錄用戶從我的服務器執行的所有操作。 我有一個替換ssh並記錄所有內容的腳本。
問題是當用戶停止ssh會話時,記錄操作的子進程不會被殺死。
my $pid = fork();
die "unable to fork: $!" unless defined($pid);
if (!$pid) { # child
exec("tail -f $logfile | logger -t $ENV{SUDO_USER}:$target ");
die "unable to exec: $!";
}
$show_cmd && print "% $cmd\n" ;
system $cmd or die "exec() failed: $!\n" ;
printf "Session end pid to kill %d\n", $pid;
kill 1, $pid;
waitpid $pid, 0;
printf "End of the script.\n";
我也放
$SIG{CHLD} = "IGNORE";
如果我刪除了指令系統(啟動用戶原始ssh命令的指令),該子級將被殺死,但這也使我的腳本無用。
任何想法如何成功終止該過程?
編輯:當系統命令結束時,腳本繼續,執行printf,並打印子進程的pid。
編輯2:
這是ssh會話期間的“ ps faux”
root 4976 [...] \_ /usr/bin/perl -w /usr/bin/ssh **.**.**.62
root 4977 [...] \_ sh -c tail -f /var/log/log-session/2014-11-26.155910.*******:root@**.**.**.62 | logger -t *********:root@**.**.**.62
root 4979 [...] | \_ tail -f /var/log/log-session/2014-11-26.155910.*********:root@**.**.**.62
root 4980 [...] | \_ logger -t ********:root@**.**.**.62
root 4978 [...] \_ sh -c /usr/bin/realssh -o UserKnownHostsFile=/etc/ssh/known_hosts_Securite -i /etc/ssh/id_dsa_Securite **.**.**.62 | ...
root 4981 [...] \_ /usr/bin/realssh -o UserKnownHostsFile=/etc/ssh/known_hosts_Securite -i /etc/ssh/id_dsa_Securite **.**.**.62
root 4982 [...] \_ /usr/bin/tee -a /var/log/log-session/2014-11-26.155910.********:root@**.**.**.62
會話結束時:用戶的^ D
Connection to **.**.**.62 closed.
Session end pid to kill: 4977
End of the script.
和“ ps faux”的結果:
root 4979 [...] tail -f /var/log/log-session/2014-11-26.155910.*********:root@**.**.**.62
root 4980 [...] logger -t ********:root@**.**.**.62
因此,最后仍然沒有這兩個過程。
我認為問題是要殺死所有進程樹,因此SO答案可以解決問題
我有這個給孩子的過程
setpgrp(0, 0);
並將kill指令更改為
kill 9, -$pid;
現在看起來像這樣
my $pid = fork();
die "unable to fork: $!" unless defined($pid);
if (!$pid) { # child
setpgrp(0, 0);
exec("tail -f $logfile | logger -t $ENV{SUDO_USER}:$target ");
die "unable to exec: $!";
}
$show_cmd && print "% $cmd\n" ;
system $cmd or die "exec() failed: $!\n" ;
printf "Session end pid to kill %d\n", $pid;
kill 9, -$pid;
waitpid $pid, 0;
printf "End of the script.\n";
謝謝你幫我
您將對這條線有疑問
system $cmd or die "exec() failed: $!\n" ;
因為成功返回命令后系統返回值將為0。 因此,您的程序在殺死它的孩子之前會在這里退出得太早。
看看這個答案: Perl:成功的系統調用后,“ or die”命令仍然結束腳本
我認為您應該以不同的方式來檢查用戶命令是否已成功執行,或者只是通過確保將退出值和輸出傳播給用戶來處理。
您可能會這樣:
system($cmd);
if ($? == -1) {
print "failed to execute: $!\n";
kill 1, $pid;
exit($?);
} elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without';
kill 1, $pid;
exit(3);
}
my $exitval = $? >> 8;
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.