2017-01-10 4 views
0

У меня возникли проблемы с использованием функции PHP exec(). Всякий раз, когда скрипт, который я пытаюсь запустить, короток, exec() работает отлично. Но если сценарий занимает больше секунды или около того, он терпит неудачу. Обратите внимание: я попытался запустить длинный скрипт вручную в командной строке, и он работает отлично. Кажется, интерпретатор PHP убивает мой внешний скрипт, если ему требуется больше секунды или около того для запуска. Любые мысли или предложения? Вот мой код:Функция PHP exec() работает только с очень короткими сценариями Python

<?php 
    $fileName = "foobar.docx"; 
    $argVar = $fileName; 
    exec("python3 /var/www/html/jan8/alexandrina.py /var/www/html/jan8/$argVar"); 
    echo "$output"; 
?> 

А вот мой сценарий:

#!/usr/bin/env python3 

import docx 
import sys 

docxFile = "".join(sys.argv[1:]) 

# The Three Lines Below Create a New Variable "htmlFile" 
# "htmlFile" is the same as "docxFile", except ".docx" is cut off 
# and replaced with ".html" 
myNumber = len(docxFile) - 5 
htmlFile = docxFile[0:myNumber] 
htmlFile = htmlFile + '.html' 

def generateHTML(filename): 
    doc = docx.Document(filename) 
    fullText = [] 
    for para in doc.paragraphs: 
     fullText.append('<p>') 
     fullText.append(para.text) 
     fullText.append('</p>') 
     fullText.append('\n') 
    return '\n'.join(fullText) 

file = open(htmlFile, "w") 
file.write(generateHTML(docxFile)) 
file.close() 

print("end python script") 

Дополнительные примечания: Я увеличил максимальные сроки выполнения в php.ini, но я не думаю, что должно иметь значения, так как «длинный сценарий» должен занимать всего несколько секунд. Кроме того, когда я ссылаюсь на «короткий сценарий» и «длинный скрипт», я на самом деле ссылаюсь на тот же скрипт. Разница между «длинным сценарием» и «коротким скриптом» - это просто время для выполнения, так как оно может меняться в зависимости от размера файла, который я прошу обработать сценарий. Во всяком случае ... любые предложения действительно будут оценены!

+0

Что произойдет, если вы наберете команду python в командной строке? Немедленно возвращается ли сообщение? Или вам нужно дождаться завершения скрипта python, прежде чем вы сможете ввести другую команду? –

+0

Если я запускаю скрипт python в командной строке, он работает отлично. – crispytx

+0

Да, но когда вы запускаете из командной строки - как только вы нажмете «enter» после ввода команды, она вернется немедленно или вам нужно подождать, пока завершится длительный процесс python? –

ответ

1

Обычно функция php exec должна блокироваться до тех пор, пока выполняемая вами команда не завершится. I.e., скрипт PHP остановится, ожидая завершения команды, пока не продолжит работу с остальным вашим скриптом. Я наполовину думал, что ваш сервер испытывает таймаут max_execution_time, но вы ясно заявили, что даже за пару секунд слишком много, и даже у этих довольно коротких скриптов возникают проблемы.

Несколько решений происходят со мной. Самый простой - это изменить команду python, чтобы: а) любой выход был перенаправлен в файл или выходной поток; б) процесс запускается в фоновом режиме. Согласно docs on exec:

If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

Я также хотел бы, чтобы использовать два дополнительных необязательных параметров для ехес функции.

$fileName = "foobar.docx"; 
$argVar = $fileName; 
$cmd = "python3 /var/www/html/jan8/alexandrina.py /var/www/html/jan8/$argVar"; 
// modify your command to toss output, background the process, and output the process id 
$cmd_modified = $cmd . " >/dev/null & echo \$!"; 
$cmd_output = NULL; // this will be an array of output 
$cmd_return_value = NULL; // this will be the return value of the script 
exec($cmd_modified, $cmd_output, $cmd_return_value); 
echo "exec has completed</br>"; 
echo "output:<br>" . print_r($cmd_output, TRUE) . "<br>"; 
echo "return value: " . print_r($cmd_return_value, TRUE); 

Это может помочь или нет. Если это не так, мы все же можем решить проблему, используя команды posix.

EDIT: в соответствии с crispytx длинные скрипты приводят к $ cmd_return_val 1, что означает, что происходит ошибка. Попробуйте изменить одну строку:

$cmd_modified = $cmd . " >/dev/null & echo \$!"; 

этой

$cmd_modified = $cmd . " & echo \$!"; 

И дайте нам знать, что выход $ cmd_output - это должно, по крайней мере, иметь идентификатор процесса вновь порожденного процесса ,

0

Спасибо за помощь S. Imp. У меня была небольшая проблема с отладкой с помощью ваших предложений, потому что я случайно использовал AJAX для вызова сценария. Однако я написал более простой скрипт, используя ваши предложения, чтобы попытаться отладить проблему, и вот что я нашел:

Array ([0] => Traceback (последний последний вызов): [1] => Файл "/ var /www/html/jan8/alexandrina.py ", строка 28, в [2] => file.write (generateHTML (docxFile)) [3] => UnicodeEncodeError: кодек ascii не может кодировать символ '\ u2026' в позиции 25: порядковый номер не в диапазоне (128))

Итак, похоже, что проблема связана с кодировкой ascii!Несмотря на то, что более крупный файл был только файлом docx с тем же текстом, что и более короткий файл docx, повторяющийся снова и снова на 300 страниц. Кажется, что если файл docx превышает 1 страницу, вставляются символы ascii, которые не присутствуют в файлах docx одной страницы. Я понятия не имею, будет ли этот пост когда-либо помогать кому-либо, но кто знает!

[SOLVED]

+0

Рад, что вы разобрали его. Если вы используете exec, вы всегда должны обратить внимание на return_val. –