2017-01-10 61 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。 –