问题
I asked the following question below and I found a very close answer but later realised it doesn't work. I am using pipe in perl. But before I even hit my condition through the pipe, the function is completed its run. Is there a way to check at run-time at the very exact second to stop the process once 10 banana's pass
parse output and count number of times a string appears
Hello I tried this...but it doesn't work...the process is finished way before I even get the chance to stop it. Isn't there anything which can actually control the flow of process with the pid. I mean, 23 banana's had crossed before it found that 10 were done. I am guessing pipe flows slower than the actual process
All I want to do is add a delay in the already running process. Like: lets say we know what the output will look like: command 1 out command 2 out banana Now I can parse for banana and put a delay of 5 seconds in the process. Once I inject a delay, I could run my perl script in that time and stop the script in time.
To make my question clear: the code I wrote:
my $pid = open my $pipe, '-|', 'commandA | tee banana.foo'
or die "Error opening pipe from commandA: $!\n";
# open my $pipe, 'commandA | tee result |'
# or die "Error opening pipe from commandA: $!\n";
print "$pid\n";
my $n = 0;
while (<$pipe>) {
$n++ if /banana/;
last if $n > 0;
print "pipestring\n";
}
kill 'INT', $pid;
close $pipe; # kills the command with SIGPIPE if it's not done yet
if ($n eq 1) {
print "commandA printed 'banana'\n";
}
else
{
print "nothing happened\n";
}
banana.foo ( actual result ) | banana.foo (expected result)
one | one
two | two
three | three
banana | banana
four
five
So I don't want the last 2 values and want the program to stop. commandA is :
echo one
echo two
echo three
echo banana
echo four
echo five
IMPORTANT EDIT: I think what I would be going towards is creating a debugger. Someone has the code for any open source debugger or something else which controls processes.
回答1:
What you're trying to do will never work reliably: there's always a race between the commandA
process writing data to the file and the other process trying to kill it. Since there are several buffering stages between the two processes, it's quite likely that the writing process will have a chance to produce a lot of extra output before it's killed.
The only ways I can think of to avoid this are:
Move the terminating condition check (stop after printing 10 "banana"s) to the program that is producing the output. That way, you won't need to kill it at all.
Have the program producing the output wait for some kind of confirmation from the other program after printing each line. This is possible, but rather tricky and probably inefficient.
Instead of using
tee
, have the controlling program (the one that checks for the terminating condition) write the data to the output file, like this:open my $out, '> banana.foo' or die "Error opening banana.foo for writing: $!\n"; my $pid = open my $pipe, 'commandA |' or die "Error opening pipe from commandA: $!\n"; my $n = 0; while (<$pipe>) { print $out $_; $n++ if /banana/; last if $n > 0; } kill 'INT', $pid; close $pipe;
回答2:
I'm editing this post because I apparently misunderstood what you needed.
http://perldoc.perl.org/perlipc.html#Bidirectional-Communication-with-Another-Process
And that whole page has some ideas about how to have more control over the child processes, etc.
来源:https://stackoverflow.com/questions/17753672/stop-a-process-with-a-condition-in-perl