Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl Open3仅输出到std错误,不异步_Perl - Fatal编程技术网

Perl Open3仅输出到std错误,不异步

Perl Open3仅输出到std错误,不异步,perl,Perl,我对perl编程比较陌生,我正试图弄清楚open3是如何工作的。这是代码 #!/usr/bin/perl use strict; use warnings; use IPC::Open3; my $dir = "/home/vman/Documents/Dev/perl_scripts/Provenance/temp"; my $fileHandle; my $bashPid; print "Starting main program\n"; my $pid = fork(); if

我对perl编程比较陌生,我正试图弄清楚open3是如何工作的。这是代码

#!/usr/bin/perl 
use strict;
use warnings;
use IPC::Open3;

my $dir = "/home/vman/Documents/Dev/perl_scripts/Provenance/temp";

my $fileHandle;
my $bashPid;

print "Starting main program\n";

my $pid = fork();

if($pid)#Parent process2
{
    print("Start transfer.\n");
    $bashPid = $pid;

    #Attaching an strace to the executed command which happens in the child process
    open3(\*WRITE, \*READ,\*ERROR,"strace", "-f", "-F", "-e", "trace=open,execve","-p", $bashPid, "-s", "2097152","-q");

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

    while(<ERROR>)
    {
        print("$_");
    }

    print("Finish transfer.\n");
}
elsif($pid == 0)
{
    if (scalar(@ARGV == 0))
    {
        exit
    }

    my $args = join(' ', @ARGV);
    exec($args);
}
else
{
    die("Could not fork.");
}

close(READ);
close(WRITE);
close(ERROR);

waitpid($bashPid, 0);

print "End of main program\n";
#/usr/bin/perl
严格使用;
使用警告;
使用IPC::Open3;
my$dir=“/home/vman/Documents/Dev/perl_scripts/provence/temp”;
我的$fileHandle;
我的$bashPid;
打印“正在启动主程序\n”;
我的$pid=fork();
if($pid)#父进程2
{
打印(“开始传输。\n”);
$bashPid=$pid;
#将strace附加到在子进程中执行的命令
open3(\*写、\*读、\*错误、“-f”、“-f”、“-e”、“trace=open、execve”、“-p”、$bashPid、“-s”、“2097152”、“-q”);
while()
{
打印(“此处1\n”);
打印($);
}
while()
{
打印($);
}
打印(“完成传输。\n”);
}
elsif($pid==0)
{
if(标量(@ARGV==0))
{
出口
}
我的$args=join(“”,@ARGV);
执行官($args);
}
其他的
{
死(“不能叉”);
}
关闭(读取);
关闭(写入);
关闭(错误);
waitpid($bashPid,0);
打印“主程序结束\n”;
我想在bash进程上运行strace,然后在输出过程中捕获所有输出。然后,我将获取该输出并对其进行解析,以查看哪个进程正在更改哪些文件,并将这些更改保存到mysql数据库中。现在,我所要做的就是在现有bash进程上附加一个strace,并在运行的bash终端中打印该strace的输出,以确保它正在异步读取输出

问题之一是我通过错误文件句柄获取输出。我有点不明白为什么会这样。我是否为open3使用了正确的顺序?如果有错误,为什么正确的输出甚至会发送到stderr

我遇到的第二个问题是,我只在exec结束时获得输出,这是不好的,因为它需要在exec运行时完成。我以为open3是异步运行的

根据建议,这是我所做的,它工作完美

#!/usr/bin/perl 
use strict;
use warnings;
use IPC::Run3;

my $bashPid;

print "Starting main program\n";
my $pid = fork(); 

if($pid)#Parent process
{
    print("Start transfer.\n");
    $bashPid = $pid;

    #Attaching an strace to the executed command which happens in the child process
    my $command = "strace -fFe trace=open,execve -p $bashPid -s 2097152 -q";

    run3($command, \*STDIN, \*STDOUT, \*STDERR);

    if ($?)
    {
        die "something went horribly wrong";
    }

    while(<STDERR>)
    {
        print($_);
    }

    print("Finish transfer.\n");
}
elsif($pid == 0)#cild process
{
    if (scalar(@ARGV == 0))
    {
        exit
    }

    my $args = join(' ', @ARGV);
    exec($args);
}
else
{
    die("Could not fork.");
}

close(STDIN);
close(STDOUT);
close(STDERR);

waitpid($bashPid, 0);

print "End of main program\n";
#/usr/bin/perl
严格使用;
使用警告;
使用IPC::Run3;
我的$bashPid;
打印“正在启动主程序\n”;
我的$pid=fork();
if($pid)#父进程
{
打印(“开始传输。\n”);
$bashPid=$pid;
#将strace附加到在子进程中执行的命令
my$command=“strace-fFe trace=open,execve-p$bashPid-s 2097152-q”;
run3($command,\*STDIN,\*STDOUT,\*STDERR);
如果($?)
{
死“出了可怕的事”;
}
while()
{
打印(美元);
}
打印(“完成传输。\n”);
}
elsif($pid==0)#cild过程
{
if(标量(@ARGV==0))
{
出口
}
我的$args=join(“”,@ARGV);
执行官($args);
}
其他的
{
死(“不能叉”);
}
关闭(标准输入);
关闭(标准输出);
关闭(STDERR);
waitpid($bashPid,0);
打印“主程序结束\n”;
问题之一是我通过错误文件句柄获取输出

对<代码>strace写入STDERR

我遇到的第二个问题是,我只在exec结束时获得输出,这是不好的,因为它需要在exec运行时完成。我以为open3是异步运行的

这是因为只有在孩子结束时关闭其标准输出后,您才开始从孩子的标准输出读取

事实上,你很幸运你还没有陷入僵局。当
strace
有足够的输出填充管道时,按当前的方式一次读取一个,就会死锁


你需要阅读孩子的STDOUT和STDERR。您可以在
select
的帮助下使用轮询非阻塞句柄或线程来完成此操作。这些选项中没有一个比放弃open3和使用更高级别的模块为您处理更简单。简单和功能齐全是不错的选择。

是的,它之所以输出到stderr是完全有道理的,因为它是用于调试的。我早该弄明白的。幸好你指出了僵局,我不知道会发生这种情况,我应该更仔细地阅读文档。非常感谢你的帮助。