Запустите perl-файл из PHP-скрипта, но не ждите вывода на Windows Server

Я пытаюсь выполнить Perl-скрипт из PHP-скрипта. У меня это работало с использованием различных методов, таких как exec, popen и proc_open, но у меня есть пара проблем, на которые старый добрый Google не дает мне ответов.

Мне нужно запустить скрипт.pl (передавая одну переменную скрипту, который является числом) из файла php, но не позволяя сценарию php ждать, пока не закончится.pl (.pl может занять 4-5 часов. запустить на сервере). Я не ожидаю каких-либо возвращаемых выходных данных от сценария perl (сценарий perl записывает свой вывод в базу данных mysql), поэтому мне просто нужно, чтобы он работал на сервере и позволил сценарию php продолжить работу.

Есть некоторые барьеры, которые нужно преодолеть, поскольку он работает на компьютерах с Windows, работающих под управлением Apache, PHP, MySQL.

Я думаю, что я видел решение для Linux, но оно должно оставаться на машине Windows.

Сейчас я пытаюсь использовать метод proc_open, используя следующий код (35 в строке proc_open - это идентификатор теста, который мне нужно передать в скрипт perl):

$descriptorspec = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("file","./error.log","a")
) ;

proc_close(proc_open('perl perlscript.pl 35', $descriptorspec, $pipes));

$i = 0;
while ($i < 1000) {
   echo ++$i;  
}

Теперь этот код выполняет сценарий perl, но размещенный после него цикл while, помещенный после него (только для тестирования), никогда не выполняется (я не ждал, пока завершится сценарий perl, чтобы убедиться, что он работает), поскольку он должен ожидать завершения.pl.,

4 ответа

Решение

Спасибо всем, кто ответил на этот вопрос. После долгих исследований и работы с различными решениями я, наконец, нашел что-то для работы и удовлетворения наших потребностей. Это далеко от совершенства, но эй, это работает, поэтому я не собираюсь жаловаться слишком много.

Поскольку это, кажется, то, что другие люди хотят знать, я подумал, что я поделюсь своим решением

  1. Я скачал крошечную программу под названием Hstart (40kb) отсюда: http://www.ntwind.com/software/utilities/hstart.html

  2. Я распаковал файлы в c:\windows\system32.

Программа hstart имеет возможность запускать пакетные файлы без открытия окна команд. Он не будет вызывать файл.pl напрямую, поэтому мне пришлось создать.bat для вызова.pl следующим образом.

  1. создал файл.bat в том же каталоге, что и мой файл.pl, который в основном вызывал скрипт perl, используя локально установленный perl и передавая переменную. Как показывают здесь:

    perl script.pl% 1

  2. В моем PHP-скрипте я использовал следующую команду для вызова моего perl-файла.

    $ cmd = 'hstart / NOCONSOLE "run.bat'. $id. '"> log.log'; Exec($ CMD);

  3. Запуск файла php приводит к тому, что hstart открывается с помощью noconsole из-за установленного флага, открывает файл perl с $id, который я передал в качестве переменной, и отправляет весь вывод скрытого консольного окна в log.log, как указано в моей команде. Все, что я вижу, это perl.exe, запущенный в моем диспетчере задач.

Как я сказал далеко не идеально, но это работает.

Я недавно опубликовал модуль для таких задач: Win32:: Detached

Добавьте его в свой Perl-скрипт, и он будет демонизироваться, позволяя вашему PHP-скрипту двигаться дальше.

Есть две возможности

  1. Используйте программу "Пуск". Вы не сможете использовать каналы, только аргументы командной строки.

  2. Создайте постоянно работающую программу Perl (запускается при запуске или с использованием Win32::Daemon). Подключитесь к нему с помощью сокетов или http. Это легко, так как на CPAN достаточно готовых серверов.

Кроме того, это может быть возможно сделать из другой Perl-программы, используя Win32::Job или Win32::Process или какой-либо другой CPAN-модуль.

Я вижу 3 варианта:

  • использование fork в вашем Perl-скрипте отключить фактическую работу с родительским процессом, существующим сразу после fork. Это может работать некорректно или вообще не работать в Windows, но стоит попробовать.

    Пожалуйста, смотрите следующее "fork на Windows "ссылки:

  • Если PHP может запустить запрос URL (аналогично Perl LWP или wget), преобразуйте ваш Perl-скрипт в CGI-скрипт (тривиальный), вставьте в каталог CGI вашего Apache и вызовите его через правильный URL-адрес для http://localhost/..., Затем тайм-аут запроса URL с помощью некоторого внутреннего тайм-аута PHP или обычного тайм-аута HTTP в худшем случае. В ДЕЙСТВИТЕЛЬНО худшем случае проделайте тот же трюк из кода Perl, поскольку Perl может определенно поддерживать как URL-вызов через библиотеки LWP, так и тайм-аут через alarm()

  • Пусть планировщик запускает ваш Perl-скрипт каждые X минут. Сценарий должен начинаться со следующей логики: if (-e $flag_file) { unlink $flag_file; do_long_work() } else { exit 0; } где $flag_file это специальное местоположение на сервере (скажем, C:\temp\myscript_start_perl.txt), а также do_long_work() содержит фактическую работу, которая должна быть сделана.

    Затем, когда PHP-скрипт должен запустить Perl-скрипт, он просто создает пустой файл флага (то же самое C:\temp\myscript_start_perl.txt), что будет замечено скриптом Perl в следующий раз, когда планировщик выполнит его.

Другие вопросы по тегам