我有一个unix.sh脚本,下面运行一个python程序,可能需要10分钟才能完成一些数据处理,它运行得很好。我想从php网页运行这个脚本。
run_virt_d_py.sh
#! /bin/bash
# activate virtual environment
cd /Users/data/myproject
source bin/activate
# virtualenv is now active
python iterate_dir_analyse_files_1.py
echo "data analysis completed ok"
当在运行osx 10.6的苹果mac上使用命令行从终端手动运行以下命令时,上面的脚本运行得"完美"。下面显示了输入命令后的提示。
[~]% cd myproject
[myproject]% source bin/activate
(myproject)[myproject]% sh run_virt_da_py.sh
然而,当我尝试从php运行.sh脚本时,它失败了,下面的脚本只返回python程序的第一个echo语句,而不返回其他语句。
<html lang="en">
<head>
<title>Data_analysis</title>
</head>
<body>
<?php
echo " data analysis script started ";
echo shell_exec('sh /Users/Data/myproject/run_virt_da_py.sh');
echo "data analysis script may have completed";
?>
</body>
</html>
研究我试过在不使用virtualenv并且没有问题的脚本上使用、system、passthrough、exec、shell_exec。
- 欢迎任何帮助、解决方案、方法或指针。提前谢谢
一些主机,如GoDaddy(在共享主机上),在PHP的exec函数中有限制。
另一点是,您需要配置php.ini以增加超时 我认为你已经达到了你的剧本,但你并没有等着完成。尝试在php顶部添加一些代码来编写一个"Hello world"文件来测试它。max_execution_time = 1200
,默认情况下,php.ini
首先,确保修改php.ini(如果可能)以允许延长执行时间。如果你的脚本花费太长时间,你的脚本可能会终止它。
然后,确保您实际上给了脚本足够的时间来进入shell_exec()
第三,确保安全模式被禁用。
第四,确保您的托管提供商允许shell_exec()或backticks。
公认的答案是正确的,但需要指出的是,virtualenv附带了一个名为activate_this.py
的脚本,该脚本的存在目的是设置一个在web服务器中使用的类似virtualenv的环境。看见https://pypi.python.org/pypi/virtualenv并在该页面中搜索CCD_ 3。然后,您就可以做到这一点,而不必从Web服务器启动子shell来修改环境以运行virtualenv的Python解释器。
为什么要在10分钟内发出web请求?PHP根本不适合这样。我见过一些后台过程,例如,生成要下载的文件,需要很长时间甚至更长的时间才能完成,用户可以等待它,但可以肯定的是,它是不可信的,这个过程可能会因为多种原因而终止(硬件限制、配置限制、网络故障等),甚至更多,在共享中,无论配置如何,服务器都会明确地杀死您的进程。
在专用或VPS中,您可以修改指令并允许脚本永远运行,但问题不在于如何执行,而在于这是否是您需要的方法。也许是,我不说这是绝对禁止的做法,但可能不是。替代方案可能是:
- 让一个cronjob定期运行你的sh。当有web请求时,您可以提供预先计算的数据
- 如果你不想让它经常生成,你可以让它经常运行,但检查它是否必须继续运行,可能是检查数据库或文件,然后当有请求时,从php更改数据库字段或文件的值,这样cron就知道它必须运行
- 让php启动sh,但在异步线程中,因此php执行程序将立即结束,通知用户数据正在处理中,实际进程正在后台运行
这是一种非常常见的方法,你可以在许多网站上看到它,例如在你的服务器上,如果你请求一些重的东西,他们会生成它,并在它准备好时通知你。或者在脸书上,当你想要备份你的数据时,也可以这样做。此外,商业智能系统和分析数据的系统使用后台流程来生成预先计算的数据,因此用户流程可以是轻量级的。
在企业级应用程序中,我使用一个链接来访问上次生成的数据(通知其日期),一个频繁运行的流程,以及一个链接强制立即启动新流程。
这样,你就可以获得一个更可靠的系统,同时最大限度地减少两个用户同时在不同的计算机上分析相同数据的机会,这意味着两个10分钟的过程可以获得相同的数据。
更新
如果你真的不需要让用户实时看到过程的结果,那就更容易了。我不得不说,像crons一样,当系统增长时,它有助于保持流程的有序性和可控性。但是,如果您现在不想要它,您可以尝试直接从php启动后台进程。试试这个代码(我很多年前就用过了,但我想它会起作用的)。适用于unix和windows服务器。
/**
* execute $cmd in the background without PHP waiting for it to finish
*/
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
因此,要开始您的命令,您必须执行以下操作:
<html lang="en">
<head>
<title>Data_analysis</title>
</head>
<body>
<?php
echo " data analysis script started ";
echo execInBackground('sh /Users/Data/myproject/run_virt_da_py.sh');
echo "data analysis script has been started";
?>
</body>
</html>
当然,由于它是在后台线程中运行的,您不直接知道进程何时完成,因此您必须在sh脚本的末尾包含一些常规操作,例如启动另一个php,然后通知您可能需要的进程,例如发送电子邮件、更新数据库等等。