Perl:监视后台进程';在不等待完成的情况下恢复输出

Perl:监视后台进程';在不等待完成的情况下恢复输出,perl,process,background,monitor,Perl,Process,Background,Monitor,我正试图用Perl编写一个管理器来自动化我的实验室一直在使用的生物信息学管道。(REPET管道,供感兴趣的人使用。)管道有八个步骤,其中几个步骤被分解为可以并行运行的子步骤。最值得注意的是,步骤3分为三个部分,步骤4分为三个相应的部分。步骤3的每个部分都可以独立运行,步骤4中对应的部分可以在步骤3完成后立即启动。我希望我的经理能够在三个并行线程中启动步骤3,对于每个线程,在步骤3完成后立即转到步骤4。我能想到的最好的方法是监视每个进程的输出。每个步骤的输出如下所示: START TEdenovo

我正试图用Perl编写一个管理器来自动化我的实验室一直在使用的生物信息学管道。(REPET管道,供感兴趣的人使用。)管道有八个步骤,其中几个步骤被分解为可以并行运行的子步骤。最值得注意的是,步骤3分为三个部分,步骤4分为三个相应的部分。步骤3的每个部分都可以独立运行,步骤4中对应的部分可以在步骤3完成后立即启动。我希望我的经理能够在三个并行线程中启动步骤3,对于每个线程,在步骤3完成后立即转到步骤4。我能想到的最好的方法是监视每个进程的输出。每个步骤的输出如下所示:

START TEdenovo.py (2012-08-23 11:20:10)
version 2.0
project name = dm3_chr2L
project directory = /home/<etc>
beginning of step 1
submitting job(s) with groupid 'dm3_chr2L_TEdenovo_prepareBatches' (2012-08-23 11:20:10)
waiting for 1 job(s) with groupid 'dm3_chr2L_TEdenovo_prepareBatches' (2012-08-23 11:20:10)
execution time per job: n=1 mean=2.995 var=0.000 sd=0.000 min=2.995 med=2.995 max=2.995
step 1 finished successfully
version 2.0
END TEdenovo.py (2012-08-23 11:20:25)
问题是,用backticks调用一个进程会导致perl等待该进程完成后再继续;正如我所发现的,这与system()不同,在system()中,您可以使用&将某些内容旋转到后台进程中,然后立即继续。据我所知,没有一种好方法可以使用system()来获得我想要的效果。我想我可以这样做:

system("TEdenovo.py [options] & > log31.txt");
然后定期轮询log31.txt,查看是否出现了“finished successfully”(完成成功),但这似乎非常混乱

我还尝试在文件句柄中打开进程:

open(my $step3, "TEdenovo.py [options] |");
my @log3;

while(1)
{
    push(@log3, <$step3>);
    last if grep("step 3 finished successfully", @log3);
    sleep(5);
}
open(my$step3,“TEdenovo.py[options]|”);
我的@log3;
而(1)
{
推动(@log3,);
最后一个如果grep(“第3步成功完成”,@log3);
睡眠(5);
}
…但是,Perl再次等待,直到进程完成,才能继续(在本例中,在push()处)。我用$| set和unset尝试了上述方法

因此,我的问题的实质是:有没有一种方法可以用perl捕获正在运行的后台进程的标准输出?

也许您可以试试

open(my $step3, "TEdenovo.py [options] |");

while(<$step3>)
{
    last if /step 3 finished successfully/;
}
open(my$step3,“TEdenovo.py[options]|”);
while()
{
最后一个if/步骤3成功完成/;
}
而不是while(1)?

也许你可以试试

open(my $step3, "TEdenovo.py [options] |");

while(<$step3>)
{
    last if /step 3 finished successfully/;
}
open(my$step3,“TEdenovo.py[options]|”);
while()
{
最后一个if/步骤3成功完成/;
}

使用
open
并从管道手柄读取的方法是正确的,而不是while(1)

方法。如果Nahuel关于在标量上下文中读取句柄的建议没有帮助,那么您仍然可能会受到缓冲的影响

$|
更改Perl输出的缓冲行为,但不更改从Perl调用的任何外部程序的行为。您必须使用不缓冲其输出的外部程序。在这种情况下,我相信通过将
-u
选项传递给python,这是可能的:

open(my $step3, "|-", "python -u TEdenovo.py [more options]");

使用
open
并从管道手柄读取的方法是正确的方法。如果Nahuel关于在标量上下文中读取句柄的建议没有帮助,那么您仍然可能会受到缓冲的影响

$|
更改Perl输出的缓冲行为,但不更改从Perl调用的任何外部程序的行为。您必须使用不缓冲其输出的外部程序。在这种情况下,我相信通过将
-u
选项传递给python,这是可能的:

open(my $step3, "|-", "python -u TEdenovo.py [more options]");

push@log3,
在列表上下文中计算
,等待eof(即流程完成)。啊哈,mob,你的建议似乎已经完成了。我没有读入数组,而是尝试一次连接一行,如
$log3.=
,它正进入我所希望的等待循环。现在只剩下一个小问题了:这样做一次只能获取一行输出,而我想在每次执行时都将其吞咽掉。使用文件slurp模式
$/=unde
也会搜索EOF,不是吗?那么,我如何才能在每个步骤中获得整个输出呢?如果没有办法,我不会感到惊讶;毕竟,这就是EOF的作用,不是吗?我仍然在使用
while(1)
而不是Nahuel的建议,因为我不会让所有的循环条件信息进入循环。我需要监控八个EOF进程,当我进入循环时,其中只有两个进程将启动。i、 例如,我还没有打开这些文件句柄,对于未打开的文件句柄,eof()返回1,这将错误地计算为循环的退出条件。因此,我还必须监视每个日志的内容作为循环条件。。。它只是变得一团糟;在这种情况下,从loo引脚内部更容易监控循环条件。
push@log3,
在列表上下文中计算
,等待eof(即流程完成)。啊哈,mob,您的建议似乎已经完成了。我没有读入数组,而是尝试一次连接一行,如
$log3.=
,它正进入我所希望的等待循环。现在只剩下一个小问题了:这样做一次只能获取一行输出,而我想在每次执行时都将其吞咽掉。使用文件slurp模式
$/=unde
也会搜索EOF,不是吗?那么,我如何才能在每个步骤中获得整个输出呢?如果没有办法,我不会感到惊讶;毕竟,这就是EOF的作用,不是吗?我仍然在使用
while(1)
而不是Nahuel的建议,因为我不会让所有的循环条件信息进入循环。我需要监控八个EOF进程,当我进入循环时,其中只有两个进程将启动。i、 例如,我还没有打开这些文件句柄,对于未打开的文件句柄,eof()返回1,这将错误地计算为循环的退出条件。因此,我还必须监视每个日志的内容作为循环条件。。。它只是变得一团糟;在这种情况下,从loo引脚内部更容易监控环路状况。