以非冒险方式从perl调用bash脚本并获取此新后台进程的pid

时间:2016-10-28 03:18:04

标签: linux bash perl nonblocking pid

我有一个bash脚本,我使用env从命令行运行,将其输出重定向到log.txt

env FOO=hello BAR=world ./myscript &> log.txt

我想在后台中从perl运行一些myscript非阻塞实例。

反过来, perl 脚本通过这种方式从另一个bash脚本mainScript运行:

#!/bin/bash -x
perlScript.pl | tee main-log.txt

我知道,我可以在这样的循环中使用perl system()调用来实现它

my $result = system("env FOO=hello BAR=world ./myscript &> log.txt &");

我使用来自perl的forkexec调用来在后台运行myscript并获取其pid:

$run_cmd = "./myscript";
$run_cmd.= " &> log.txt";

defined(my $pid = fork) or die "$0: fork: $!\n";
if (!$pid) {  # child code is here

    $ENV{FOO} = 'hello';
    $ENV{BAR} = 'world';

    exec "exec $run_cmd";
    die "$0: failed to exec sh: $!\n";

}

# parent code continues here
print "PID of run_cmd: $pid \n";

但我发现当我在|内使用管道teemainScript

| tee main-log.txt

perl

中为myScript创建新程序后,我无法在屏幕上看到输出

如果我从perlScript.pl拨打mainScript而没有tee,一切正常。

在这种情况下如何使用tee,或者可能有另一种方法来重定向mainScript的输出,它会同时出现在屏幕和某些日志文件

3 个答案:

答案 0 :(得分:1)

这是未经测试的,但你不能这样做吗?

defined(my $pid = fork) or die "$0: fork: $!\n";
if (!$pid) {
    $ENV{FOO} = 'hello';
    $ENV{BAR} = 'world';
    exec 'exec ./myscript &> log.txt';
    die "$0: failed to exec sh: $!\n";
}
# parent process here, child pid is in $pid

你甚至可以在perl中进行输出重定向,保存对shell的调用:

    open STDOUT, '>', 'log.txt' or die "$0: log.txt: $!\n";
    open STDERR, '>&', \*STDOUT or die "$0: dup(stdout): $!\n";
    exec './myscript';
    die "$0: ./myscript: $!\n";

答案 1 :(得分:0)

使用 open

my $pid = open(my $h, "$cmd |");

然后你可以从句柄 h 中读取 cmd 的输出:

while (<$h>) {
    print "$_\n";
}

答案 2 :(得分:-1)

我会使用IPC :: Open3 perl模块 - https://metacpan.org/pod/IPC::Open3