¿Usa PHP para crear, editar y eliminar trabajos crontab?

116

¿Es posible usar PHP para crear, editar y eliminar trabajos crontab?

Sé cómo enumerar los trabajos crontab actuales del usuario de Apache:

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

Pero, ¿cómo agregar un trabajo cron con PHP? 'crontab -e' simplemente abriría un editor de texto y tendrá que editar manualmente las entradas antes de guardar el archivo.

¿Y cómo eliminar un trabajo cron con PHP? Nuevamente, debe hacer esto manualmente con 'crontab -e'.

Con una cadena de trabajo como esta:

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

¿Cómo lo agrego a la lista de trabajos crontab con PHP?

datasn.io
fuente
2
posible duplicado de trabajos de Cron usando php y un par más
Gordon
14
(pista) el crontab es solo un archivo
Gordon
1
@Gordon, gracias. Sé que todo es un archivo, pero ¿están almacenando trabajos crontab en la misma ruta en diferentes distribuciones? Además, ¿necesitaría obtener el usuario de Apache, como www-data, y tener los privilegios de root?
datasn.io
No estoy seguro de si la ruta cambia en las distribuciones, pero está haciendo bien en hacer de la ruta un valor configurable en su código y configurarlo en tiempo de ejecución. En cuanto al usuario y los permisos: cada usuario puede tener un crontab que ejecuta trabajos con los derechos asignados a ese usuario, por lo que es individual para la configuración de su sistema.
Gordon
También vea stackoverflow.com/q/3186471/632951
Pacerier

Respuestas:

133

uso 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)

Entonces,

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

Lo anterior se puede utilizar tanto para crear como para editar / adjuntar siempre que el usuario tenga el permiso de escritura de archivo adecuado.

Para eliminar trabajos:

echo exec('crontab -r');

Además, tenga en cuenta que apache se ejecuta como un usuario en particular y que generalmente no es root, lo que significa que los trabajos cron solo se pueden cambiar para el usuario de apache a menos que se le crontab -uotorgue privilegios al usuario de apache.

ajreal
fuente
4
¿No eliminaría 'crontab -r' todos los trabajos del usuario? ¿Hay alguna forma de eliminar una línea específica de trabajo en las crontabs del usuario? Cargar, buscar y luego eliminar la línea encontrada parece ser la única forma.
datasn.io
3
Puede usar tuberías en lugar de escribir un archivo temporal
realmfoo
7
Buena solución, pero shell_exec('crontab -l')solo devolverá la última línea. Yo usé exec('crontab -l', $output). Luego implosione la matriz $ output en una cadena (con \ n como pegamento).
David Fairbanks
1
@Rahul si los proveedores de servidores no proporcionó comandos shell como system(), passthru(), shell_exec()y exec(), intente utilizar el panel de control que viene con el alojamiento, tales como cPanel o Plesk.
Raptor
3
esto seguirá agregando el mismo trabajo cada vez en un archivo. (marcado) ¿hay alguna manera de eliminar los trabajos coincidentes primero y luego escribir uno nuevo?
RT
20

Recientemente preparamos un mini proyecto (PHP> = 5.3) para administrar los archivos cron para tareas privadas e individuales. Esta herramienta conecta y administra los archivos cron para que pueda usarlos, por ejemplo, por proyecto. Pruebas unitarias disponibles :-)

Muestra de la línea de comando:

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

Muestra de API:

use php\manager\crontab\CrontabManager;

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

Gestión de tareas individuales desde 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
fuente
Agradable. Esto sin duda será útil ... suponiendo que realmente funcione :)
Baraka
@Pacerier este proyecto parece muerto y tiene algunos problemas. Pruebe yzalis / crontab, que es más activo.
Jeff Puckett
10

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

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

Eliminar un crontab

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

Ejemplo

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
fuente
la función append_cronjob no funciona para mí. Obtengo la salida '-' no existe: Array ([0] => '-' no existe. [1] => uso: archivo crontab [2] => crontab [-e | -l | -r] [3] => -e (editar crontab del usuario) [4] => -l (listar crontab del usuario) [5] => -r (eliminar crontab del usuario))
user1307016
exec ('echo -e " crontab -l\ n'. $ comando. '" | crontab -', $ salida); es correcto. No obtengo crontab para www-data "-": 0: errores de minutos incorrectos en el archivo crontab, no se puede instalar.
Rahul Tailwal
Crontab delimita trabajos con saltos de línea (nuevas líneas). Cada trabajo ocupa una línea. Por lo tanto, si crontab ve algo que no sea un número entero en la primera columna de una línea, arroja el error de “mal minuto”, ya que el argumento de minutos es el primero que encuentra crontab. mira
RafaSashi
gracias ... ¿cómo puedo usar cron_TZ usando su proyecto?
Salem Ahmed
5

Esto debería hacerlo

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

Probé la solución a continuación

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éditos a: Crontab Class para agregar, editar y eliminar trabajos Cron

Sam T
fuente
4

Puede intentar anular la EDITORvariable de entorno con algo como edque puede tomar una secuencia de comandos de edición sobre la entrada estándar.

Alnitak
fuente
3

Depende de dónde guarde su crontab:

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

Puede poner su archivo en /etc/cron.d/ en formato cron. Agregue un prefijo único al nombre de archivo Para enumerar los trabajos cron específicos del script, simplemente trabaje con una lista de archivos con un prefijo único. Elimine el archivo cuando desee deshabilitar el trabajo.

Dmitry Kireev
fuente
Me gusta más esta solución porque evita manipular todo el archivo cron y es fácil de eliminar frente a tener que agregar y eliminar una tarea cron específica en un archivo cron enorme.
Jovanni G
3

Bien ...
Pruebe esto para eliminar un trabajo cron específico (probado).

<?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
fuente
Recuerda agregar exit;después header('Location: ...');. Además, este formulario es bastante peligroso, ya que puede agregar un trabajo cron para "destruir" el servidor.
Raptor
1
Nota para principiantes: en realidad, no incluimos todas las líneas de PHP en etiquetas PHP. Uno al principio de PHP y opcionalmente uno al final será suficiente.
ekerner
0

La forma más sencilla es utilizar el comando shell_exec para ejecutar un script bash, pasando los valores como parámetros. A partir de ahí, puede manipular crontabs como lo haría en cualquier otro script no interactivo, y también asegurarse de tener los permisos correctos utilizando sudo, etc.

Vea esto, Crontab sin crontab -e , para más información.

Codemwnci
fuente
Algunas personas pueden estar en un host compartido, por lo que es posible que esto no funcione en absoluto.
TheRealChx101
-1

En lugar de crontab, también puede usar la cola de tareas del motor de aplicaciones de Google . Tiene una generosa cuota gratuita, es rápido, escalable, modificable.

Alfredo
fuente
3
¿Por qué no usar cronjob?
Pacerier
-1

Es simple. Puedes curl para hacerlo, asegúrate de que curl esté instalado en el servidor:

para activar cada minuto: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • *

    minuto hora día mes semana

Supongamos que desea enviar esta notificación a las 2:15 p.m. todos los días . Puede cambiar POST / GET según su API:

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

dinesh kandpal
fuente