2011-07-01 7 views
11

Si je tape crontab -l dans la ligne de commande, je peux voir la ligne suivante:Comment démarrer/arrêter un cronjob en utilisant PHP?

# * * * * * /usr/bin/php /home/user/every_minute_script.php 

Pour début cette tâche cron, je dois modifier le fichier en utilisant la commande crontab -e, supprimez le caractère de commentaire au début de la ligne, enregistrez le fichier modifié et quittez l'éditeur.

À arrêtez ce cronjob, les mêmes étapes, mais en ajoutant le caractère de commentaire au début de la ligne.

Je souhaite obtenir exactement le même effet en utilisant un script PHP , au lieu de modifier manuellement le fichier.

+0

Remarque: vous ne démarrez pas/n'arrêtez pas le travail proprement dit (votre modification n'affecte pas les travaux déjà en cours d'exécution), vous définissez simplement s'il doit démarrer la prochaine fois ou non. – Piskvor

+0

Oui. Peut-être qu'il y a une meilleure façon d'écrire cette question. Au lieu de démarrer/arrêter, peut-être activer/désactiver? –

+0

cela ressemble à un doublon de http://stackoverflow.com/questions/4421020/use-php-to-create-edit-and-delete-crontab-jobs – ben

Répondre

10

je fait quelques recherches et found in a forum, le message suivant:

Appel "crontab -e" avec la variable d'environnement EDITOR réglé sur un php script. Ce script peut modifier le fichier et quand il sortira crontab relire le fichier et mettre à jour.

Donc, j'ai essayé quelque chose, et cela a fonctionné.Je vais coller le code de travail ci-dessous:

#!/usr/bin/php 
<?php 

$on = "* * * * * /usr/bin/php /home/user/every_minute_script.php\n"; 
$off = "# * * * * * /usr/bin/php /home/user/every_minute_script.php\n"; 

$param = isset($argv[1]) ? $argv[1] : ''; 
$filename = isset($argv[2]) ? $argv[2] : ''; 

if ($param == 'activate') 
{ 
    shell_exec('export EDITOR="/home/user/cron.php on"; crontab -e'); 
} 
elseif($param == 'deactivate') 
{ 
    shell_exec('export EDITOR="/home/user/cron.php off"; crontab -e'); 
} 
elseif(in_array($param, array('on', 'off'))) 
{ 
    if (!is_writable($filename)) 
     exit(); 

    $crontab = file($filename); 
    $key = array_search($param == 'on' ? $off : $on, $crontab); 

    if ($key === false) 
     exit(); 

    $crontab[$key] = $param == 'on' ? $on : $off; 
    sleep(1); 
    file_put_contents($filename, implode('', $crontab)); 
} 

exit(); 

?> 

Comme il est, nous avons un seul script nommé cron.php situé au dossier /home/user, qui doit être exécutable (chmod a+x cron.php) et appelé à partir de la ligne de commande (PHP-CLI) . Plus tard, je vais le modifier pour fonctionner à partir du Web, ce qui est mon intention. Utilisation: ./cron.php activate pour activer le cronjob et ./cron.php deactivate pour le désactiver. Le script définit correctement la variable d'environnement EDITOR (sur elle-même) puis appelle crontab -e, qui à son tour appelle l'EDITOR (qui est maintenant le même script cron.php) en passant l'emplacement du fichier crontab temporaire en tant qu'argument. Ensuite, la ligne de crontab appropriée est trouvée et modifiée, et la version modifiée est enregistrée, en substituant le fichier temporaire. Lorsque le script se termine, crontab va se mettre à jour.

Cela fait exactement ce que je voulais, et correspond à mes besoins.

Les autres réponses sont belles et peuvent correspondre à différents besoins et scénarios, et je tiens à remercier tous ceux qui ont contribué.

+0

quand j'exécute ./cron.php activer je reçois l'erreur «? Php: No tel fichier ou répertoire» – Hunt

+0

@Hunt: assurez-vous que vous utilisez des chemins et des noms de fichiers valides ... vous devez changer '/ home/user 'pour un chemin existant –

2

Mettez votre arrêt/condition de démarrage au début de every_minute_script.php

if($condition == false) { 
    exit(); 
} 
+0

Ça a l'air bien, et j'y ai pensé. Le problème est que j'ai besoin que la sortie du cronjob soit postée pour moi (ne peut pas utiliser/dev/null). Et dans ma configuration, même avec une "exit" au début du script PHP, je recevrais un email (toutes les minutes!) ... –

+0

@J. Bruni: Ce que nous avons fait était d'utiliser un wrapper: '* * * * * /x/y/z/blah.sh &>/dev/null'; et blah.sh était un script qui exécutait le travail réel, obtenait sa sortie, et l'envoyait par la poste, à moins qu'il n'y ait pas de sortie. – Piskvor

+0

@J. Bruni - Je pensais qu'il n'y avait qu'un e-mail s'il y avait une sortie du script? –

2

Pourriez-vous placer une sorte de logique au début de every_minute_script.php qui vérifie un drapeau pour voir si elle doit faire quoi que ce soit? De cette façon, il pourrait tourner et s'arrêter rapidement s'il n'y a pas de travail à faire.

Ou est-ce trop inefficace pour vos besoins?

+0

Je viens de commenter la réponse d'Adam (semblable à la vôtre). Cette idée est belle, et peut-être la réponse finale à beaucoup de scénarios. Dans mon cas, si possible, je préfère ne pas exécuter 'every_minute_script.php'. –

+0

Pouvez-vous faire quelque chose dans la ligne de ce que suggère @Piskvor, et envoyer seulement un email quand le script fonctionne réellement et produit une sortie? –

6

Here's un tutoriel assez cool pour créer exactement ce genre de fonctionnalité avec PHP.

7

Plutôt que de déconner avec crontab programatically (qui est subtile et rapide à la colère), je vous suggère de faire un chèque à l'intérieur de votre every_minute_script.php:

if (!file_exists('/your/path/run_every_minute_script')) { 
    exit; 
} 

De cette façon, le script démarre toujours chaque minute , mais si la condition n'est pas remplie (/your/path/run_every_minute_script n'existe pas), il se terminera immédiatement sans traitement supplémentaire.

(Bien sûr, vous pouvez remplacer là des conditions différentes, par exemple la vérification de la base de données d'autorisation, etc.)


Si vous avez besoin de la sortie envoyé par la poste, vous pouvez utiliser un script d'emballage. Crontab:

* * * * * /your/path/wrapper.sh > /dev/null 2> /dev/null 

Le script wrapper exécute ensuite le bon travail, recueille sa production et les erreurs, et si ce ne sont pas vides, mails eux sur (notez que vous pouvez aussi faire le chèque à l'intérieur du script d'emballage, nous n'a pas, comme il s'appuyait sur la base de données).

+0

J'aime cette solution. Beaucoup plus élégant que de jouer avec crontab. – jahackbeth