PHP file_get_contents 超时 "local file" (NFS/mount)

PHP file_get_contents timeout "local file" (NFS/mount)

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

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

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

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

我也想这个解决方案不适合我,它也适合 Web,对吗?

ini_set('default_socket_timeout', 900);

您可以使用 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');

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

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

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

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