PHP脚本没有理由突然停止工作

时间:2012-12-30 11:28:18

标签: php mysql linux apache shell

我正在运行一个大的PHP脚本,它可能需要一整天来完成它的工作,
这个脚本从MySQL数据库中获取数据并将其与curl一起用来测试东西......它用 40,000 记录来实现..
因此,为了使它在后台运行,只要它需要,我使用终端执行它..在PHP脚本本身它有这些设置,以确保它运行尽可能长,直到它完成:

set_time_limit(0); // run without timeout limit

因为我从另一个单独的PHP脚本执行它,所以我使用这个函数

ignore_user_abort(1); // ignore my abort

因为直接从命令行执行它,它会给我两个选择..
1)等到脚本完成2)取消整个过程

在搜索之后,有一篇文章给了我第三个选择,它可以在后台运行它,尽可能通过创建一个外部PHP脚本来在后台执行主要的BIG PHP脚本这个功能:

exec("php bigfile.php");

这意味着我可以正常地从浏览器打开此外部页面并毫无顾虑地退出,因为ignore_user_abort将使其在后台运行.. 这仍然不是问题

问题是......在一段未知的时间之后,脚本停止工作.. 我怎么知道?我告诉它在外部文件中写下它工作的每条记录的当前日期时间在,所以我每次刷新到该外部页面,看它是否停止更新,

在一个未知的时期之后它实际上没有任何理由停止,脚本没有任何说停止或任何东西..如果发生任何错误,我告诉它跳过记录(没有错误发生,他们都在同一工作如果一个人工作,那么所有人都应该工作)

然而,我的主要疑虑如下:

  • Apache有超时杀死它
  • 这不是在后台执行PHP脚本的正确方法
  • 某处有超时,无论是在PHP还是Apache或( MySQL !?)中      这就是我最大的疑问.. MySQL ,是否会停止从while向PHP循环提供记录?如果发生错误,它会崩溃整个脚本吗?在崩溃整个脚本的任何事情上是否有任何超时?

如果这些都不适用于它,有没有办法记录脚本现在正在发生什么?或者为什么会崩溃?记录所有内容的详细方法?

<小时/> 更新

我在messages中的/var/log/文件中找到了这个:

Dec 29 16:29:56 i0sa shutdown[5609]: shutting down for system halt
Dec 29 16:30:14 i0sa exiting on signal 15
Dec 29 16:30:28 i0sa syslogd 1.5.0#6: restart.
Dec 29 16:50:28 i0sa -- MARK --
            .....
Dec 29 18:50:31 i0sa -- MARK --
Dec 29 19:02:36 i0sa shutdown[3641]: shutting down for system halt
Dec 29 19:03:11 i0sa exiting on signal 15
Dec 29 19:03:48 i0sa syslogd 1.5.0#6: restart.

它说系统暂停..我会尽力确保这可能是在未来的崩溃和匹配时间,这可能导致它?为什么? memory_limit是128M而我有2GB服务器内存ram,这可能是吗?

P.S。:我手动多次重启服务器..但是这个说关机并停止了?

9 个答案:

答案 0 :(得分:5)

对于这种情况,我使用成功nohup命令,如下所示:

nohup php  /home/cron.php >/dev/null  2>&1 &

如果脚本运行时,您可以检查:

jobs -l

注意: 当您使用nohup命令路径时,php文件必须绝对不是相对的。 我认为从一个php文件调用另一个php文件只是为了防止执行在完成工作之前停止是不是很优雅。

外部参考: http://en.wikipedia.org/wiki/Nohup

还要确保脚本中没有内存泄漏,这会导致脚本在一段时间后崩溃,因为“内存不足”。

答案 1 :(得分:2)

你尝试过使用nohup吗?

exec("nohup php bigfile.php &");

如果你的主机允许nohup命令,那么命令应该在后台运行,并且调用exec的脚本应该立即继续。

答案 2 :(得分:1)

Osa,你的Apache很可能已经杀了这个,我可以详细了解可能的原因,正如其他人肯定会的那样。 我宁愿回答您的问题,而不是您的问题,并建议您使用tmux来完成您描述的任务(或screen如果tmux不可用)。

所以你要做的就是打开tmux并从那里开始编写脚本。与ctrl-b d分离,稍后与tmux attach重新合并以查看它有多远。分离时,您可以在不停止的情况下退出。

简要介绍其他tmux内容,您还不需要,但可以帮助您了解方法http://victorquinn.com/blog/2011/06/20/tmux/ 或以后 http://blog.hawkhost.com/2010/06/28/tmux-the-terminal-multiplexer/非常好

答案 3 :(得分:0)

执行时间不是唯一要考虑的事情。接下来可能的罪魁祸首是脚本超过max_memory_limit

您是否检查/启用了错误记录?可能会默默地失败。

答案 4 :(得分:0)

如果您使用Apache,则会有大约300秒的超时。定期调用apache_reset_timeout();可以允许脚本永久运行,如果你不停止它。

答案 5 :(得分:0)

首先我遇到了这个问题并解决但我想强调你的MySQL服务器不负责这个挂起只需要在Apache中更改一些设置。在PHP文件的上面这些下面的行

ini_set('max_execution_time', 1000);
ini_set('memory_limit', '50M');
set_time_limit(0); 

并且每个提取数据应使用:

$url_class = $URL_path;
//open connection
$ch_school_class = curl_init();
curl_setopt($ch_school_class, CURLOPT_URL, $url_class);
$result_school_class = curl_exec($ch_school_class);
//clean up
curl_close($ch_school_class);

//Each fetch like this 
$url_class = $URL_path;
//open connection
$ch_school_class = curl_init();
curl_setopt($ch_school_class, CURLOPT_URL, $url_class);
$result_school_class = curl_exec($ch_school_class);
//clean up
curl_close($ch_school_class);

答案 6 :(得分:0)

1:考虑使用popen()pclose()等在外部运行PHP脚本。

2:您可以使用multi curl handler

缩短cURL请求的长度

3:如果可能,您应该尝试使用其他语言。众所周知,PHP对于较大的任务来说相当慢。为什么全部花费一整天才能在最短的几个小时内完成(我说几个小时,因为它必须向40,000个不同的地址发出网络请求)

4:并且,正如许多其他人所说的那样,如果可以,请尝试使用nohup。

答案 7 :(得分:0)

使用ignore_user_abort通过apache运行长时间运行的脚本是一种肮脏的方法。

最简单的方法是使用 GNU屏幕,只需键入屏幕,然后您将连接到当前控制台内的新控制台,启动脚本,然后使用 ctrl从屏幕上分离-a d (完整的手动here),即使您与服务器断开连接,屏幕仍会继续工作。

要重新连接到您的屏幕,请使用 screen -r ,然后您将返回正在运行的脚本。

最难的方式(也是最干净的方法)是重写你的脚本以作为系统守护进程工作,有很多lib可以帮助你做到这一点,我建议你挖掘一下pear的守护进程lib(例子{{ 3}})。

至于内存限制问题(?),在决定更新memory_limit配置之前,你必须检查你的脚本是否比你当前配置中写的更多ram,做一个简单的 ps aux | grep php 并查找 RSS 列,这是您的脚本正在吃的所有内存。

答案 8 :(得分:0)

我们通常面临许多其他问题。

  1. 您失败的程序可能会以不适当的用户权限连接到任何其他用户/服务/服务器。因为web-php通常使用的是用户apache(centos)或www-data(在ubuntu中),它们不是执行sudo列表的一部分。给予相关许可,然后尝试。
    1. 检查php.ini并检查行disabled_function:exec,shell_exec或其他东西,删除/注释该行然后尝试。