Я пытаюсь выполнить скрипт perl из PHP-скрипта. У меня была эта работа с использованием различных методов, таких как exec, popen и proc_open, но у меня есть пара проблем, вокруг которых старый добрый Google не дает мне ответов.
Мне нужно запустить скрипт .pl (передав одну переменную скрипту, который является числом) из файла php, но остановите PHP-скрипт от ожидания до завершения .pl. (.pl, скорее всего, займет 4-5 часов для запуска на сервере). Я не ожидаю возврата из сценария perl (perl-скрипт записывает свой вывод в mysql db), поэтому мне просто нужно, чтобы он работал на сервере и продолжал скрипт 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 Ive, который он разместил после него (только для тестирования), никогда не выполняется (ive не дождался завершения скрипта perl, чтобы убедиться, что он это делает), поскольку он должен ждать завершения .pl ,
Я вижу 3 варианта:
Используйте fork
в своем скрипте perl, чтобы отменить фактическую работу с родительским процессом, существующим сразу после fork. Однако это может не работать корректно или вообще на Windows, но стоит попробовать.
См. Следующие ссылки « fork
on Windows»:
Если PHP может запустить URL-запрос (похожий на LWP Perl или 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; }
if (-e $flag_file) { unlink $flag_file; do_long_work() } else { exit 0; }
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 в следующий раз, когда планировщик выполнит его.
Есть две возможности
Используйте программу «start». Вы не сможете использовать трубы, а только аргументы командной строки.
Создайте постоянно действующую программу Perl (запустите при запуске или с помощью Win32 :: Daemon). Подключайтесь к нему с помощью сокетов или http. Это легко, поскольку на CPAN имеется много готовых серверов
Кроме того, возможно, это возможно сделать из другой программы Perl с использованием Win32 :: Job или Win32 :: Process или другого модуля CPAN.
Недавно я опубликовал модуль для таких задач: Win32 :: Detached
Добавьте его в свой Perl-скрипт, и он будет демоннизироваться, позволяя вашему скрипту PHP двигаться дальше.
Спасибо всем, кто ответил на этот вопрос. После долгих исследований и возиться с различными решениями, я наконец получил кое-что, чтобы работать и удовлетворить наши потребности. Это далеко не идеально, но эй, это работает, поэтому я не собираюсь жаловаться слишком много.
Поскольку это похоже на то, что другие люди хотят знать, Id Id делится моим решением.
Я загрузил крошечную программу под названием Hstart (40kb) отсюда: http://www.ntwind.com/software/utilities/hstart.html
Я извлек файлы в c: \ windows \ system32.
Программа hstart имеет возможность запускать пакетные файлы без открытия командного окна. Он не будет работать напрямую с файлом .pl, поэтому мне пришлось создать .bat для вызова .pl следующим образом.
создал файл .bat в том же каталоге, что и мой .pl-файл, который в основном называется perl-скриптом, используя локально установленный perl и передающий переменную. Как показано здесь:
perl script.pl% 1
В моем скрипте PHP я использовал следующую команду для вызова моего файла perl.
$ cmd = 'hstart / NOCONSOLE "run.bat'. $ id. '"> log.log'; Exec ($ CMD);
Запуск php-файла заставляет hstart открываться с помощью noconsole из-за установленного флага, откройте файл perl с $ id, который я передал как переменная, и отправьте весь вывод скрытого окна консоли в log.log, как указано в моей команде. Все, что я вижу, это perl.exe, запущенный в моем диспетчере задач.
Как я сказал, далека от совершенства, но он работает.