如何从Windows上的Perl CGI脚本分叉后台进程?

时间:2022-12-07 22:12:21

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

(只是为了让生活变得更加困难,我真的想要一个将分叉进程输出重定向到文件的好方法)。

5 个解决方案

#1


9  

If you want to do this in a platform independent way, Proc::Background is probably the best way.

如果您想以独立于平台的方式执行此操作,Proc :: Background可能是最好的方法。

#2


3  

Use Win32::Process->Create with DETACHED_PROCESS parameter

使用Win32 :: Process-> Create with DETACHED_PROCESS参数

#3


0  

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.

Perl提供了一个fork()关键字,它对应于同名的Unix系统调用。在大多数类似于Unix的平台上,fork()系统调用可用,Perl的fork()只是调用它。

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.

在某些平台上,例如Windows(其中fork()系统调用不可用),可以构建Perl以在解释器级别模拟fork()。虽然仿真被设计为与Perl程序级别的真实fork()尽可能兼容,但是存在某些重要的差异,这些差异源于所有伪子“进程”以这种方式创建的事实就操作系统而言,在相同的实际过程中。

#4


0  

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的网站上同时接受多个连接,然后使用更多线程同时执行不同的脚本。

#5


0  

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的随机数是过度的,但我没有兴趣创建极易避免的问题。希望这可以帮助那些想要做同样事情的人。记得在脚本的顶部添加使用Proc :: Daemon,镜像代码并改变程序的路径和名称,你应该好好去。

#1


9  

If you want to do this in a platform independent way, Proc::Background is probably the best way.

如果您想以独立于平台的方式执行此操作,Proc :: Background可能是最好的方法。

#2


3  

Use Win32::Process->Create with DETACHED_PROCESS parameter

使用Win32 :: Process-> Create with DETACHED_PROCESS参数

#3


0  

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.

Perl提供了一个fork()关键字,它对应于同名的Unix系统调用。在大多数类似于Unix的平台上,fork()系统调用可用,Perl的fork()只是调用它。

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.

在某些平台上,例如Windows(其中fork()系统调用不可用),可以构建Perl以在解释器级别模拟fork()。虽然仿真被设计为与Perl程序级别的真实fork()尽可能兼容,但是存在某些重要的差异,这些差异源于所有伪子“进程”以这种方式创建的事实就操作系统而言,在相同的实际过程中。

#4


0  

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的网站上同时接受多个连接,然后使用更多线程同时执行不同的脚本。

#5


0  

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的随机数是过度的,但我没有兴趣创建极易避免的问题。希望这可以帮助那些想要做同样事情的人。记得在脚本的顶部添加使用Proc :: Daemon,镜像代码并改变程序的路径和名称,你应该好好去。