3

を使用Linuxしており.shますtcsh

非常に基本的なforkexecを作成しましたが、安全性を実装するには助けが必要です。

基本的に、私の perl スクリプトは.sh子プロセスでスクリプトを呼び出します。しかしCtrl+c、親を殺すと、シグナルは子によって無視されます。

SIGINT1)子プロセスもキャプチャするにはどうすればよいですか?

2) .sh スクリプトを実行する子プロセスは、xterm の画面に対して STDOUT のままです。どうすればこれを削除できますか? バックグラウンドでスクリプトを実行することを考えていました

 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 スクリプトを実行する子プロセスは、xterm の画面に対して STDOUT のままです。どうすればこれを削除できますか?

を呼び出す前に、子で次のことを行います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を参照してください。

于 2012-09-26T18:39:06.380 に答える
0

親スレッドでwaitpidを使用します:http://perldoc.perl.org/functions/waitpid.html

waitpid($pid, 0);

execのstdoutを/dev/nullにリダイレクトすることもできます。

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