Aller au contenu principal

Lancer une tâche planifiée PrestaShop par cron, protégée par jeton

Fiche écrite en 2019, pour les navigateurs et les versions de l’époque. Vérifiez qu’elle correspond encore à votre environnement avant de l’appliquer.

Synchroniser un stock, importer des commandes, envoyer un export à un transporteur : ces traitements doivent tourner seuls, à intervalle régulier. Le plus simple et le plus portable est un contrôleur de module appelé par la crontab du serveur. Encore faut-il que n’importe qui ne puisse pas le déclencher, et qu’un passage lent ne se superpose pas au suivant.

PHP
<?php
// modules/w4usync/controllers/front/cron.php
class W4uSyncCronModuleFrontController extends ModuleFrontController
{
    public function initContent()
    {
        // 1. Jeton : comparaison à temps constant
        $attendu = (string) Configuration::get('W4USYNC_TOKEN');
        if ($attendu === '' || !hash_equals($attendu, (string) Tools::getValue('token'))) {
            header('HTTP/1.1 403 Forbidden');
            exit('Accès refusé');
        }

        // 2. Verrou : si le passage précédent tourne encore, on ne relance pas
        $verrou = fopen(_PS_CACHE_DIR_ . 'w4usync.lock', 'c');
        if (!flock($verrou, LOCK_EX | LOCK_NB)) {
            exit('Déjà en cours');
        }

        // 3. Traitement et trace dans Paramètres avancés > Logs
        $traites = $this->module->synchroniser();
        PrestaShopLogger::addLog('W4U Sync : ' . (int) $traites . ' éléments traités', 1);

        flock($verrou, LOCK_UN);
        exit('OK ' . (int) $traites);
    }
}

Côté serveur, curl -fsS reste silencieux quand tout va bien et fait remonter une erreur HTTP par le courriel de cron quand quelque chose échoue. L’option -m fixe une durée maximale : si le traitement peut dépasser la limite de PHP, il vaut mieux le découper en lots qu’augmenter max_execution_time sans fin.

Terminal
# Le jeton est généré une fois, à l'installation du module :
#   Configuration::updateValue('W4USYNC_TOKEN', Tools::passwdGen(32));

# crontab -e : toutes les 15 minutes, échec signalé par cron s'il y en a un
*/15 * * * * curl -fsS -m 600 "https://www.exemple.fr/module/w4usync/cron?token=VOTRE_JETON" > /dev/null

Sources

  1. PHP, hash_equals() php.net
  2. PHP, flock() php.net