从开始的CGI脚本后台进程/守护进程 [英] Start background process/daemon from CGI script

查看:244
本文介绍了从开始的CGI脚本后台进程/守护进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从一个CGI脚本启动一个后台进程。基本上,当提交表单的CGI脚本将指示他或她的要求正在处理用户,而后台脚本执行实际的处理(因为处理往往需要很长的时间)。我所面临的问题是,直到孩子脚本终止Apache将不是父CGI脚本的输出发送到浏览器。

I'm trying to launch a background process from a CGI scripts. Basically, when a form is submitted the CGI script will indicate to the user that his or her request is being processed, while the background script does the actual processing (because the processing tends to take a long time.) The problem I'm facing is that Apache won't send the output of the parent CGI script to the browser until the child script terminates.

我已经告诉一个同事说我想要做的是不可能的,因为没有从等待CGI脚本的整个进程树死的方式prevent的Apache。不过,我也看到了网络上多次提到这是应该做的工作是双叉的把戏。诀窍是在<一个简洁描述href=\"http://stackoverflow.com/questions/1952900/running-c-cgi-script-as-background-process/1954215#1954215\">this堆栈溢出的答案,但我已经看到了类似的code别处。

I've been told by a colleague that what I want to do is impossible because there is no way to prevent Apache from waiting for the entire process tree of a CGI script to die. However, I've also seen numerous references around the web to a "double fork" trick which is supposed to do the job. The trick is described succinctly in this Stack Overflow answer, but I've seen similar code elsewhere.

下面是我写的,以测试在Python双叉招很短的脚本:

Here's a short script I wrote to test the double-fork trick in Python:

import os
import sys

if os.fork():
    print 'Content-type: text/html\n\n Done'
    sys.exit(0)

if os.fork():
    os.setsid()
    sys.exit(0)

# Second child
os.chdir("/")
sys.stdout.close()
sys.stderr.close()
sys.stdin.close()

f = open('/tmp/lol.txt', 'w')

while 1:
     f.write('test\n')

如果我运行这个从外壳,但它正是我期望:原始脚本和第一后裔死,第二后代继续工作,直到它的手动杀死。但是,如果我通过CGI访问,页面将不会加载,直到我杀了第二后裔或Apache杀死它,因为CGI超时。我也试着更换第二个 sys.exit(0) os._exit(0),但有是没有区别的。

If I run this from the shell, it does exactly what I'd expect: the original script and first descendant die, and the second descendant keeps running until it's killed manually. But if I access it through CGI, the page won't load until I kill the second descendant or Apache kills it because of the CGI timeout. I've also tried replacing the second sys.exit(0) with os._exit(0), but there is no difference.

我在做什么错了?

推荐答案

这双分叉的办法是某种形式的黑客攻击,这对我来说是指示它不应该做的:)。对于CGI反正。根据一般的原则是,如果事情是太难做到,你可能快到了错误的方式。

Don't fork - run batch separately

This double-forking approach is some kind of hack, which to me is indication it shouldn't be done :). For CGI anyway. Under the general principle that if something is too hard to accomplish, you are probably approaching it the wrong way.

幸运的是,你给你所需要的背景信息 - 一个CGI呼叫发起的独立发生的一些处理并返回给调用者。那么肯定的 - 有一些做到这一点UNIX命令 - schedule命令在特定时间运行(),或当CPU是免费的(批量)。所以这样做,而不是:

Luckily you give the background info on what you need - a CGI call to initiate some processing that happens independently and to return back to the caller. Well sure - there are unix commands that do just that - schedule command to run at specific time (at) or whenever CPU is free (batch). So do this instead:

import os

os.system("batch <<< '/home/some_user/do_the_due.py'")
# or if you don't want to wait for system idle, 
#   os.system("at now <<< '/home/some_user/do_the_due.py'")

print 'Content-type: text/html\n'
print 'Done!'

和你有它。请记住,如果有一些输出到标准输出/标准错误,将电子邮件发送给用户(这是很好的调试,但其它的脚本也许应该保持安静)。

And there you have it. Keep in mind that if there is some output to stdout/stderr, that will be mailed to the user (which is good for debugging but otherwise script probably should keep quiet).

PS。我只是记得窗口也有与调用的微小修改版本的,这样你就可以在Windows下的Apache的工作太(VS叉技巧,将无法在Windows工作)。

PS. i just remembered that Windows also has version of at, so with minor modification of the invocation you can have that work under apache on windows too (vs fork trick that won't work on windows).

PPS。确保过程运行CGI是不是在 /etc/at.deny 从调度批处理作业排除

PPS. make sure the process running CGI is not excluded in /etc/at.deny from scheduling batch jobs

这篇关于从开始的CGI脚本后台进程/守护进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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