如何从 Windows 上的 Perl CGI 脚本派生后台进程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45792/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I fork a background processes from a Perl CGI script on Windows?
提问by Matt Sheppard
I've had some trouble forking of processes from a Perl CGI script when running on Windows. The main issue seems to be that 'fork' is emulated when running on windows, and doesn't actually seem to create a new process (just another thread in the current one). This means that web servers (like IIS) which are waiting for the process to finish continue waiting until the 'background' process finishes.
在 Windows 上运行时,我在从 Perl CGI 脚本分叉进程时遇到了一些麻烦。主要问题似乎是在 Windows 上运行时模拟了“fork”,并且实际上似乎并没有创建新进程(只是当前进程中的另一个线程)。这意味着等待进程完成的 Web 服务器(如 IIS)将继续等待,直到“后台”进程完成。
Is there a way of forking off a background process from a CGI script under Windows? Even better, is there a single function I can call which will do this in a cross platform way?
有没有办法在 Windows 下从 CGI 脚本中分出后台进程?更好的是,是否有我可以调用的单个函数以跨平台方式执行此操作?
(And just to make life extra difficult, I'd really like a good way to redirect the forked processes output to a file at the same time).
(为了让生活变得更加困难,我真的很想要一种将分叉进程输出同时重定向到文件的好方法)。
回答by Leon Timmermans
If you want to do this in a platform independent way, Proc::Backgroundis probably the best way.
如果您想以独立于平台的方式执行此操作,Proc::Background可能是最好的方法。
回答by aku
Use Win32::Process->Createwith DETACHED_PROCESS parameter
使用Win32::Process->Createwith DETACHED_PROCESS 参数
回答by Espo
叉子:
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.
Perl 提供了一个 fork() 关键字,对应于同名的 Unix 系统调用。在 fork() 系统调用可用的大多数类 Unix 平台上,Perl 的 fork() 只是调用它。
在 fork() 系统调用不可用的某些平台(例如 Windows)上,可以构建 Perl 以在解释器级别模拟 fork()。虽然仿真被设计为尽可能与 Perl 程序级别的真实 fork() 兼容,但存在某些重要差异,因为所有以这种方式创建的伪子“进程”都存在就操作系统而言,在相同的真实进程中。
回答by Spedge
I've found real problems with fork() on Windows, especially when dealing with Win32 Objects in Perl. Thus, if it's going to be Windows specific, I'd really recommend you look at the Thread library within Perl.
我在 Windows 上发现了 fork() 的真正问题,尤其是在处理 Perl 中的 Win32 对象时。因此,如果它是特定于 Windows 的,我真的建议您查看 Perl 中的 Thread 库。
I use this to good effect accepting more than one connection at a time on websites using IIS, and then using even more threads to execute different scripts all at once.
我用它来很好地在使用 IIS 的网站上一次接受多个连接,然后使用更多线程一次执行不同的脚本。
回答by Jeffrey Tackett
This question is very old, and the accepted answer is correct. However, I just got this to work, and figured I'd add some more detail about how to accomplish it for anyone who needs it.
这个问题很老了,接受的答案是正确的。但是,我刚刚开始使用它,并认为我会为需要它的任何人添加一些有关如何完成它的更多详细信息。
The following code exists in a very large perl CGI script. This particular sub routine creates tickets in multiple ticketing systems, then uses the returned ticket numbers to make an automated call via Twilio services. The call takes awhile, and I didn't want the CGI users to have to wait until the call ended to see the output from their request. To that end, I did the following:
以下代码存在于一个非常大的 perl CGI 脚本中。这个特定的子例程在多个票务系统中创建票,然后使用返回的票号通过 Twilio 服务进行自动调用。调用需要一段时间,我不希望 CGI 用户必须等到调用结束才能看到他们请求的输出。为此,我做了以下工作:
(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)
I am sure that the random number generated and attached to the pid is overkill, but I have no interest in creating issues that are extremely easily avoided. Hopefully this helps someone looking to do the same sort of thing. Remember to add use Proc::Daemon
at the top of your script, mirror the code and alter to the paths and names of your program, and you should be good to go.
我确信生成并附加到 pid 的随机数是矫枉过正的,但我对创建极易避免的问题没有兴趣。希望这可以帮助那些想做同样事情的人。请记住use Proc::Daemon
在脚本的顶部添加,镜像代码并更改程序的路径和名称,您应该很高兴。