2017-01-10 25 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函數應該阻塞,直到您運行的命令完成。即,PHP腳本將停止,等待命令完成,直到你的腳本的其餘部分繼續。我有一半認爲你的服務器正在經歷一個max_execution_time超時,但你已經清楚地表明,即使只是幾秒鐘的時間太長,甚至這些相當短的腳本也遇到了麻煩。

我遇到了一些解決方案。最簡單的方法是更改​​python命令,以便a)將任何輸出路由到文件或輸出流,以及b)該進程在後臺運行。按照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.

我也希望你能充分利用兩個附加的可選參數爲exec函數。

$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命令來解決問題。

編輯:根據crispytx,長腳本導致$ cmd_return_val爲1,這意味着錯誤正在發生。嘗試改變這一行:

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

這個

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

,讓我們知道$ cmd_output的輸出是什麼 - 它應該至少是具有新衍生進程的進程id 。

0

感謝所有幫助S. Imp。我在使用你的建議進行調試時遇到了一些麻煩,因爲我碰巧使用AJAX來調用腳本。然而,我寫了更簡單的腳本使用你的建議來嘗試和調試問題,這是我發現的:

Array([0] => Traceback(最近調用最後一次):[1] => File「/ 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文件中。我不知道這篇文章是否會幫助任何人,但誰知道呢!

[已解決]

+0

很高興你把它整理出來。如果你使用exec,你應該時刻關注return_val。 –