IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Peut-on créer/détruire un cron dynamiquement


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2003
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 125
    Par défaut Peut-on créer/détruire un cron dynamiquement
    Bonjour,
    comme souvent, je ne sais pas si ma question est dans le bon forum : php ou bien linux ou bien ???
    Bref, je vous expose mon problème :

    Mon environnement :
    Serveur dédié linux, avec apache, php et mysql

    Un client met à jour la base de donnée mysql avec des occasions et les visiteurs qui se sont inscrits doivent recevoir une alerte personnalisée selon les occasions qui les intéressent (donc un mail différent par personne, pas de BCC) en fonction de paramètres qu'ils auront choisi.

    Sachant qu'il y aura entre 500 et 1500 personnes concernées
    - je ne peux lancer un script qui envoie un mail à chaque personne (problème de timeout évident)
    - je ne peux (je pourrais mais c'est une solution peu agréable pour le client) permettre au script d'envoyer x mail puis de demander au client de cliquer pour en envoyer x autres, etc.
    => j'ai songé au cron, en remplaçant l'action du clic du client pour relancer par un rappel du script un certain temps après.

    Mais c'est là où je coince : si je crée un cron sur mon serveur (j'ai un dédié), ne tournera-t'il pas indéfiniment (selon la fréquence définie) ?

    Ce que je souhaiterai savoir, c'est s'il est possible en php,
    - de créér un cron (donc dynamiquement),
    - qui tournera autant de fois que nécessaire (jusqu'à ce qu'il n'y ait plus de mail à envoyer - testé par un flag "sent" dans la base pour chaque visiteur)
    - qui sera détruit par un appel php quand on aura plus besoin de lui (dans un test dans le script d'envoi de mail j'imagine)

    1) Pensez-vous que c'est une solution envisageable ?
    -comment peut-on dynamiquement (via php), créer détruire un cron ?
    - Quel est le paramétrage nécessaire du serveur (safe_mode on/off important ? ...)

    2) Avez vous une autre solution ?

    Merci d'avance

  2. #2
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut
    Aaah si j'avais reçu 1€ à chaque fois que quelqu'un émulait un daemon avec un cron

    Bref, c'est pas un cron que tu cherches à faire: c'est un Daemon. C'est à dire un processus qui ne meurt pas et que tu peux appeler pour prendre une charge un (ou plusieurs) traitements sans briser le flux de l'application qui l'appelle (et qu'on peut au passage appeler pour savoir "où il en est").

    Pour créer un Daemon, il faut d'abord installer l'extension PCNTL et avoir PHP 5.3 (impératif). Est-ce que c'est possible sur ton environnement de prod ? (sinon on va chercher un autre moyen parce sans ça c'est pas la peine d'aller plus loin).

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2003
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 125
    Par défaut
    Désolé, si je te fais perdre encore un euro...

    Je suis sur un serveur "assez ancien" avec un php 5.1.6... que je ne peux upgrader facilement et surtout sans risque. Donc j'oublie.
    Donc pas de PCNTL. Mais d'après ce que j'ai pu en comprendre c'est un processus qui tourne tout le temps. Je souhaite que lorsque tous les mails sont envoyés, une condition puisse arréter le processus (cron, pcntl...).

    Désolé pour cette piste, mais merci pour la réponse.

  4. #4
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut
    Citation Envoyé par beyo Voir le message
    Je suis sur un serveur "assez ancien" avec un php 5.1.6... que je ne peux upgrader facilement et surtout sans risque. Donc j'oublie.
    Donc pas de PCNTL. Mais d'après ce que j'ai pu en comprendre c'est un processus qui tourne tout le temps. Je souhaite que lorsque tous les mails sont envoyés, une condition puisse arréter le processus (cron, pcntl...).
    Le principe aurait été d'avoir un Daemon qui, lors qu'il reçoit un signal indiquant une liste de tâche à traiter (une queue quoi), se forke et fasse tous les traitements dans un thread indépendant. L'intérêt de la manœuvre c'est que le thread parent peut toujours contrôler le fils.

    Mais déjà, si tu ne peux pas avoir PHP 5.3 (au moins) on oublie tout de suite: sans garbage collector, ton Daemon va consommer la mémoire jusqu'au crash, c'est donc totalement inutile.

    Donc oui, un cronjob devient la seule solution réaliste. Une façon d'implémenter ce que tu essaie de faire serait d'avoir un serveur Redis ou Memcached pour la queue de traitement. Le cron se lance à intervale régulier, prends les X premiers élements à traiter et fais les opérations nécéssaires. On lui adjoint un fichier de conf, un log et l'affaire est dans le sac!

    Je te recommande d'écrire ce script en PHP et de le tailler pour le travail en CLI. Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    <?php
     
    //
    // Une calculatrice simple en ligne de commande
    //
     
    // ligne de commande seulement !
    if (!PHP_SAPI === 'cli') {
        echo "CLI mode only\n";
        exit(-1);
    }
     
    // définition des opérations
    define('OP_MULTIPLY', '*');
    define('OP_ADD',      '+');
    define('OP_DIVIDE',   '/');
    define('OP_MODULO',   '%');
     
    // messages utilisés
    $message['usage'] =
    $message['help']  = <<< EOF
    Usage: {$argv[0]} [options] <a> <b>
     
        Returns the result of <a> [operation] <b>,
        see available operations in options below.
     
    Available Options:
     
        -h, --help       Display this message
        -m, --multiply   Use the multiplication operation
        -a, --add        Use the addition operation
        -d, --div        Use the division operation
        --modulo         Use the module operation
        --abs            Returns absolute result
        --int            Returns integer result
     
    EOF;
     
    // valeurs par défaut des options
    $options = array(
        'operation' => null,
        'abs'       => false,
        'int'       => false,
    );
     
    // help
    if (in_array('-h', $argv) || in_array('--help', $argv)) {
        echo $message['help'];
        exit(0);
    }
     
    // traiter les paramètres de la ligne de commande
    for ($i = 1; $i < $argc -2; $i++) {
        switch ($argv[$i]) {
            case '-m':
            case '--multiply':
                $options['operation'] = OP_MULTIPLY;
                break;
     
            case '-a':
            case '--add':
                $options['operation'] = OP_ADD;
                break;
     
            case '-d':
            case '--div':
                $options['operation'] = OP_DIVIDE;
                break;
     
            case '--modulo':
                $options['operation'] = OP_MODULO;
                break;
     
            case '--abs':
                $options['abs'] = true;
                break;
     
            case '--int':
                $options['int'] = true;
                break;
     
            default:
                echo "Unrecoginized option: {$argv[$i]}\n";
                echo $message['usage'];
                break;
        }
    }
     
    if (!$options['operation']) {
        echo "Error: No operation specified";
        echo $message['usage'];
        exit(-1);
    }
     
    // obtenir les valeurs <a> et <b> et les valider
    list($a, $b) = array_slice($argv, -2) + array(null, null);
     
    if (!preg_match('~[-+]?([0-9]*\.[0-9]+|[0-9]+)~', $a)) {
        echo "Error: $a is not a valid number\n";
        exit(-1);
    }
     
    if (!preg_match('~[-+]?([0-9]*\.[0-9]+|[0-9]+)~', $b)) {
        echo "Error: $b is not a valid number\n";
        exit(-1);
    }
     
    $a = floatval($a);
    $b = floatval($b);
     
    //
    // traitement principal
    //
     
    if (($result = perform_operation($a, $b, $options['operation'])) === false) {
        echo "Error: unable to get a result!";
        exit(-1);
    }
     
    if ($options['int'])
        $result = (int)$result;
     
    if ($options['abs'])
        $result = abs($result);
     
    echo "{$a} {$options['operation']} {$b} = {$result}\n";
    exit(0);
     
    //
    // fonctions
    //
     
    function perform_operation ($left, $right, $operation) {
        switch ($operation) {
            case OP_MULTIPLY:
                return $left * $right;
            case OP_ADD:
                return $left + $right;
            case OP_DIVIDE:
                return $right !== 0 ? $left / $right : 'NaN'; // attention à la division par 0
            case OP_MODULO:
                return $right !== 0 ? $left % $right : 'NaN'; // attention à la division par 0
            default:
                return false;
        }
    }
    Usage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ php calc.php --abs --int -d -25 3
    -25 / 3 = 8

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2003
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 125
    Par défaut
    Une façon d'implémenter ce que tu essaie de faire serait d'avoir un serveur Redis ou Memcached pour la queue de traitement.
    Euh ! Là c'est peut-être un peu trop raccourci pour moi comme réponse : ce à quoi tu fais référence c'est un système de cache. J'espère que tu excuseras mon ignorance dans ce domaine, mais si c'est ça en quoi c'est nécessaire ou ça améliore le système pour l'envoi périodique d'un nombre défini de mails. Pour moi le cache c'est pour les pages "statiques".

    Je te recommande d'écrire ce script en PHP et de le tailler pour le travail en CLI
    Re-euh
    je ne suis pas sûr de comprendre ce que tu veux dire : "tailler pour le travail en CLI" signifie t'il modifier/rajouter des instructions pour pouvoir être exécuté en ligne de commande ? Si oui, peut-être (sûrement) ne suis-je pas assez balèze en php, mais dans mon scénario (idéal) ça serait le client qui lancerait le cron quand il mettrait à jour la base (via l'admin web du site, donc pas en CLI), est-ce que ce script cli pourrait être lancé via une page web ?? Mais principalement je ne vois pas pourquoi il faut que ce soit en CLI.

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 418
    Par défaut
    Citation Envoyé par beyo Voir le message
    Ce que je souhaiterai savoir, c'est s'il est possible en php,
    - de créér un cron (donc dynamiquement),
    - qui tournera autant de fois que nécessaire (jusqu'à ce qu'il n'y ait plus de mail à envoyer - testé par un flag "sent" dans la base pour chaque visiteur)
    - qui sera détruit par un appel php quand on aura plus besoin de lui (dans un test dans le script d'envoi de mail j'imagine)

    1) Pensez-vous que c'est une solution envisageable ?
    -comment peut-on dynamiquement (via php), créer détruire un cron ?
    - Quel est le paramétrage nécessaire du serveur (safe_mode on/off important ? ...)

    2) Avez vous une autre solution ?

    Merci d'avance
    C'est pas un problème que le cron tourne toutes les minutes ou toutes les x minutes, ça dépend de ce qu'il fait. Genre si tu stocke quelque part l'état de tes envois de mail, la première tache du cron doit être d'interroger cet état et si c'est fini il ne fait rien sinon il continue d'envoyer des paquets de mails.

    Donc même quand le cron se déclenchera pour rien il ne consommera qu'une petite requête pour vérifier ce qu'il doit faire ou ne pas faire et c'est tout.

  7. #7
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    enfin dans ton cron tu ne mets qu'un seul "launcher", le reste de la logique c'est pour le script php qui se débrouille.

    Eventuellement tu passes un argument différent au "launcher" en fonction de la périodicité... qui permettra à php de s'avoir si c'est la newletter mensuelle ou quotidienne à expédier...

    du coup le coté "dynamique" du cron euuuh. non.

  8. #8
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2003
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 125
    Par défaut
    Citation Envoyé par ABCIWEB Voir le message
    C'est pas un problème que le cron tourne toutes les minutes ou toutes les x minutes, ça dépend de ce qu'il fait. Genre si tu stocke quelque part l'état de tes envois de mail, la première tache du cron doit être d'interroger cet état et si c'est fini il ne fait rien sinon il continue d'envoyer des paquets de mails.

    Donc même quand le cron se déclenchera pour rien il ne consommera qu'une petite requête pour vérifier ce qu'il doit faire ou ne pas faire et c'est tout.
    Donc, si j'ai bien compris ta réponse, tu dis que laisser exister le cron qui continuera "indéfiniment" par principe à être appelé n'est pas un problème si la tache qu'il lance est finie (genre, plus de mail à envoyer). Je ne suis pas (mais vraiment pas) un acharné de l'optimisation, mais ça me semble un peu extrème quand même.
    je vais essayer de préciser un exemple de scénario, tel que je l'imagine et vous me direz si mon idée est réaliste.
    J'ai disons, 1000 contacts auxquels envoyer une alerte mail. Dans la base, chacun a un flag "is_sent" (0/1).
    mon cron se déclencherait toutes les 2-3 minutes et appelerait un script sendalert.php
    Ce script :
    => dans mon idée de cron "dynamique" (à défaut d'un terme correct/exact - @gene69 en fait je dis dynamique dans le sens ou il serait créé/détruit avec php), créerait un cron en php au premier appel
    - enverrait 20 mails (à ajuster) au personnes avec un flag is_sent = 0
    - mettrait à jour leur flag
    - vérifierait qu'il reste des personnes à qui envoyer
    => s'il n'y a plus personne à qui envoyer on détruit ce cron, via php.
    => sinon, le cron sera rappelé toutes les 2-3 minutes indéfiniment et donc sera "inutile" jusqu'à ce que le client remette à jour sa base (tous les 15 jours au mieux) et ainsi remette à 0 les flags.


    Est-ce que c'est plus clair, est-ce logique...
    Le but étant d'avoir un minimum de délivrabilité des mails.
    Merci de vous intéresser à ma question.

  9. #9
    Expert confirmé

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 418
    Par défaut
    Citation Envoyé par beyo Voir le message
    Est-ce que c'est plus clair, est-ce logique...
    On avait bien compris ta question et l'on t'a expliqué comment on pouvait faire avec un cron. C'est à dire le même principe que tu énonce mais le cron ne s'éteindra jamais totalement par php (mais on le contrôlera pour qu'il n'effectue aucune tâche).

    Ou alors ce n'est plus un cron et Benjamin Delespierre t'a expliqué d'autres pistes.

    Mais même avec un cron basique et quand bien même tu serais un inconditionnel de l'optimisation, faire une requête serveur toutes les deux ou trois minutes pour vérifier s'il y a une tâche à faire ou non, n'est absolument pas un problème Sinon cela reviendrait à dire que ton serveur exploserait s'il devait afficher une seule page visiteur de plus toutes les deux ou trois minutes. Si tu en es là, avec ou sans cron, il est plus qu'urgent de changer

  10. #10
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2003
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 125
    Par défaut
    je me doute bien que vous aviez compris la question... je pensais juste que je n'avais pas été assez précis.

    Dans l'absolu, je n'ai rien contre l'idée de créer un cron qui soit là pour rien faire la plupart du temps. L'avantage c'est que je n'aurais pas à me prendre la tête à me battre avec la config du serveur pour autoriser la création via php... Je le ferai via mon interface serveur et basta.
    C'est juste que je pensais qu'on pouvais créer/(modifier)/supprimer un cron via php... Maintenant, si vous me dites que c'est plus "simple" ou efficace de laisser tourner ce cron, je vous crois

  11. #11
    Expert confirmé

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 418
    Par défaut
    Oui prends-toi pas la tête pour si peu et fais dans le classique. Ton cron pourra éventuellement servir aussi pour d'autres opérations si besoin.

    Et quand je disais plus haut que cela prendrait les ressources équivalentes à l'affichage d'une page, je suis très large car l'affichage d'une page web actuelle nécessite souvent au minimum une bonne dizaine d'accès au serveur de fichiers et autant de requêtes vers le serveur de bdd. Alors qu'un cron qui vient juste vérifier l'état des tâches à accomplir peut se résumer à un accès fichier et une requête bdd. On est donc grosso modo tout au plus sur l'équivalent ressource nécessaire pour afficher 1/10 ème de page toutes les deux ou x minutes... Alors bon ...

Discussions similaires

  1. Réponses: 1
    Dernier message: 04/05/2005, 11h43
  2. Peut-on créer une page internet via JBuilder?
    Par Xavier dans le forum JBuilder
    Réponses: 2
    Dernier message: 17/02/2005, 21h21
  3. Créer un sous-menu dynamiquement
    Par PurL dans le forum C++Builder
    Réponses: 4
    Dernier message: 09/09/2004, 10h31
  4. Créer des alias BDE dynamiquement
    Par alex4 dans le forum Bases de données
    Réponses: 3
    Dernier message: 27/05/2004, 18h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo