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

查看:55
本文介绍了从 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.

一位同事告诉我,我想做的事情是不可能的,因为没有办法阻止 Apache 等待 CGI 脚本的整个进程树死亡.但是,我还在网络上看到了许多关于双叉"技巧的参考,该技巧应该可以完成这项工作.this Stack Overflow answer中简洁地描述了这个技巧,但我在其他地方看到过类似的代码.

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')

如果我从 shell 运行它,它完全符合我的预期:原始脚本和第一个后代死亡,而第二个后代继续运行,直到它被手动杀死.但是如果我通过 CGI 访问它,页面将不会加载,直到我杀死第二个后代或 Apache 由于 CGI 超时而杀死它.我也试过用 os._exit(0) 替换第二个 sys.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.

我做错了什么?

推荐答案

不要 fork - 单独运行批处理

这种双分叉方法是某种黑客行为,对我来说这表明不应该这样做:).无论如何,对于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 命令可以做到这一点 - 安排命令在特定时间(at)或 CPU 空闲时(batch)运行.所以改为这样做:

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!'

这就给你了.请记住,如果有一些输出到 stdout/stderr,它将通过邮件发送给用户(这有利于调试,否则脚本可能应该保持安静).

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).

附注.我只记得 Windows 也有 at 的版本,所以只要稍微修改一下调用,你也可以在 Windows 上的 apache 下工作(与不会的 fork 技巧相比)在 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.确保 /etc/at.deny 中不排除运行 CGI 的进程调度批处理作业

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

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

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