打开流失败:打开的文件太多。

3

我正在为一位在共享主机上运行的客户编写PHP CLI脚本。 它使用类似于以下简单函数将日志记录到文件中:

function log_entry($msg) {
    global $log_file, $log_handle;
    $msg =  "[".date('Y-m-d H:i:s')."] ".$msg."\n";
    echo $msg;
    $log_handle = fopen($log_file, 'a');
    fwrite($log_handle, $msg);
}

我遇到了以下错误:

PHP Warning:  fopen(./logs/sync.20130410.log) 
[<a href='function.fopen'>function.fopen</a>]: failed to open stream: 
Too many open files in ./functions.php on line 61

我曾认为使用相同的句柄会有问题,所以我将其更改为:

function log_entry($msg) {
    global $log_file;
    $msg =  "[".date('Y-m-d H:i:s')."] ".$msg."\n";
    echo $msg;
    $log_handle = fopen($log_file, 'a');
    fwrite($log_handle, $msg);
    fclose($log_handle);
}

但是那样做没有用。我总是在同一行日志中遇到错误。当我执行 ulimit -n 命令时,返回的是 1024,但这不应该成为问题,因为我从未打开过一个以上的文件。有什么想法吗?


你可能在与你的共享托管提供商运行文件描述符限制的问题。 - Zak
但是我不是一次只使用一个功能吗?第一个函数应该在整个执行过程中只使用一个,第二个函数应该每行使用一个...或者它的工作方式不同吗? - Mauro
http://serverfault.com/questions/195334/apache-crashes-every-night-due-to-too-many-open-files - zod
Apache可以配置为将其ulimit降低到它打开的文件数量,从而限制您打开其他文件。您应该与您的托管提供商检查配置。 - Zak
@Zak 这是一个 PHP 脚本,但它是通过 CLI 执行的,因此 Apache 不在中间。 - Mauro
1个回答

7

发现问题。我回答这个问题只是为了防止有人因同样的原因进行谷歌搜索,但我知道这个答案并未暗示在问题中。

我正在使用BigCommerce API客户端,结果发现他们每次请求都会打开一个句柄,导致我的脚本崩溃。以下是我如何解决它的方法:

BigCommerce/API/Connection.php:354-365:

public function put($url, $body)
{
    $this->addHeader('Content-Type', $this->getContentType());

    if (!is_string($body)) {
        $body = json_encode($body);
    }

    $this->initializeRequest();
    $handle = tmpfile();
    fwrite($handle, $body);
    fseek($handle, 0);
    curl_setopt($this->curl, CURLOPT_INFILE, $handle);
    curl_setopt($this->curl, CURLOPT_INFILESIZE, strlen($body));

    curl_setopt($this->curl, CURLOPT_URL, $url);
    curl_setopt($this->curl, CURLOPT_PUT, true);
    curl_exec($this->curl);
    fclose($handle); // Added this line

    return $this->handleResponse();
}

添加了fclose($handle);这行代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接