【问题标题】:Reasons for PHP's popen command to failPHP的popen命令失败的原因
【发布时间】: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 实例突然消失时系统负载会是什么样子。

标签: php email pipe


【解决方案1】:

我建议改用 proc_open。它使用起来稍微复杂一些,但可以让您访问 stdout 和 stderr。这两个管道上的消息将为您节省大量调试时间。

如何使用,阅读PHP文档中的示例和cmets即可。

【讨论】:

    猜你喜欢
    • 2012-01-07
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多