Verwenden Sie PHP, um Crontab-Jobs zu erstellen, zu bearbeiten und zu löschen?

115

Ist es möglich, mit PHP Crontab-Jobs zu erstellen, zu bearbeiten und zu löschen?

Ich weiß, wie man die aktuellen Crontab-Jobs des Apache-Benutzers auflistet:

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

Aber wie füge ich einen Cron-Job mit PHP hinzu? 'crontab -e' würde nur einen Texteditor öffnen und Sie müssen die Einträge manuell bearbeiten, bevor Sie die Datei speichern.

Und wie lösche ich einen Cron-Job mit PHP? Wieder müssen Sie dies manuell mit 'crontab -e' tun.

Mit einer Jobzeichenfolge wie dieser:

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

Wie füge ich es mit PHP zur Crontab-Jobliste hinzu?

datasn.io
quelle
2
Mögliches Duplikat von Cron-Jobs mit PHP und ein paar anderen
Gordon
14
(Hinweis) Die Crontab ist nur eine Datei
Gordon
1
@ Gordon, danke. Ich weiß, dass alles eine Datei ist, aber speichern sie Crontab-Jobs auf demselben Pfad in verschiedenen Distributionen? Außerdem müsste der Benutzer von Apache, wie z. B. www-data, über die Berechtigungen von root verfügen.
datasn.io
Ich bin nicht sicher, ob sich der Pfad über Distributionen hinweg ändert, aber Sie tun gut daran, den Pfad zu einem konfigurierbaren Wert in Ihrem Code zu machen und ihn dann zur Laufzeit festzulegen. Benutzer und Berechtigungen: Jeder Benutzer kann über eine Crontab verfügen, auf der Jobs mit den diesem Benutzer zugewiesenen Rechten ausgeführt werden. Dies ist also individuell für Ihr System-Setup.
Gordon

Antworten:

132

Verwendung des Befehls 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)

So,

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

Das Obige kann sowohl zum Erstellen als auch zum Bearbeiten / Anhängen verwendet werden, vorausgesetzt, der Benutzer verfügt über die entsprechende Berechtigung zum Schreiben von Dateien.

So löschen Sie Jobs:

echo exec('crontab -r');

Beachten Sie außerdem, dass Apache als bestimmter Benutzer ausgeführt wird und dies normalerweise nicht root ist. Dies bedeutet, dass die Cron-Jobs nur für den Apache-Benutzer geändert werden können, sofern dem Apache-Benutzer keine crontab -uBerechtigung erteilt wurde .

ajreal
quelle
4
Würde 'crontab -r' nicht alle Jobs des Benutzers löschen? Gibt es eine Möglichkeit, eine bestimmte Jobzeile in den Crontabs des Benutzers zu löschen? Das Laden, Suchen und anschließende Löschen der gefundenen Zeile scheint der einzige Weg zu sein.
Datasn.io
3
Sie können Pipes verwenden, anstatt eine temporäre Datei zu schreiben
Realmfoo
7
Gute Lösung, gibt aber shell_exec('crontab -l')nur die letzte Zeile zurück. Ich verwenden exec('crontab -l', $output). Implodieren Sie dann das $ output-Array in eine Zeichenfolge (mit \ n als Klebstoff).
David Fairbanks
1
@Rahul wenn Server - Anbieter nicht bieten Shell - Befehle wie system(), passthru(), shell_exec()und exec()versuchen , über das Bedienfeld , das mit dem Hosting, wie cPanel oder Plesk kommt.
Raptor
3
Dadurch wird jedes Mal in einer Datei derselbe Job angehängt. (aktiviert) Gibt es eine Möglichkeit, zuerst die passenden Jobs zu entfernen und dann einen neuen zu schreiben?
RT
20

Wir haben kürzlich ein Mini-Projekt (PHP> = 5.3) vorbereitet, um die Cron-Dateien für private und individuelle Aufgaben zu verwalten. Dieses Tool verbindet und verwaltet die Cron-Dateien, sodass Sie sie beispielsweise pro Projekt verwenden können. Unit Tests verfügbar :-)

Beispiel aus der Kommandozeile:

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

Beispiel aus der API:

use php\manager\crontab\CrontabManager;

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

Verwalten einzelner Aufgaben über die 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: php-crontab-manager

Chris Suszyński
quelle
Nett. Dies wird sicherlich nützlich sein ... vorausgesetzt, es funktioniert tatsächlich :)
Baraka
@ Pacerier dieses Projekt scheint tot und hat einige Probleme. Probieren Sie Yzalis / Crontab, das aktiver ist.
Jeff Puckett
10

Überprüfen Sie einen 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;
}

Fügen Sie einen Cronjob hinzu

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;
}

Entfernen Sie eine Crontab

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

Beispiel

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
quelle
Funktion append_cronjob funktioniert bei mir nicht. Ich bekomme die Ausgabe '-' existiert nicht: Array ([0] => '-' existiert nicht. [1] => Verwendung: crontab-Datei [2] => crontab [-e | -l | -r] [3] => -e (crontab des Benutzers bearbeiten) [4] => -l (crontab des Benutzers auflisten) [5] => -r (crontab des Benutzers löschen))
user1307016
exec ('echo -e " crontab -l\ n'. $ Befehl. '" | crontab -', $ output); ist es richtig. Ich erhalte kein crontab für www-data "-": 0: Fehler in der Minute in der crontab-Datei, kann nicht installiert werden.
Rahul Tailwal
Crontab begrenzt Jobs mit Zeilenumbrüchen (Zeilenumbrüchen). Jeder Job belegt eine Zeile. Wenn crontab daher in der ersten Spalte einer Zeile etwas anderes als eine Ganzzahl sieht, wird der Fehler "Bad Minute" ausgegeben, da das Argument "Minute" das erste ist, auf das Crontab stößt. check this out dougv.com/2006/12/…
RafaSashi
danke ... wie kann ich cron_TZ mit deinem Projekt verwenden?
Salem Ahmed
5

Das sollte es tun

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

Ich habe die folgende Lösung ausprobiert

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;
    }
}

}}

Credits für: Crontab-Klasse zum Hinzufügen, Bearbeiten und Entfernen von Cron-Jobs

Sam T.
quelle
4

Sie können versuchen, die EDITORUmgebungsvariable mit etwas zu überschreiben, das edeine Folge von Bearbeitungsbefehlen über die Standardeingabe übernehmen kann.

Alnitak
quelle
3

Hängt davon ab, wo Sie Ihre Crontab aufbewahren:

shell_exec('echo "'. $job .'" >> crontab');
Freiheit
quelle
3

Sie können Ihre Datei im cron-Format in /etc/cron.d/ ablegen. Hinzufügen eines eindeutigen Präfixes zum Dateinamen Um skriptspezifische Cron-Jobs aufzulisten, arbeiten Sie einfach mit einer Liste von Dateien mit einem eindeutigen Präfix. Löschen Sie die Datei, wenn Sie den Job deaktivieren möchten.

Dmitry Kireev
quelle
Ich mag diese Lösung besser, weil sie die Manipulation der gesamten Cron-Datei vermeidet und einfach zu entfernen ist, anstatt eine bestimmte Cron-Aufgabe in einer riesigen Cron-Datei hinzufügen und entfernen zu müssen.
Jovanni G
3

Schön ...
Versuchen Sie dies, um einen bestimmten Cron-Job zu entfernen (getestet).

<?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
quelle
Denken Sie daran , hinzufügen exit;nach header('Location: ...');. Außerdem ist dieses Formular tatsächlich ziemlich gefährlich, da es Cron-Jobs hinzufügen kann, um den Server zu "zerstören".
Raptor
1
Hinweis für Anfänger: Wir verpacken nicht jede Zeile von PHP in PHP-Tags. Eine am Anfang von PHP und optional eine am Ende wird ausreichen.
ekerner
0

Am einfachsten ist es, mit dem Befehl shell_exec ein Bash-Skript auszuführen und die Werte als Parameter zu übergeben. Von dort aus können Sie Crontabs wie in jedem anderen nicht interaktiven Skript bearbeiten und mithilfe von sudo usw. sicherstellen, dass Sie über die richtigen Berechtigungen verfügen.

Weitere Informationen finden Sie unter Crontab ohne Crontab -e .

Codemwnci
quelle
Einige Personen befinden sich möglicherweise in einem gemeinsam genutzten Host, sodass dies möglicherweise überhaupt nicht funktioniert.
TheRealChx101
-1

Anstelle von crontab können Sie auch die App Engine- Task-Warteschlange von Google verwenden . Es hat eine großzügige kostenlose Quote, ist schnell, skalierbar, modifizierbar.

Alfred
quelle
3
Warum nicht einfach Cronjob benutzen?
Pacerier
-1

Es ist einfach. Sie können sich dazu locken. Stellen Sie sicher, dass die Locke auf dem Server installiert ist:

zum Auslösen jeder Minute: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • * *

    Minute Stunde Tag Monat Woche

Angenommen, Sie möchten diese Benachrichtigung täglich um 14:15 Uhr senden. Sie können POST / GET basierend auf Ihrer API ändern:

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

Dinesh Kandpal
quelle