Как я могу разветвить фоновые процессы из CGI-скрипта Perl в Windows?
У меня были некоторые проблемы с разветвлением процессов из сценария Perl CGI при работе в Windows. Кажется, основная проблема заключается в том, что "fork" эмулируется при запуске в Windows, и на самом деле, похоже, не создает новый процесс (просто другой поток в текущем). Это означает, что веб-серверы (такие как IIS), которые ожидают завершения процесса, продолжают ждать, пока не завершится "фоновый" процесс.
Есть ли способ отключить фоновый процесс из CGI-скрипта под Windows? Еще лучше, есть ли одна функция, которую я могу вызвать, которая сделает это кроссплатформенным способом?
(И просто для того, чтобы сделать жизнь более сложной, я действительно хотел бы хороший способ перенаправить вывод разветвленных процессов в файл одновременно).
5 ответов
Если вы хотите сделать это независимо от платформы, лучше всего использовать Proc::Background.
Используйте Win32::Process->Create с параметром DETACHED_PROCESS
Я обнаружил реальные проблемы с fork() в Windows, особенно при работе с объектами Win32 в Perl. Таким образом, если это будет зависеть от Windows, я действительно рекомендую вам взглянуть на библиотеку Thread в Perl.
Я использую это для получения хорошего эффекта, принимая более одного подключения за раз на веб-сайтах, использующих IIS, а затем использую еще больше потоков для одновременного выполнения различных сценариев.
Этот вопрос очень старый, и принятый ответ правильный. Тем не менее, я просто заставил это работать, и решил добавить больше подробностей о том, как это сделать для всех, кому это нужно.
Следующий код существует в очень большом 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)
Я уверен, что случайное число, сгенерированное и прикрепленное к pid, излишне, но я не заинтересован в создании проблем, которых очень легко избежать. Надеюсь, это поможет кому-то, желающему сделать то же самое. Не забудьте добавить use Proc::Daemon
вверху вашего скрипта отразите код и измените пути и имена вашей программы, и вы должны быть в порядке.
Perl предоставляет ключевое слово fork(), которое соответствует системному вызову Unix с тем же именем. На большинстве Unix-подобных платформ, где доступен системный вызов fork(), Perl fork() просто вызывает его.
На некоторых платформах, таких как Windows, где системный вызов fork() недоступен, Perl может быть построен для эмуляции fork() на уровне интерпретатора. Хотя эмуляция спроектирована так, чтобы быть максимально совместимой с реальной функцией fork() на уровне программы Perl, существуют определенные важные различия, связанные с тем фактом, что все псевдо-дочерние `` процессы '', созданные таким образом, работают в том же реальном процессе, что касается операционной системы.