【问题标题】:How do I get output in a Perl process started from Win32::Process?如何在从 Win32::Process 启动的 Perl 进程中获取输出?
【发布时间】:2010-11-22 01:14:48
【问题描述】:

我有一个 Perl 脚本,它通过Win32::Process 在新控制台中启动另一个 Perl 脚本,如下所示:

Win32::Process::Create($ProcessObj,
                      "C:\\Perl\\bin\\perl.exe",
                      "$path_to_other_perl_script",
                      0,
                      NEW_CONSOLE,
                      ".");

$ProcessObj->Suspend();
$ProcessObj->Resume();
$ProcessObj->Wait(0);

问题是,创建的新控制台中没有标准输出。如果我不使用新的控制台选项,脚本会在后台静默运行。

如果我使用 cmd.exe 启动 Perl 脚本,我可以看到输出正常,但现在我无法通过 Win32::Process 控制子 Perl 脚本。

有人有有效的解决方案吗?

【问题讨论】:

  • 我使用 Win32::Process 生成大量 perl 进程,并发现使用 Log4perl 进行日志记录优于写入控制台输出。

标签: windows perl winapi


【解决方案1】:

更新:根据您的 cmets,我感觉您的程序不是 Linux 或 Windows 上的最佳实践示例。但是,我敢肯定,在阅读Win32::Process 的文档时,您注意到您可以在进程上调用Kill 方法来终止它。所以,我改变了下面的例子来做到这一点。

如果您提供真实代码,您获得有用帮助的机会会成倍增加。以下是Win32::Process::Create 的参数:

$iflags:标志:是否继承调用进程句柄

现在,我不确定您是要捕获第二个进程的 STDOUT,还是要使其 STDOUT 输出显示在与父进程相同的控制台中。

如果是后者,那么以下脚本说明了这样做的一种方法:

父.pl

#!/usr/bin/perl

use strict;
use warnings;

use Win32;
use Win32::Process;

$| = 1;

my $p;

print "Starting child process ... \n";

Win32::Process::Create(
    $p,
    'c:/opt/perl/bin/perl.exe',
    'perl hello.pl',
    1,
    NORMAL_PRIORITY_CLASS,
    '.',
) or die Win32::FormatMessage( Win32::GetLastError() );

print "Waiting three seconds before killing 'hello.pl'\n";

for (1 .. 3) {
    print;
    sleep 1;
}
$p->Kill(0)
    or die "Cannot kill '$p'";

你好.pl

#!/usr/bin/perl

$| = 1;

print "Hello World\n";
print "Sleeping 1000 seconds\n";

for (1 .. 1000) {
    sleep 1;
    print '.';
}

输出:

启动子进程... 在杀死“hello.pl”之前等待三秒钟 1你好世界 睡眠 1000 秒 2.3.

现在,我仍然不确定你为什么使用Win32::Process。除非有特定原因将您的脚本绑定到Win32,否则我建议使用标准 Perl 工具。例如,阅读perldoc -f openperldoc perlipc(尤其是Using open for IPC)。

更好地解释您的问题,以获得针对您的特定情况而不是笼统的答案。

【讨论】:

  • 如果我通过系统命令创建进程,我无法找到任何方法来终止win32上的进程。在 Linux 上,我只是使用 system("kill -9 -$$") 来杀死 perl 脚本及其所有子脚本,但在 Windows 上找不到这么简单的东西
  • speculation.org/garrick/kill-9.html 不开玩笑,我发现system("kill -9 -$$") 是嫌疑人。 fork 适用于 Windows:fork 您的孩子,将他们的 pids 和 wait 保存在他们或 kill 他们认为合适的位置。我更喜欢search.cpan.org/perldoc/Parallel::ForkManager
  • 尝试过并且很想这样做 - 但是,如果我 fork() 然后通过 exec 或 system 调用我的子脚本,则 exec 进程的 PID 与返回的 PID 不同叉子。
  • 注意在 Windows 上分叉。对于几个进程来说这很好,但是我在 Windows 处理来自同一个进程的数百个进程时遇到了很多问题。
  • @brian d foy 我从来没有超过几十个(而且只有一个程序)。感谢您指出这一点。
【解决方案2】:

在 $filepath 修复它之前使用 -w !不过还是需要解释一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-30
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多