2

我想知道如何使用 file_get_content(不是 HTTP uri)在本地文件上设置超时,有时 NFS 挂载分区非常慢,我更喜欢在超时后放弃(例如 5 秒),

file_get_contents("/mnt/photo/photo.jpg");

我阅读了其他类似问题的答案,但我猜这些解决方案仅适用于 HTTP,不适用于本地文件:

$ctx = stream_context_create(array('http'=>array('timeout' => 1200)));

我还认为这个解决方案不适合我,它也适合 Web,对吧?

ini_set('default_socket_timeout', 900);
4

2 回答 2

1

您可以将流设置为非阻塞模式stream_set_blocking并尝试读取文件直到超时。就像是:

function readReallyBigFile($path, $timeoutSeconds = 5) {
    if (false === $stream = fopen($path, "r")) {
        throw new \RuntimeException('Cannot open file');
    }

    stream_set_blocking($stream, 0);

    $timeout = time();

    $contents = '';
    while (!feof($stream)) {
        $contents .= fread($stream, 8192);
        if ((time() > $timeout + $timeoutSeconds)) {
            throw new \RuntimeException('Timeout reached out');
        }
    }

    fclose($stream);

    return $contents;
}

$img = readReallyBigFile('/mnt/photo/photo.jpg');
于 2016-11-10T13:06:43.007 回答
1

恐怕您无法通过 PHP 控制 NFS 超时,因为 NFS 协议选项只能通过挂载选项控制。PHP 不知道文件是在 NFS 上还是在本地硬盘上。我相信,有一些方法可以确定文件在 NFS 上的事实,但它不会让我们控制超时。

NFS 中有两种超时类型:次要主要timeo如果在挂载选项 ( )中指定的超时时间内未收到来自服务器的确认,则会发生轻微超时。然后重试操作,超时时间加倍。当超时间隔达到 60 秒时,将发生重大超时。接下来会发生什么取决于其他选项。

默认情况下,原始超时时间加倍,并且无休止地继续重试。据说一个卷是硬安装的(hard选项默认打开)。如果使用soft选项挂载卷,则主要超时将导致 I/O 错误。您应该考虑软安装。但是,请注意,默认超时仅为7(0.7 秒),这对于软挂载来说可能有点太小了。您应该估计可能的等待时间,并timeo相应地调整选项。

另一个有趣的选项是intr,它应该允许挂起的 NFS 操作中断。但是,在内核版本 2.6.25 之后不推荐使用此选项。只能SIGKILL中断 NFS 操作。您可能希望使用该fork()函数实现看门狗进程。子进程可能会运行 NFS 操作,父进程可能会在一段时间后将其杀死。

于 2016-11-10T13:06:51.550 回答