当前位置: 首页 > 面试题库 >

从CGI脚本启动后台进程/守护程序

汝和裕
2023-03-14
问题内容

我正在尝试从CGI脚本启动后台进程。基本上,提交表单时,CGI脚本将向用户指示他或她的请求正在处理中,而后台脚本则进行实际处理(因为该处理往往会花费很长时间。)我面临的问题是Apache不会在子脚本终止之前将父CGI脚本的输出发送到浏览器。

一位同事告诉我,我想做的事情是不可能的,因为无法阻止Apache等待CGI脚本的整个过程树消失。但是,我在网络上也看到了很多关于“双叉”技巧的参考资料,这些技巧本来可以做到的。

这是我编写的用于测试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),但没有任何区别。

我究竟做错了什么?


问题答案:

不要分叉-单独运行批处理

这种双重分叉的方法是一种hack,对我而言,这表明不应该这样做:)。无论如何对于CGI。根据一般原则,如果某件事太难完成,那么您可能会错误地进行处理。

幸运的是,您提供了所需信息的背景信息-一个CGI调用,以启动一些独立发生的处理并返回给调用者。可以肯定-有unix命令就是这样做的-
计划命令在特定时间(at)或每当CPU空闲(batch)时运行。因此改为:

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,它将被发送给用户(这对于调试非常有用,但是脚本可能应该保持安静)。

PS。我只是记得 Windows 也具有的版本at,因此,只需稍加修改调用,您就可以在Windows上的apache下进行该工作(vs
fork技巧在Windows上不起作用)。

PPS。确保/etc/at.deny计划批处理作业中不排除运行CGI的进程



 类似资料:
  • 首先,我在删除后下载了lquidbounce的源代码。gradle和我发布了代码信息,希望你们能帮我

  • 当我试图在Android Studio中导入一个gradle项目时,我遇到了以下错误。 这是我看到的输出: 我已经关闭了在SO中的解决方案中提到的防病毒软件。但是似乎什么都不起作用。

  • 错误:无法启动守护进程。此问题可能是由不正确的守护程序配置引起的。例如,使用无法识别的 jvm 选项。请参阅守护程序的用户指南章节,http://gradle.org/docs/1.12/userguide/gradle_daemon.html VM初始化期间发生错误无法为对象堆保留足够的空间无法创建Java虚拟机。

  • Android版本:1.2.2 它显示错误:无法启动守护进程。此问题可能是由于守护进程配置不正确造成的。例如,使用了无法识别的jvm选项。请参阅《用户指南》中关于守护进程的一章,网址为:http://gradle.org/docs/2.2.1/userguide/gradle_daemon.html VM 初始化期间发生错误 无法为对象堆保留足够的空间 错误: 无法创建 Java 虚拟机。错误:发

  • 问题内容: 我的python脚本可以产生一个将无限期运行的进程吗? 我对python或生成的守护进程不太熟悉,因此我对此进行了总结: 该进程继续运行经过python.exe,但是一旦关闭cmd窗口,该进程便被关闭。 问题答案: 使用答案Janne Karila指出,这是一种可以运行一个流程的方法,该流程在其父级死亡时不会死亡,而无需使用该模块。 是传递到基础CreateProcess函数的流程创建

  • 守护(Daemon)进程 我们可以认为守护进程就是后台服务进程,因为它会有一个很长的生命周期提供服务,关闭终端不会影响服务,也就是说可以忽略某些信号。 实现守护进程 首先要保证进程在后台运行,可以在启动程序后面加&,当然更原始的方法是进程自己fork然后结束父进程。 if (pid=fork()) { exit(0); // Parent process } 然后是与终端、进程组、会话(Ses