【发布时间】:2011-04-06 19:38:18
【问题描述】:
我有一个发送大约 30,000 封电子邮件的批处理电子邮件。我遇到了一个奇怪的问题,它完成了大约 85% 的过程,然后电子邮件开始失败并显示消息 Could not execute: /usr/sbin/sendmail 我正在使用一个名为 PHPMailer 1.73 的库,错误消息来自的相关代码是
if(!@$mail = popen($sendmail, "w"))
{
$this->SetError($this->Lang("execute") . $this->Sendmail);
return false;
}
$sendmail 的值格式为:/usr/sbin/sendmail -oi -f support1@example.com -t
我有set_time_limit(0);,所以脚本不会超时。
有没有办法弄清楚为什么突然 popen() 开始失败?操作系统是否会耗尽文件描述符或达到其他限制?
我应该如何解决这个问题?我应该让它休眠,然后在失败之前重试 popen() 几次?
更新:感谢 Marko 的建议,查看 proc_open() 我在 proc_open documentation 上发现了一条评论,如果它返回 FALSE,这可能意味着您的文件描述符用完了或者你内存不足。我发现我的进程占用了20G 的内存。但是如果memory_limit 设置为64M,它怎么会占用这么多内存呢?好吧,使用exec()、popen() 或proc_open() 运行外部程序似乎不计入 PHP 的内存限制。请参阅此 SO 问题以获取更多信息,Debugging memory usage in mod_php。我仍然不确定这是怎么发生的,但我怀疑某种内存泄漏。
总之,popen() 和 proc_open() 可以在文件描述符不足或内存不足的情况下返回 FALSE。
【问题讨论】:
-
您的服务器是否配置了每小时/每天最大数量的 smtp 中继?您的脚本执行超时设置为多少?
-
PID 也可能用完。较旧的 unix 机器(尤其是 linux)的上限为 2^16 个 pid。 30,000 封电子邮件听起来可能会接近这个数字,其中包括常规系统进程。不过,我不希望看到 30,000 多个 sendmail 实例突然消失时系统负载会是什么样子。