我有一个php-cli
脚本,cron
每5 minutes
运行一次。由于此间隔很短,因此multiple processes
同时运行。这不是我想要的,因为这个脚本必须在文本文件中写入一个每次递增的数字id
。碰巧writers
正在同时写入此文本文件,并且写入的值不正确。
我曾尝试使用php的flock
函数阻止在文件中写入,当另一个进程正在写入但它不起作用时。
$fw = fopen($path, 'r+');
if (flock($fw, LOCK_EX)) {
ftruncate($fw, 0);
fwrite($fw, $latestid);
fflush($fw);
flock($fw, LOCK_UN);
}
fclose($fw);
所以我想这个解决方案是创建一个bash
脚本来验证是否有一个正在运行的php script
实例,如果是,它应该等到它完成。但我不知道怎么做,有什么想法吗?
答案 0 :(得分:3)
我真的不明白每5分钟增加一个计数器会导致多个进程同时尝试写入计数器文件,但是......
更简单的方法是使用类似于下面的简单锁定机制:
<?php
$lock_filename = 'nobodyshouldincrementthecounterwhenthisfileishere';
if(file_exists($lock_filename)) {
return;
}
touch($lock_filename);
// your stuff...
unlink($lock_filename);
这是一个简单的方法,它不会处理脚本在删除锁定文件之前中断的情况,在这种情况下,它会在删除之前再次运行。
如您所建议的那样,也可以采用更复杂的方法,例如:在自己的进程中分配作业,将PID写入文件,然后在运行作业之前,可以检查PID是否仍在运行。
答案 1 :(得分:3)
我与bash script
一起使用的解决方案是:
exec 9>/path/to/lock/file
if ! flock -n 9 ; then
echo "another instance is running";
exit 1
fi
# this now runs under the lock until 9 is closed (it will be closed automatically when the script ends)
文件描述符9>
在/var/lock/file
中创建,flock
将退出尝试运行的新进程,除非脚本中没有其他实例在跑。
How can I ensure that only one instance of a script is running at a time (mutual exclusion)?
答案 2 :(得分:0)
不是每隔5分钟使用cron
来运行脚本,而是在完成后5分钟使用at
来安排脚本再次运行。在脚本结束时,您可以使用shell_exec()运行at
命令来安排脚本在5分钟内再次运行,如下所示:
at now + 5 minutes /path/to/script
答案 3 :(得分:0)
或者,甚至可能比我之前的答案更简单(使用at
安排脚本在5分钟内再次运行)通过使用非终止循环使您的脚本成为守护程序,如下所示:
while(1) {
// whatever your script does here....
sleep(300) //wait 5 minutes
}
然后,您可以完全取消cron
或at
的排程。只需从命令行在后台运行脚本,如下所示:
/path/to/your/script &
或者,在/etc/rc.local中添加/path/to/your/script
以使您的脚本在计算机启动时自动启动。
答案 4 :(得分:0)
为防止在上一个会话仍在运行之前启动任何程序的下一个会话,例如下一个cron作业,我建议使用内置于程序中或外部检查此程序的运行过程。只需在开始程序之前执行
ps -ef|grep <process_name>|grep -v grep|wc -l
并检查,如果结果为0.只有在这种情况下才可以启动程序。 我想,您必须保证缺少具有相似名称的第三方流程。 (为此目的,为您的程序提供更长且唯一的名称)。并且程序的名称不得包含“grep”模式。
这项工作很好地与cron守护程序在cron表中配置的程序的正常常规启动相结合。 对于将检查写为外部脚本的情况,crontab中的条目可能类似于
<time_specification> <your_starter_script> <your_program> ...
2个重要说明:如果没有启动程序,your_starter_script的退出代码必须为0,最好完全禁止通过此脚本写入stdout或stderr。
这种启动器非常简短,只需简单的编程练习。因此,我觉得不需要提供完整的代码。