簡體   English   中英

Perl fork執行程序,父系統中的系統並殺死子系統

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM