在Windows上运行时,从Perl CGI脚本分叉进程时遇到了一些麻烦。 主要问题似乎是在Windows上运行时模拟了" fork",实际上似乎并没有创建一个新进程(只是当前进程中的另一个线程)。 这意味着等待进程完成的Web服务器(如IIS)将继续等待,直到"后台"进程完成。
有没有办法在Windows下从CGI脚本派生后台进程? 更好的是,有没有一个我可以调用的函数可以跨平台实现?
(而且,为了使生活变得更加困难,我真的很想一个很好的方法同时将派生的进程输出重定向到文件中)。
如果要以独立于平台的方式执行此操作,则Proc :: Background可能是最好的方式。
使用Win32 :: Process-> Create with DETACHED_PROCESS参数
这个问题很老了,被接受的答案是正确的。但是,我只是使它起作用,并认为我会为需要它的人添加一些有关如何完成它的更多详细信息。
以下代码存在于非常大的perl CGI脚本中。这个特定的子例程在多个票务系统中创建票证,然后使用返回的票证编号通过Twilio服务进行自动呼叫。调用需要一段时间,并且我不希望CGI用户必须等到调用结束才能看到他们请求的输出。为此,我做了以下工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| (All the CGI code that is standard stuff. Calls the subroutine needed, and then)
my $randnum = int(rand(100000));
my $callcmd = $progdir_path ."/aoff-caller.pl --uniqueid $uuid --region $region --ticketid $ticketid";
my $daemon = Proc::Daemon->new(
work_dir => $progdir_path,
child_STDOUT => $tmpdir_path . '/stdout.txt',
child_STDERR => $tmpdir_path . '/stderr.txt',
pid_file => $tmpdir_path . '/' . $randnum . '-pid.txt',
exec_command => $callcmd,
);
my $pid = $daemon->Init();
exit 0;
(kill CGI at the appropriate place) |
我确信生成并附加到pid的随机数会过大,但是我对创建非常容易避免的问题没有兴趣。希望这可以帮助想要做同样事情的人。记住要在脚本顶部添加use Proc::Daemon,镜像代码并更改为程序的路径和名称,您应该一切顺利。
我在Windows上发现了fork()的真正问题,尤其是在Perl中处理Win32对象时。因此,如果要特定于Windows,我真的建议您查看Perl中的Thread库。
我使用此方法效果很好,一次可以在使用IIS的网站上接受多个连接,然后使用更多的线程一次执行所有不同的脚本。
perlfork:
Perl provides a fork() keyword that
corresponds to the Unix system call of
the same name. On most Unix-like
platforms where the fork() system call
is available, Perl's fork() simply
calls it.
On some platforms such as Windows
where the fork() system call is not
available, Perl can be built to
emulate fork() at the interpreter
level. While the emulation is designed
to be as compatible as possible with
the real fork() at the the level of
the Perl program, there are certain
important differences that stem from
the fact that all the pseudo child
``processes'' created this way live in
the same real process as far as the
operating system is concerned.