1

我试图从 php 脚本中执行 perl 脚本。我已经使用各种方法(例如 exec、popen 和 proc_open)进行了这项工作,但是我有几个问题需要解决,而老 Google 并没有给我答案。

我需要从 php 文件中运行 .pl 脚本(将一个变量传递给脚本,该脚本是一个数字),但停止 php 脚本等待 .pl 完成(.pl 可能需要 4-5 小时在服务器上运行)。我不期望 perl 脚本有任何返回输出(perl 脚本将其输出记录到 mysql db)所以我只需要它在服务器上运行并让 php 脚本继续运行。

当它在运行 apache、php、mysql 的 Windows 机器上运行时,有一些障碍需要克服。

我想我已经看到了 linux 的解决方案,但它需要留在 Windows 机器上。

我目前正在尝试使用以下代码的 proc_open 方法(proc_open 行上的 35 是我需要传递给 perl 脚本的测试 ID):

$descriptorspec = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("file","./error.log","a")
) ;

proc_close(proc_open('perl perlscript.pl 35', $descriptorspec, $pipes));

$i = 0;
while ($i < 1000) {
   echo ++$i;  
}

现在这段代码确实执行了 perl 脚本,但是我放置在它之后的 while 循环(仅用于测试)永远不会执行(我没有等待 perl 脚本完成以查看它是否执行),因为它必须等待 .pl 完成.

4

4 回答 4

0

我可以看到 3 个选项:

  • 在您的 perl 脚本中使用fork在 fork 之后使用现有的父进程来分叉实际工作。然而,这在 Windows 上可能无法正常工作或根本无法工作,但值得一试。

    请参阅以下“fork在 Windows 上”参考:

  • 如果 PHP 可以启动 URL 请求(类似于 Perl 的 LWP 或 wget),那么将您的 Perl 脚本转换为 CGI 脚本(简单),粘贴到您的 Apache 的 CGI 目录中,并通过适当的 URL 将其调用到http://localhost/.... 然后在最坏的情况下通过一些内部 PHP 超时或常规 HTTP 超时来超时 URL 请求。在最坏的情况下,在 Perl 代码中执行相同的技巧,因为 Perl 绝对可以同时支持通过 LWP 库的 URL 调用以及通过alarm()

  • 让调度程序每 X 分钟启动一次您的 Perl 脚本。该脚本应以以下逻辑开始:服务器上的特殊位置在if (-e $flag_file) { unlink $flag_file; do_long_work() } else { exit 0; }哪里(例如),并包含需要完成的实际工作。$flag_fileC:\temp\myscript_start_perl.txtdo_long_work()

    然后,当 PHP 脚本需要启动 Perl 脚本时,它会简单地创建一个空标志文件(相同C:\temp\myscript_start_perl.txt),下次调度程序执行时 Perl 脚本会注意到它。

于 2010-11-26T12:01:53.340 回答
0

有两种可能

  1. 使用“启动”程序。您将无法使用管道,只能使用命令行参数。

  2. 创建一个始终运行的 Perl 程序(在启动时运行或使用 Win32::Daemon)。使用套接字或 http 连接到它。这很容易,因为 CPAN 上有很多现成的服务器

此外,可以从另一个使用 Win32::Job 或 Win32::Process 或其他 CPAN 模块的 Perl 程序执行此操作。

于 2010-11-26T12:14:26.733 回答
0

我最近为这样的任务发布了一个模块:Win32::Detached

将它添加到您的 perl 脚本中,它会自行守护进程,让您的 PHP 脚本继续运行。

于 2010-11-28T15:43:26.530 回答
0

感谢所有回答这个问题的人。经过大量研究并弄乱了不同的解决方案,我终于找到了一些可以满足我们需求的工作。它远非完美,但它有效,所以我不会抱怨太多。

因为这似乎是其他人想知道的东西,所以我认为我分享了我的解决方案。

  1. 我从这里下载了一个名为 Hstart (40kb) 的小程序:http: //www.ntwind.com/software/utilities/hstart.html

  2. 我将文件解压缩到 c:\windows\system32。

hstart 程序能够在不打开命令窗口的情况下运行批处理文件。直接调用 .pl 文件是行不通的,所以我必须创建一个 .bat 来调用 .pl ,如下所示。

  1. 创建了一个与我的 .pl 文件相同的目录的 .bat 文件,该文件基本上使用本地安装的 perl 并传递一个变量来调用 perl 脚本。如这里所示:

    perl 脚本.pl %1

  2. 在我的 PHP 脚本中,我使用以下命令来调用我的 perl 文件。

    $cmd = 'hstart /NOCONSOLE "run.bat ' . $id . '" > log.log'; 执行($cmd);

  3. 由于设置了标志,运行 php 文件会导致 hstart 以 noconsole 打开,使用我作为变量传递的 $id 打开 perl 文件,并将隐藏控制台窗口的所有输出发送到我的命令指定的 log.log。我只能看到 perl.exe 在我的任务管理器中运行。

正如我所说,远非完美,但它有效。

于 2010-11-29T16:44:35.293 回答