stop a process with a condition in perl

久未见 提交于 2019-12-12 17:02:36

问题


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:

  1. 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.

  2. 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.

  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!