如何使用 system() 从 CGI 文件调用异步 Perl 脚本

How to call asynchronous Perl script from CGI file using system()

让我先说明我的问题,我已经阅读了很多关于 SO 的不同帖子以及网络搜索,但一直无法找到适合我的确切情况的内容。

其实问题很简单。我有一个 CGI 脚本 (Perl) 在 Web 服务器上提供动态页面,当用户加载某个页面时,我想让 CGI 脚本使用 system() 调用 .pl 文件来做一些 "housekeeping".这是在 Windows NT 环境中 运行ning。

用于测试目的的CGI脚本是test1.pltest1.cgi,例如“https://www.awebsite.com/test1.pl”。

test1.pl(生成网页的cgi脚本)

#!/usr/bin/perl

print "Content-type: text/html\n\n";

print "Hello user, this is a test page.";

system("start C:/path/to/script/test2.pl");

print "Page is fully loaded and housekeeping is being done, even though this page is now fully loaded";

test2.pl(正在执行 "housekeeping" 的单独 .pl 文件,与 test1.pl 正在执行的操作异步)

#!/usr/bin/perl

#just a counter that takes a while to complete, to verify test2.pl is running
for ($x=0; $x <= 100000; $x++){print "$x ";}

好的,请记住这是为了测试操作,而不是功能。当从命令行 运行ning test1.pl 时,它工作正常。

当从浏览器 运行ning test1.pl 时,这会在服务器上不断提示 "openWith.exe"(在任务管理器中查看)。我的 .pl 文件是可执行文件,所以这不是未知文件类型或不知道 运行 使用 Perl 命令行解释器的问题。我无法弄清楚这里发生了什么,以及为什么当通过 Web 界面调用时它不会 运行 来自 test1.pl 的系统命令。

没有从用户输入传递的参数。 test1.pl 只需要 运行 test2.pl 做一些内务处理,但我不能让 test1.pl 等待 test2.pl 完成后再继续。因此,test2.pl 应该由 test1.pl 开始并继续 运行ning - 与此同时,test1.pl 已经完成了它的工作。我 不需要 需要或想要捕获 test2.pl 的任何输出。

希望我已经解释清楚了。我使用了简单的示例,尽管实际代码会复杂得多。在这一点上,它甚至还没有 运行 宁这些简单的示例脚本,所以此时实际运行的代码并不重要。

感谢任何能帮助我的人。顺便说一下,我尝试为 test1.pl 设置 "full control" 权限,但这没有帮助。同样,这个 "openwith.exe" 真的让我陷入困境。

您可以留在环境的语义中 (cgi/web) 并使 script2 成为自己的 CGI 脚本,然后在 script1 中向其发出异步 http 请求。 您可以为此使用 HTTP::Async。但是你必须注意不能从外部调用 script2,例如通过检查客户端 ip。

此外,由于这是一个 cgi,script1 可能会并行 运行 多次,对于 script2 也是如此,但是您最终会调用它。所以你必须确保在发生这种情况时不要把事情搞砸。

start C:/path/to/script/test2.pl 依赖于在 .pl 文件和您的 perl 可执行文件之间建立关联。您可能在您的用户上进行了设置,但网络服务器可能没有。

你可以设置它。或者您不能使用 start 而是直接将您的程序传递给 perl。具体如何执行此操作取决于 Perl 的安装方式和 Web 服务器的设置方式。您也许可以只使用 perl.exe.

system('perl.exe C:/path/to/script/test2.pl');

或者您可能必须传递完整路径。

system('C:/path/to/perl.exe C:/path/to/script/test2.pl');

有关详细信息,请参阅 the documentation for start


请注意,从 Perl 程序 运行ning Perl 程序并不理想。有许多难以调试的东西,一旦您开始传递数据并检查错误就可能出错。

而是考虑将该代码作为子例程,并在后台使用 forkthreads 到 运行 它。或者更好的是,使用网络框架,例如 Dancer and link it to a job queue like Minion.

终于想通了(像往常一样,靠我自己)。结果是 Schwern,你走在正确的轨道上。尽管 .pl 文件关联是通过控制面板建立的,以便使用 Perl 命令行解释器打开,但 windows 文件类型关联存在问题(blahblahblah,我什至不完全理解)。我终于在这里找到了真正问题的答案:

特别是这里的这一部分:

You must create a file association between the .pl file extension and the Perl runtime. At a command prompt type the following.
assoc .pl=PerlScript
ftype PerlScript=c:\perl\bin\perl.exe %1 %*

我希望这对可能遇到同样问题的人有所帮助。