close $out
のときに外部プログラムを終了していない場合は、STDOUT
を閉じています。
プログラムを閉じるには、プロセスIDを取得してから適切な信号を送信する必要があります。 open
呼び出しはpidを返し、保存するだけです。その後、条件が満たされたときに信号を送信します。
use Scalar::Util qw(openhandle); # to check whether the handle is open
my $pid = open (my $out, "-|", "usfos $memory<input-$cpu.scr")
// die "Can't fork: $!"; #/stop editor red coloring
while (<$out>) {
if (/MIN STEP LENGTH/) {
kill "TERM", $pid; # or whatever is appropriate; add checks
close $out; # no check: no process any more so returns false
last;
}
}
# Close it -- if it is still open.
if (openhandle($out)) {
close $out or warn "Error closing pipe: $!";
}
はopen
とopentut
、およびclose
を参照してください。
のFortranのエラーが存在しないコンソール(STDOUT
)への書き込みについては確かなので、あなたが問題を正しく診断されていることに私には思える:条件が一致したとして、あなたは(last
)読み取りを停止し、その後、プログラムのSTDOUT
を閉じますこれは、次に試行された書き込みで報告されたエラーを引き起こします。
いくつかのメモ。パイプを閉じると、他のプロセスが終了するのを待ちます。他端のプログラムがclose
に知られるような問題を抱えている場合は、$?
に質問する必要があります。他のプログラムが書き込まれる前にパイプを閉じると、SIGPIPE
が送信されます。 close
ドキュメント
からファイルハンドルをパイプで連結された、オープン、クローズを返すから来た場合はfalseの場合は、そのプログラムが非ゼロのステータスで終了した場合に関与する他のシステムコールの一つが故障しましたか。唯一の問題は、プログラムが非ゼロで終了したことである場合、$! 0に設定されます。パイプを閉じると、パイプ上で実行されているプロセスが終了するのを待ちます。パイプの出力を後で見たい場合は、そのコマンドの終了ステータス値を暗黙的に$?に入れます。 $ {^ CHILD_ERROR_NATIVE}です。
...
パイプの読取り側を処理終了前に閉じると、書込み側はSIGPIPEを受け取って結果を書き込みます。もう一方の端で処理できない場合は、パイプを閉じる前にすべてのデータを必ず読み込んでください。
注 オブジェクトがSTDOUT
がそのファイルハンドル(一度条件が満たされている)を閉じるために、ファイルハンドルとに接続されているプロセスを殺すために添加します。プロセスがまだ書き込んでいる間に最初にハンドルを閉じると、わからないプロセスにSIGPIPE
が送信されています。 (信号を処理していますか?)一方で、最初に終了すると、$out
に接続されたプロセスが終了したため、close($out)
は正常に完了できません。プロセスが殺された後(kill
が成功した場合)、それが偽であるように、コードは、close
への呼び出しからの復帰をチェックしない理由
です。ループの後でハンドルを閉じる前にまだハンドルが開いているかどうかがチェックされます。パッケージScalar::Util
はこれに使用され、別のオプションはfileno
です。コードでkill
がジョブを実行したかどうかはチェックされず、必要に応じて追加されます。
Windowsシステムでは、子供のプロセスIDを見つける必要があるため、少し異なります。これを行うには、名前を使用してからWin32::Process::Kill
を使用するか、kill
を使用して終了します。 (または、以下、このすべてを行う必要があり、Windowsのコマンドを参照してください。)プロセスIDがWin32::Process::Info
を使用しWin32::Process::List
use Win32::Process::Kill;
use Win32::Process::List;
my $pobj = Win32::Process::List->new();
my %proc = $pobj->GetProcesses();
my $exitcode;
foreach my $pid (sort { $a <=> $b } keys %proc) {
my $name = $proc{$pid};
if ($name =~ /usfos\.exe/) {
Win32::Process::KillProcess($pid, \$exitcode);
# kill 21, $pid;
last;
}
}
使用
のいずれかを試してみてください見つけるために。 this postを参照してください。
use Win32::Process::Info;
Win32::Process::Info->Set(variant=>'WMI'); # SEE DOCS about WMI
my $pobj = Win32::Process::Info->new();
foreach my $pid ($pobj->ListPids) {
my ($info) = $pobj->GetProcInfo($pid);
if ($info->{CommandLine} =~ /^usfso/) { # command-line, not name
my $proc = $info->{ProcessId};
kill 2, $proc;
last;
}
}
このモジュールはまた、提出$ppid
(S)のすべての子を同定する方法Subprocesses([$ppid,...])
を提供することに留意されたいです。これは、$ppid
でインデックス付けされ、$ppid
がサブミットされたすべてのサブプロセスの$pid
である配列-refを含むハッシュを返します。
use Win32::Process::Info;
Win32::Process::Info->Set(variant=>'WMI');
my $pobj = Win32::Process::Info->new();
my %subproc = $pobj->Subprocesses([$pid]); # pid returned by open() call
my $rkids = $subproc{$pid};
foreach my $kid (@$rkids) {
print "pid: $kid\n"; # I'd first check what is there
}
は、私は今、この権利のいずれかをテストすることはできませんプロセスとその子
system("TASKKILL /F /T /PID $pid");
を終了する必要があり、WindowsのコマンドTASKKILL /T
に走りました。
perlは書き込みしようとしていませんが、これは書き込みを行わないパイプです。あなたの外部のプログラムがエラーを出すものだと思われます。 –