Utiliser PHP pour créer, modifier et supprimer des tâches crontab?

116

Est-il possible d'utiliser PHP pour créer, modifier et supprimer des tâches crontab?

Je sais comment répertorier les tâches crontab actuelles de l'utilisateur Apache:

$output = shell_exec('crontab -l');
echo $output;

Mais comment ajouter un travail cron avec PHP? 'crontab -e' ouvrirait simplement un éditeur de texte et vous devrez éditer manuellement les entrées avant d'enregistrer le fichier.

Et comment supprimer un travail cron avec PHP? Encore une fois, vous devez le faire manuellement par «crontab -e».

Avec une chaîne de tâche comme celle-ci:

$job = '0 */2 * * * /usr/bin/php5 /home/user1/work.php';

Comment puis-je l'ajouter à la liste des tâches crontab avec PHP?

datasn.io
la source
2
duplication possible de tâches Cron en utilisant php et quelques autres
Gordon
14
(indice) le crontab est juste un fichier
Gordon
1
@Gordon, merci. Je sais que tout est un fichier mais stockent-ils les tâches crontab sur le même chemin dans différentes distributions? De plus, il faudrait que l'utilisateur d'Apache, tel que www-data, ait les privilèges de root?
datasn.io
Je ne sais pas si le chemin change entre les distributions, mais vous faites du bien pour faire du chemin une valeur configurable dans votre code et le définir au moment de l'exécution. En ce qui concerne l'utilisateur et les autorisations: chaque utilisateur peut avoir une crontab qui exécute des travaux avec les droits attribués à cet utilisateur, c'est donc individuel pour la configuration de votre système.
Gordon
Voir également stackoverflow.com/q/3186471/632951
Pacerier

Réponses:

133

utilisation de la commande crontab

usage:  crontab [-u user] file
        crontab [-u user] [ -e | -l | -r ]
                (default operation is replace, per 1003.2)
        -e      (edit user's crontab)
        -l      (list user's crontab)
        -r      (delete user's crontab)
        -i      (prompt before deleting user's crontab)

Alors,

$output = shell_exec('crontab -l');
file_put_contents('/tmp/crontab.txt', $output.'* * * * * NEW_CRON'.PHP_EOL);
echo exec('crontab /tmp/crontab.txt');

Ce qui précède peut être utilisé à la fois pour créer et modifier / ajouter à condition que l'utilisateur dispose de l'autorisation d'écriture de fichier adéquate.

Pour supprimer des travaux:

echo exec('crontab -r');

Notez également qu'apache s'exécute en tant qu'utilisateur particulier et que ce n'est généralement pas root, ce qui signifie que les tâches cron ne peuvent être modifiées que pour l'utilisateur apache, sauf si le crontab -uprivilège est accordé à l'utilisateur apache.

ajreal
la source
4
«Crontab -r» ne supprimerait-il pas tous les travaux de l'utilisateur? Existe-t-il un moyen de supprimer une ligne spécifique de travail dans les crontabs de l'utilisateur? Charger, rechercher puis supprimer la ligne trouvée semble être le seul moyen.
datasn.io
3
Vous pouvez utiliser des tubes au lieu d'écrire un fichier temporaire
realmfoo
7
Belle solution mais shell_exec('crontab -l')ne retournera que la dernière ligne. J'ai utilisé exec('crontab -l', $output). Puis implosez le tableau $ output en une chaîne (avec \ n comme colle).
David Fairbanks
1
@Rahul si les fournisseurs de serveur n'a pas fourni de commandes shell comme system(), passthru(), shell_exec()et exec(), essayez d' utiliser le panneau de commande qui vient avec l'hébergement, comme cPanel ou Plesk.
Raptor
3
cela continuera à ajouter le même travail à chaque fois dans un fichier. (coché) existe-t-il un moyen de supprimer d'abord les travaux correspondants, puis d'en écrire un nouveau?
RT
20

Nous avons récemment préparé un mini projet (PHP> = 5.3) pour gérer les fichiers cron pour les tâches privées et individuelles. Cet outil connecte et gère les fichiers cron afin que vous puissiez les utiliser, par exemple par projet. Tests unitaires disponibles :-)

Échantillon de la ligne de commande:

bin/cronman --enable /var/www/myproject/.cronfile --user www-data

Échantillon de l'API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$crontab->enableOrUpdate('/tmp/my/crontab.txt');
$crontab->save();

Gérer des tâches individuelles à partir de l'API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$job = $crontab->newJob();
$job->on('* * * * *');
$job->onMinute('20-30')->doJob("echo foo");
$crontab->add($job);
$job->onMinute('35-40')->doJob("echo bar");
$crontab->add($job);
$crontab->save();

github: gestionnaire-php-crontab

Chris Suszyński
la source
Agréable. Cela sera certainement utile ... en supposant que cela fonctionne réellement :)
Baraka
@Pacerier ce projet semble mort et a quelques problèmes. Essayez yzalis / crontab qui est plus actif.
Jeff Puckett
10

Vérifier un cronjob

function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

Ajouter un cronjob

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

Supprimer un crontab

exec('crontab -r', $crontab);

Exemple

exec('crontab -r', $crontab);

append_cronjob('* * * * * curl -s http://localhost/cron/test1.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test2.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test3.php');
RafaSashi
la source
La fonction append_cronjob ne fonctionne pas pour moi. J'obtiens la sortie '-' n'existe pas: Array ([0] => '-' n'existe pas. [1] => utilisation: fichier crontab [2] => crontab [-e | -l | -r] [3] => -e (modifier le crontab de l'utilisateur) [4] => -l (afficher le crontab de l'utilisateur) [5] => -r (supprimer le crontab de l'utilisateur))
user1307016
exec ('echo -e " crontab -l\ n'. $ commande. '" | crontab -', $ sortie); est-ce correct. Je ne reçois pas de crontab pour www-data "-": 0: erreurs de mauvaise minute dans le fichier crontab, impossible d'installer.
Rahul Tailwal
Crontab délimite les travaux avec des sauts de ligne (retours à la ligne). Chaque travail occupe une ligne. Par conséquent, si crontab voit autre chose qu'un entier dans la première colonne d'une ligne, il renvoie l'erreur «mauvaise minute», puisque l'argument minute est le premier que crontab rencontre. Vérifiez ceci sur dougv.com/2006/12/…
RafaSashi
merci ... comment puis-je utiliser cron_TZ en utilisant votre projet ??
Salem Ahmed
5

Cela devrait le faire

shell_exec("crontab -l | { cat; echo '*/1    *    *    *    *    command'; } |crontab -");
Fred
la source
5

J'ai essayé la solution ci-dessous

class Crontab {

// In this class, array instead of string would be the standard input / output format.

// Legacy way to add a job:
// $output = shell_exec('(crontab -l; echo "'.$job.'") | crontab -');

static private function stringToArray($jobs = '') {
    $array = explode("\r\n", trim($jobs)); // trim() gets rid of the last \r\n
    foreach ($array as $key => $item) {
        if ($item == '') {
            unset($array[$key]);
        }
    }
    return $array;
}

static private function arrayToString($jobs = array()) {
    $string = implode("\r\n", $jobs);
    return $string;
}

static public function getJobs() {
    $output = shell_exec('crontab -l');
    return self::stringToArray($output);
}

static public function saveJobs($jobs = array()) {
    $output = shell_exec('echo "'.self::arrayToString($jobs).'" | crontab -');
    return $output; 
}

static public function doesJobExist($job = '') {
    $jobs = self::getJobs();
    if (in_array($job, $jobs)) {
        return true;
    } else {
        return false;
    }
}

static public function addJob($job = '') {
    if (self::doesJobExist($job)) {
        return false;
    } else {
        $jobs = self::getJobs();
        $jobs[] = $job;
        return self::saveJobs($jobs);
    }
}

static public function removeJob($job = '') {
    if (self::doesJobExist($job)) {
        $jobs = self::getJobs();
        unset($jobs[array_search($job, $jobs)]);
        return self::saveJobs($jobs);
    } else {
        return false;
    }
}

}

crédits à: Classe Crontab pour ajouter, modifier et supprimer des tâches Cron

Sam T
la source
4

Vous pouvez essayer de remplacer la EDITORvariable d'environnement par quelque chose comme edqui peut prendre une séquence de commandes d'édition sur l'entrée standard.

Alnitak
la source
3

Dépend de l'endroit où vous stockez votre crontab:

shell_exec('echo "'. $job .'" >> crontab');
thedom
la source
3

Vous pouvez placer votre fichier dans /etc/cron.d/ au format cron. Ajouter un préfixe unique au nom de fichier Pour répertorier les tâches cron spécifiques au script, il suffit de travailler avec une liste de fichiers avec un préfixe unique. Supprimez le fichier lorsque vous souhaitez désactiver la tâche.

Dmitry Kireev
la source
J'aime mieux cette solution car elle évite de manipuler tout le fichier cron et est facile à supprimer vs devoir ajouter et supprimer une tâche cron spécifique sur un énorme fichier cron.
Jovanni G
3

Bien ...
Essayez ceci pour supprimer un travail cron spécifique (testé).

<?php $output = shell_exec('crontab -l'); ?>
<?php $cron_file = "/tmp/crontab.txt"; ?>

<!-- Execute script when form is submitted -->
<?php if(isset($_POST['add_cron'])) { ?>

<!-- Add new cron job -->
<?php if(!empty($_POST['add_cron'])) { ?>
<?php file_put_contents($cron_file, $output.$_POST['add_cron'].PHP_EOL); ?>
<?php } ?>

<!-- Remove cron job -->
<?php if(!empty($_POST['remove_cron'])) { ?>
<?php $remove_cron = str_replace($_POST['remove_cron']."\n", "", $output); ?>
<?php file_put_contents($cron_file, $remove_cron.PHP_EOL); ?>
<?php } ?>

<!-- Remove all cron jobs -->
<?php if(isset($_POST['remove_all_cron'])) { ?>
<?php echo exec("crontab -r"); ?>
<?php } else { ?>
<?php echo exec("crontab $cron_file"); ?>
<?php } ?>

<!-- Reload page to get updated cron jobs -->
<?php $uri = $_SERVER['REQUEST_URI']; ?>
<?php header("Location: $uri"); ?>
<?php exit; ?>
<?php } ?>

<b>Current Cron Jobs:</b><br>
<?php echo nl2br($output); ?>

<h2>Add or Remove Cron Job</h2>
<form method="post" action="<?php $_SERVER['REQUEST_URI']; ?>">
<b>Add New Cron Job:</b><br>
<input type="text" name="add_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<b>Remove Cron Job:</b><br>
<input type="text" name="remove_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<input type="checkbox" name="remove_all_cron" value="1"> Remove all cron jobs?<br>
<input type="submit"><br>
</form>
Ajie Kurniyawan
la source
N'oubliez pas d'ajouter exit;après header('Location: ...');. En outre, cette forme est en fait assez dangereuse, car elle peut ajouter un travail cron pour «détruire» le serveur.
Raptor
1
Remarque pour les débutants: nous n'enveloppons pas réellement chaque ligne de PHP dans des balises PHP. Un au début de PHP et éventuellement un à la fin suffiront.
ekerner le
0

Le moyen le plus simple est d'utiliser la commande shell_exec pour exécuter un script bash, en passant les valeurs en paramètres. À partir de là, vous pouvez manipuler les crontabs comme vous le feriez dans tout autre script non interactif, et vous assurer également que vous disposez des autorisations appropriées en utilisant sudo, etc.

Voir ceci, Crontab sans crontab -e , pour plus d'informations.

Codemwnci
la source
Certaines personnes peuvent être dans un hôte partagé, donc cela peut ne pas fonctionner du tout.
TheRealChx101
-1

Au lieu de crontab, vous pouvez également utiliser la file d'attente des tâches du moteur d'application de Google . Il a un quota gratuit généreux, est rapide, évolutif, modifiable.

Alfred
la source
3
Pourquoi ne pas simplement utiliser cronjob?
Pacerier
-1

C'est simple Vous pouvez vous curl pour le faire, assurez-vous que curl est installé sur le serveur:

pour un déclenchement toutes les minutes: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • *

    minute heure jour mois semaine

Supposons que vous souhaitiez envoyer cette notification à 14 h 15 tous les jours.Vous pouvez modifier POST / GET en fonction de votre API:

15 14 * * * curl --request POST 'url of ur API'

dinesh kandpal
la source