Utilizzare PHP per creare, modificare ed eliminare i lavori crontab?


116

È possibile utilizzare PHP per creare, modificare ed eliminare lavori crontab?

So come elencare i lavori crontab correnti dell'utente Apache:

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

Ma come aggiungere un cron job con PHP? 'crontab -e' aprirà semplicemente un editor di testo e dovrai modificare manualmente le voci prima di salvare il file.

E come eliminare un cron job con PHP? Di nuovo devi farlo manualmente con "crontab -e".

Con una stringa di lavoro come questa:

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

Come posso aggiungerlo all'elenco dei lavori crontab con PHP?


2
possibile duplicato di lavori Cron utilizzando php e un paio di altri
Gordon

14
(suggerimento) il crontab è solo un file
Gordon

1
@ Gordon, grazie. So che tutto è un file ma memorizzano i lavori crontab nello stesso percorso su distribuzioni diverse? Inoltre sarebbe necessario ottenere l'utente di Apache, come www-data, e avere i privilegi di root?
datasn.io

Non sono sicuro che il percorso cambi tra le distribuzioni, ma stai facendo bene a rendere il percorso un valore configurabile nel tuo codice e impostarlo in fase di esecuzione. Per quanto riguarda l'utente e le autorizzazioni: ogni utente può avere un crontab che esegue lavori con i diritti assegnati a quell'utente, quindi questo è individuale per la configurazione del sistema.
Gordon

Risposte:


133

utilizzo del comando 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)

Così,

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

Quanto sopra può essere utilizzato sia per creare che per modificare / aggiungere a condizione che l'utente disponga dell'autorizzazione di scrittura del file adeguata.

Per eliminare i lavori:

echo exec('crontab -r');

Inoltre, prendi nota che apache è in esecuzione come un particolare utente e di solito non è root, il che significa che i cron job possono essere modificati solo per l'utente apache a meno che non venga concesso il crontab -uprivilegio all'utente apache.


4
"Crontab -r" non cancellerebbe tutti i lavori dell'utente? Esiste un modo per eliminare una specifica riga di lavoro nei crontabs dell'utente? Il caricamento, la ricerca e quindi l'eliminazione della riga trovata sembra essere l'unico modo.
datasn.io

3
Puoi usare pipe invece di scrivere un file temporaneo
realmfoo

7
Bella soluzione ma shell_exec('crontab -l')restituirà solo l'ultima riga. Ho usato exec('crontab -l', $output). Quindi implodere l'array $ output in una stringa (con \ n come collante).
David Fairbanks

1
@Rahul se fornitori di server non ha fornito comandi shell come system(), passthru(), shell_exec()e exec(), provare a utilizzare il pannello di controllo che viene fornito con l'hosting, come ad esempio cPanel o Plesk.
Raptor

3
questo continuerà ad aggiungere lo stesso lavoro ogni volta in un file. (selezionato) esiste un modo per rimuovere prima i lavori corrispondenti e poi scriverne uno nuovo?
RT

20

Recentemente abbiamo preparato un mini progetto (PHP> = 5.3) per gestire i file cron per attività private e individuali. Questo strumento collega e gestisce i file cron in modo da poterli utilizzare, ad esempio per progetto. Test unitari disponibili :-)

Esempio dalla riga di comando:

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

Esempio da API:

use php\manager\crontab\CrontabManager;

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

Gestione di singole attività dall'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


Bello. Questo tornerà sicuramente utile ... supponendo che funzioni davvero :)
Baraka

@Pacerier questo progetto sembra morto e ha alcuni problemi. Prova yzalis / crontab che è più attivo.
Jeff Puckett

10

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

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

Rimuovi un crontab

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

Esempio

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');

la funzione append_cronjob non funziona per me. Ottengo l'output "-" non esiste: Array ([0] => "-" non esiste. [1] => utilizzo: crontab file [2] => crontab [-e | -l | -r] [3] => -e (modifica crontab dell'utente) [4] => -l (elenca crontab dell'utente) [5] => -r (elimina crontab dell'utente))
user1307016

exec ('echo -e " crontab -l\ n'. $ comando. '" | crontab -', $ output); è corretto. Non ricevo crontab per www-data "-": 0: errori di minuti non corretti nel file crontab, impossibile installare.
Rahul Tailwal

Crontab delimita i lavori con interruzioni di riga (newline). Ogni lavoro occupa una riga. Pertanto, se crontab vede qualcosa di diverso da un intero nella prima colonna di una riga, genera l'errore "bad minute", poiché l'argomento minute è il primo che crontab incontra. dai un'occhiata a dougv.com/2006/12/…
RafaSashi

grazie ... come posso usare cron_TZ usando il tuo progetto ??
Salem Ahmed

5

Questo dovrebbe bastare

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

5

Ho provato la soluzione di seguito

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

}

crediti a: Crontab Class to Add, Edit and Remove Cron Jobs


4

Potresti provare a sovrascrivere la EDITORvariabile d'ambiente con qualcosa di simile edche può accettare una sequenza di comandi di modifica sull'input standard.


3

Dipende da dove archivi il tuo crontab:

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

3

Puoi mettere il tuo file in /etc/cron.d/ in formato cron. Aggiungere un prefisso univoco al nomefile Per elencare i cron job specifici dello script è sufficiente lavorare con un elenco di file con un prefisso univoco. Elimina il file quando desideri disabilitare il lavoro.


Mi piace di più questa soluzione perché evita di manipolare l'intero file cron ed è facile da rimuovere rispetto a dover aggiungere e rimuovere un'attività cron specifica su un file cron enorme.
Jovanni G

3

Bello ...
Prova questo per rimuovere un cron job specifico (testato).

<?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>

Ricordati di aggiungere exit;dopo header('Location: ...');. Inoltre, questo modulo è in realtà piuttosto pericoloso, in quanto può aggiungere cron job per "distruggere" il server.
Raptor

1
Nota per i principianti: in realtà non racchiudiamo ogni riga di PHP nei tag PHP. Uno all'inizio di PHP e uno alla fine facoltativamente saranno sufficienti.
ekerner

0

Il modo più semplice è usare il comando shell_exec per eseguire uno script bash, passando i valori come parametri. Da lì, puoi manipolare i crontab come faresti in qualsiasi altro script non interattivo e assicurarti anche di avere le autorizzazioni corrette usando sudo ecc.

Vedi questo, Crontab senza crontab -e , per maggiori informazioni.


Alcune persone potrebbero trovarsi in un host condiviso, quindi potrebbe non funzionare affatto.
TheRealChx101

-1

Invece di crontab puoi anche usare la coda delle attività del motore dell'app di Google . Ha una generosa quota gratuita, è veloce, scalabile, modificabile.


3
Perché non usare semplicemente cronjob?
Pacerier

-1

È semplice Puoi piegarti per farlo, assicurati che curl sia installato sul server:

per l'attivazione ogni minuto: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • *

    minuto ora giorno mese settimana

Supponiamo che tu voglia inviare questa notifica alle 14:15 tutti i giorni. Puoi modificare POST / GET in base alla tua API:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.