Perl Open3仅输出到std错误,不异步
我对perl编程比较陌生,我正试图弄清楚open3是如何工作的。这是代码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
#!/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是完全有道理的,因为它是用于调试的。我早该弄明白的。幸好你指出了僵局,我不知道会发生这种情况,我应该更仔细地阅读文档。非常感谢你的帮助。