php - 为什么在 PHP 中使用“锁定”文件而不是仅仅计算进程?
问题描述
我见过很多例子,其中使用“锁定”文件来跟踪 PHP 脚本当前是否正在运行。
例子:
- 脚本开始
- 检查“/tmp/lockfile”当前是否被锁定
- 如果已锁定,请退出。如果没有,锁定文件并继续
这样,如果一个长时间运行的脚本启动了两次,那么只有第一个实例会运行。这是伟大的。
但是,绕过它似乎是错误的方法。我们为什么不检查进程是否已经像这样运行呢?
if(exec("ps -C " . basename(__FILE__) . " --no-headers | wc -l") > 1){
echo "Already running.";
exit;
}
这种方法有任何潜在的缺陷吗?为什么我经常看到“锁定”文件解决方法?用我们正在寻找的名称来计算进程似乎更准确....
解决方案
根据这里的评论和我自己的观察,我列出了两种方法的优缺点:
flock
方法:
优点:
- 跨操作系统更兼容
- 不需要 bash 知识
- 更常用的方法,很多例子
- 即使有
exec()
残疾人也可以使用 - 可以在单个文件中使用多个锁,以允许同一文件同时运行不同的“模式”
缺点:
- 这不是确定的。如果您的锁定文件被外部进程/用户删除,您最终可能会得到多个进程。如果您将锁定文件保存在
/tmp
目录中,这是一种有效的可能性,因为该目录中的所有内容都应该是“临时的” - 在某些情况下,当一个进程意外死亡时,文件锁可以转移到一个不相关的进程(起初我不相信这一点,但我发现它发生在 200 多个基于 unix 的系统中的实例(虽然很少),在 3不同的操作系统)
exec("ps -C...")
方法
优点:
- 由于您实际上是在计算进程,因此无论文件锁定等状态如何,它都会每次都起作用。
缺点:
- 仅适用于 linux
- 需要启用“exec”
- 如果您更改脚本的名称,可能会导致双重处理(并确保您的脚本名称未在代码中硬编码)
- 假设您的脚本只有一个正在运行的“模式”
编辑:我最终使用了这个:
if (exec("pgrep -x " . $scriptName . " -u ". $currentUser . " | wc -l") > 1)
{
echo $scriptName . " is already running.\n";
exit;
}
...因为ps
除了进程名称之外,不允许您过滤进程的所有者,并且我希望允许该脚本在其他用户运行它时多次运行。
编辑2:
...因此,在运行了几天之后,它也不完美。不知何故,该进程在同一用户下的同一台机器上启动了多次。我唯一的猜测是有一些问题(内存不足等)导致pgrep
它什么都不返回,而它应该返回一些东西。
因此,这意味着该flock
方法和计数过程方法都不是 100% 可靠的。您必须确定哪种方法更适合您的项目。
最终,我使用了另一种解决方案,将当前任务的 PID 存储在“锁定”文件中,实际上并没有被锁定。然后,当脚本启动时,检查锁定文件是否存在,如果存在,则获取内容(脚本上次启动时的 PID)然后,通过将/proc/#PID#/cmdline
内容与名称进行比较来检查它是否仍在运行正在运行的脚本。
推荐阅读
- c# - c#如何允许同一用户多次登录,但限制为一定数量
- svelte - 不能使用`svelte/animate`使列表项飞入标题
- php - 无法在我的 Laravel 项目中使用 fork 存储库 - “找不到匹配的包版本”
- unit-testing - 使用 Jest & Enzyme 测试 switch 语句
- flutter - 颤振项目编译失败,“任务'fluttertoast:compileDebugJavaWithJavac'的执行失败”AndroidX
- swift - 如何映射和过滤低于某个数字的 JSON 嵌套数据字典?
- python - 如何使 Dask 一次处理更少的分区/文件?
- sql - 依靠 join 和 union 语句
- c - C中的嵌套函数
- regex - 匹配十进制数