首页 » 开源分析 » 解决crond脚本执行并发冲突问题

解决crond脚本执行并发冲突问题

 

问题

在crond配置脚本执行后,经常会出现重复执行的情况。如下面的脚本:

<?php
sleep(70);
?>

如果,在crond中的配置项如下:

*/1 * * * * root php ./test.php

就出出现,之前执行的test.php还未结束,新的test.php又被执行。如下:

[hailong@vhost ~]$ ps aux | grep tt.php
56667     5280  0.0  0.0 103388  4432 pts/2    T    08:06   0:00 vim ./test.php
root      5455  0.0  0.1 225288  8812 ?        Ssl  08:08   0:00 /usr/bin/php /home/hailong/test.php
root      5665  5.0  0.1 225288  8748 ?        Ssl  08:09   0:00 /usr/bin/php /home/hailong/test.php
56667     5675  0.0  0.0  69460   852 pts/2    S+   08:09   0:00 grep tt.php

进程一直堆积的话,可能会把系统资源给耗尽,导致系统宕机。

解决方案

解决方案有两种。各有利弊。

第一种,代码中控制并发

这种方法,就是对代码进行改造。增加是否有进程执行的判断。如下面的代码:

<?php  
$lockfile = '/tmp/mytest.lock';  
  
if(file_exists($lockfile)){  
    exit();  
}
file_put_contents($lockfile, date("Y-m-d H:i:s"));
  
sleep(70);

unlink($lockfile);  
?>

代码逻辑很简单,这里就不再解释。这种判断文件是否不存在的方式,会有一个问题。那就是有可能程序未执行到最后,也就是没有删除之前创建的mytest.lock文件。这会导致,之后程序将不能正常执行。

为了解决这个问题,我们对代码进行下改造。不再使用文件是否存在的判断,而是判断进程是否存在。代码修改后如下:

$fp = popen("ps aux | grep 'test.php' | wc -l", "r");
$proc_num = fgets($fp);
if ($proc_num > 3) {
    exit;
}
sleep(70);

这种方式有一个弊端,就是ps命令要写的精确。避免把不是执行test.php脚本的进程也统计到。如:
我们通过vim打开test.php文件。就会导致上面命令误统计。
另外,$proc_num 为什么要大于3而不是大于1,大家可以想想。如果,想不明白,可以加我微信 1798159444。

第二种,使用linux的flock命令

flock命令提供了文件锁的功能。命令参数如下:

[hailong@vhost ~]$ flock -h
flock (util-linux 2.13-pre7)
Usage: flock [-sxun][-w #] fd#
       flock [-sxon][-w #] file [-c] command...
  -s  --shared     Get a shared lock
  -x  --exclusive  Get an exclusive lock
  -u  --unlock     Remove a lock
  -n  --nonblock   Fail rather than wait
  -w  --timeout    Wait for a limited amount of time
  -o  --close      Close file descriptor before running command
  -c  --command    Run a single command string through the shell
  -h  --help       Display this text
  -V  --version    Display version

使用flock控制并发冲突,我们的crond配置如下:

*/1 * * * * root flock -xn /tmp/mytest.lock -c 'php ./test.php'

其实,使用flock也是有坑的。坑的详细信息,请查看crond中使用flock命令的坑

技术交流

原文链接:解决crond脚本执行并发冲突问题,转载请注明来源!

原文链接:解决crond脚本执行并发冲突问题,转载请注明来源!

11