在运行在Perl的后台作业无需等待回报 [英] Running job in the background from Perl WITHOUT waiting for return

查看:141
本文介绍了在运行在Perl的后台作业无需等待回报的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

免责声明

首先,我知道这个问题(或接近变化)已经被问了一千次。我真的花了几个小时,看在明显的和不那么明显的地方,但也有可能是一些小的我失踪。

上下文

让我更清楚地定义问题:我在写的,我想实际的发送过程是一个异步通讯的应用程序。作中,用户点击发送,请求立即返回,然后他们可以为您在特定页面的进展(通过AJAX,例如)。这是写在传统的LAMP堆栈。

在特定主机我使用的,PHP的执行exec()和系统()是出于安全原因禁用,但Perl的系统功能(EXEC,系统和反引号)不是。所以,我的解决方法的解决方案是建立在Perl中触发脚本调用通过PHP CLI实际的发送者,并重定向到进度页面。

当我被困

非常排队呼叫发件人是,截至目前:

 系统(PHP -q sender.php&安培;);

问题是,它不是立即返回,而是在等待脚本来完成。我希望它在后台运行,并有系统调用本身立即返回。我也试过在我的Linux终端上运行一个类似的脚本,而实际上提示不显示,直到脚本完成后,即使我的测试输出不运行,这表明它的真正在后台运行。

什么我已经尝试过


  • Perl的exec()函数 - 系统相同的结果()

  • 更改命令:PHP -q sender.php |在现在的),希望在守护进程会返回和PHP程序本身不会被附加到Perl的

  • 执行命令'间接'。/ bin / sh的-c'PHP -q sender.php&放大器;' - 依然等待,直到sender.php完成发送

  • fork()的ING的过程和执行在孩子的系统调用(希望分离的进程) - 上述相同的结果

我的测试环境

只是要确保我没有错过什么明显的,我创建了一个sleeper.php脚本,它只是睡觉5秒飞去。和test.cgi脚本是这样的,逐字:

 #!的/ usr / local / bin目录/ perl的
系统(PHP sleeper.php&放大器;);
打印内容类型:text / html的\\ n \\ ndone

我应该现在就来试试?


解决方案

从本质上讲,你需要'以进程的过程 - 叉掉一个孩子,然后完全从父断开连接,这样家长可以在不影响安全地终止这个孩子。

您可以用CPAN做到这一点很容易模块 PROC ::守护

 使用PROC ::守护进程;
#你需要分叉孩子之前做的一切......#做成​​守护进程;关闭所有打开的FDS
PROC ::守护::初始化();

The Disclaimer

First of all, I know this question (or close variations) have been asked a thousand times. I really spent a few hours looking in the obvious and the not-so-obvious places, but there may be something small I'm missing.

The Context

Let me define the problem more clearly: I'm writing a newsletter app in which I want the actual sending process to be async. As in, user clicks "send", request returns immediately and then they can check the progress in a specific page (via AJAX, for example). It's written in your traditional LAMP stack.

In the particular host I'm using, PHP's exec() and system() are disabled for security reasons, but Perl's system functions (exec, system and backticks) aren't. So my workaround solution was to create a "trigger" script in Perl that calls the actual sender via the PHP CLI, and redirects to the progress page.

Where I'm Stuck

The very line the calls the sender is, as of now:

system("php -q sender.php &");

Problem being, it's not returning immediately, but waiting for the script to finish. I want it to run in the background and have the system call itself return right away. I also tried running a similar script in my Linux terminal, and in fact the prompt doesn't show until after the script has finished, even though my test output doesn't run, indicating it's really running in the background.

What I already tried

  • Perl's exec() function - same result of system().
  • Changing the command to: "php -q sender.php | at now"), hoping that the "at" daemon would return and that the PHP process itself wouldn't be attached to Perl.
  • Executing the command 'indirectly': "/bin/sh -c 'php -q sender.php &'" - still waits until sender.php is finished sending.
  • fork()'ing the process and executing the system call in the child (hopefully detached process) - same result as above

My test environment

Just to be sure that I'm not missing anything obvious, I created a sleeper.php script which just sleeps five seconds before exiting. And a test.cgi script that is like this, verbatim:

#!/usr/local/bin/perl
system("php sleeper.php &");
print "Content-type: text/html\n\ndone";

What should I try now?

解决方案

Essentially you need to 'daemonize' a process -- fork off a child, and then entirely disconnect it from the parent so that the parent can safely terminate without affecting the child.

You can do this easily with the CPAN module Proc::Daemon:

use Proc::Daemon;
# do everything you need to do before forking the child...

# make into daemon; closes all open fds
Proc::Daemon::Init();

这篇关于在运行在Perl的后台作业无需等待回报的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆