我有一个生产脚本,可以将文件从一个安装的网络共享复制并重命名到另一个(两个 CIFS),有时 copy
函数在读取 I/O 时无限期挂起,从而使进程进入不间断 sleep 状态它只能用 SIGKILL 杀死。
(谢天谢地,显然是 TASK_KILLABLE。)
由于操作在 copy
调用时被阻止,我无法优雅地处理 I/O 故障,更重要的是,也无法记录它。
$res = copy("/path/to/mount/file.pdf", "/path/to/productionqueue/newfile.pdf");
//This doesn't run because of the process state.
if($res) {
//Report success to the log.
} else {
//Report failure to the log.
}
这是一个环境、特定于文件的问题,手动干预可以解决它,但我需要记录故障,以便管理员可以收到有关该情况的通知。 (旁白:我认为这是一个锁竞争条件。我可以通过卸载和重新安装源共享来解决这个问题,但是重现它有点问题。)
理想情况下,我希望 copy
调用在 10 秒后超时,这样我就可以记录错误,但在 PHP 中似乎没有办法做到这一点。
我正在考虑的是将复制或读取操作委托(delegate)给由 timeout
命令监视的子进程并根据退出代码进行响应,但是 PHP 脚本中是否有更简单的方法来处理这个问题什么样的场景?
我在搜索中发现的所有内容都表明只有运行时配置可用于套接字/网络超时,而不是文件系统调用。
据我所知,答案是否定的——在 PHP 中没有内置的文件读取操作超时方法。但是,在您的 I/O 为 TASK_KILLABLE
的系统上,您可以在子进程中执行 I/O 操作并使用 timeout -s 9
终止它。 timeout
然后会返回一个非零的退出状态。
例如,使用 cp
实用程序:
$ssrc = escapeshellarg($src);
$sdst = escapeshellarg($dst);
//10 second timeout, send KILL
exec("timeout -s 9 10 cp $ssrc $sdst 2>&1", $output, $ret);
if($ret != 0) {
log("Failed copying $src to $dst, exit status: $ret");
}
我是一名优秀的程序员,十分优秀!