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 中有两种类型的超时:minor 和major。如果在挂载选项 (timeo
) 指定的超时时间内未从服务器收到确认,则会发生轻微超时。然后重试操作,超时时间加倍。当超时间隔达到 60 秒时,发生严重超时。接下来会发生什么取决于其他选项。
默认情况下,原来的超时加倍,不断重试。据说卷是硬安装的(hard
选项默认打开)。如果使用 soft
选项安装卷,主要超时将导致 I/O 错误。您应该考虑软安装。但是,请注意默认超时仅为 7(0.7 秒),这对于软安装来说可能有点太小了。您应该估计可能的等待时间,并相应地调整 timeo
选项。
另一个有趣的选项是 intr
,它应该允许中断挂起的 NFS 操作。但是,此选项在内核版本 2.6.25 之后已弃用。只有 SIGKILL
可以中断 NFS 操作。您可能希望使用 fork()
函数实现看门狗进程。子进程可能运行一个NFS操作,而父进程可能kill它在一定时间后。
我想知道如何使用 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 中有两种类型的超时:minor 和major。如果在挂载选项 (timeo
) 指定的超时时间内未从服务器收到确认,则会发生轻微超时。然后重试操作,超时时间加倍。当超时间隔达到 60 秒时,发生严重超时。接下来会发生什么取决于其他选项。
默认情况下,原来的超时加倍,不断重试。据说卷是硬安装的(hard
选项默认打开)。如果使用 soft
选项安装卷,主要超时将导致 I/O 错误。您应该考虑软安装。但是,请注意默认超时仅为 7(0.7 秒),这对于软安装来说可能有点太小了。您应该估计可能的等待时间,并相应地调整 timeo
选项。
另一个有趣的选项是 intr
,它应该允许中断挂起的 NFS 操作。但是,此选项在内核版本 2.6.25 之后已弃用。只有 SIGKILL
可以中断 NFS 操作。您可能希望使用 fork()
函数实现看门狗进程。子进程可能运行一个NFS操作,而父进程可能kill它在一定时间后。