Impedir que um Script PHP seja executado ao mesmo tempo no Cron

Estou construindo um script de sincronia de banco de dados que deve rodar de 5 em 5 minutos na cron do linux. O problema é que ele pode acabar durando mais do que cinco minutos então pesquisando uma forma de evitar que o script seja executado novamente antes que o anterior termine encontrei a solução no link abaixo e coloco aqui com pequenas alterações:

http://abhinavsingh.com/blog/2009/12/how-to-use-locks-in-php-cron-jobs-to-avoid-cron-overlaps/

Crie um arquivo chamado CronHelper.php e adicione o código abaixo (eu coloquei na mesma pasta do meu script cron):

<?php
define('LOCK_DIR', __DIR__ . '/');
define('LOCK_SUFFIX', '.lock');

class CronHelper {
    private static $pid;

    function __construct() {
        
    }

    function __clone() {
        
    }

    private static function isrunning() {
        $pids = explode(PHP_EOL, `ps -e | awk '{print $1}'`);
        if (in_array(self::$pid, $pids)) {
            return TRUE;
        }
        return FALSE;
    }

    public static function lock() {
        global $argv;
        
        $path_parts = pathinfo($argv[0]);

        $lock_file = LOCK_DIR . $path_parts['basename'] . LOCK_SUFFIX;

        if (file_exists($lock_file)) {
            //return FALSE;
            // Is running?
            self::$pid = file_get_contents($lock_file);
            if (self::isrunning()) {
                error_log("==" . self::$pid . "== Já está em progresso...");
                return FALSE;
            } else {
                error_log("==" . self::$pid . "== O job anterior foi interrompido abruptamente...");
            }
        }

        self::$pid = getmypid();
        file_put_contents($lock_file, self::$pid);
        error_log("==" . self::$pid . "== Trava adquirida, processando o job...");
        return self::$pid;
    }

    public static function unlock() {
        global $argv;

        $lock_file = LOCK_DIR . $argv[0] . LOCK_SUFFIX;

        if (file_exists($lock_file)) {
            unlink($lock_file);
        }

        error_log("==" . self::$pid . "== Soltando a trava...");
        return TRUE;
    }

}

Para utilizado coloque todo o código do cron dentro do if:

<?php
require 'CronHelper.php';

if(($pid = cronHelper::lock()) !== FALSE) {
    /*
     * O código do seu cron job vai aqui!
     */

    cronHelper::unlock();
}

?>
Tags: , , , ,

Sobre o autor

Um desenvolvedor web veterano que está sempre a procura de novas tecnologias que facilitem o desenvolvimento de aplicativos ricos para a internet. Louco por tecnologia, games e Linux.

Deixe uma resposta