我想从cgi调用中派生后台进程。这样httpd调用立即返回,其余的东西一直在运行
在我们迁移到新机器之前,这一直都是这么做的
............
## Close the http connection so that the remote client returns
close STDOUT;
close STDERR;
POSIX::setsid();
fork() && exit;
do_job();
.........
现在在新机器上,相同的代码永远不会执行do_job() Perl,httpd版本是相同的(有一个小的内核升级)
现在我将代码更改为
..........
open(STDOUT,">/dev/null");
open(STDERR,">/dev/null");
POSIX::setsid();
fork() && exit;
do_job();
.........
这有效,但我不确定为什么
答案 0 :(得分:1)
我不太确定为什么第一个代码会起作用。但是你应该总是在fork()之后放置setsid。如果你这样做之后它不起作用,请告诉我。
每个进程组都在一个唯一的会话中。 (创建进程时,它将成为其父进程的成员。)按照惯例,会话的会话ID等于会话的第一个成员的进程ID,称为会话负责人。进程使用系统调用getsid()来查找其会话的ID。
创建一个新会话
pid = setsid();
仅当当前流程不是流程组负责人时才允许这样做。
让我解释一下原因。假设您是进程组组长或会话负责人,您必须了解进程组和会话ID是从创建它们的进程的进程ID初始化的(然后引导它们,即对于会话领导者pid == sid和进程)组长pid == pgid)。此外,进程组不能在会话之间移动。
这意味着如果您是流程组负责人,并且允许创建新会话,那么sid和pgid将设置为您的pid,使旧流程组中的其他流程处于奇怪的状态:他们的流程小组长突然处于不同的会话中,然后他们自己可能会。而这是不允许的,因此内核返回了EPERM。
现在如果你fork()一旦既不是会话也不是进程组长,那么将你的sid和pgid设置到你的pid是安全的,因为这样的组中没有其他进程。
以下链接可能会有所帮助:
答案 1 :(得分:0)
我建议您使用处理此类工作的外部队列。您可以使用一些CPAN模块来获得此功能,例如Queue::DBI或其他,如Gearman