Use o PHP para criar, editar e excluir jobs do crontab?

116

É possível usar o PHP para criar, editar e excluir jobs do crontab?

Eu sei como listar os jobs crontab atuais do usuário Apache:

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

Mas como adicionar um cron job com PHP? 'crontab -e' apenas abriria um editor de texto e você terá que editar manualmente as entradas antes de salvar o arquivo.

E como deletar um cron job com PHP? Novamente, você terá que fazer isso manualmente com 'crontab -e'.

Com uma string de trabalho como esta:

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

Como faço para adicioná-lo à lista de jobs crontab com PHP?

datasn.io
fonte
2
possível duplicata de trabalhos Cron usando php e alguns outros
Gordon
14
(dica) o crontab é apenas um arquivo
Gordon
1
@Gordon, obrigado. Eu sei que tudo é um arquivo, mas eles estão armazenando jobs do crontab no mesmo caminho em diferentes distros? Além disso, seria necessário obter o usuário do Apache, como www-data, e ter os privilégios de root?
datasn.io
Não tenho certeza se o caminho muda entre as distros, mas você está fazendo bem em tornar o caminho um valor configurável em seu código e defini-lo em tempo de execução então. Quanto ao usuário e permissões: cada usuário pode ter um crontab que executa trabalhos com os direitos atribuídos a esse usuário, portanto, é individual para a configuração do seu sistema.
Gordon
Consulte também stackoverflow.com/q/3186471/632951
Pacerier

Respostas:

133

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

Assim,

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

O acima pode ser usado para criar e editar / anexar, desde que o usuário tenha a permissão de gravação de arquivo adequada.

Para excluir trabalhos:

echo exec('crontab -r');

Além disso, observe que o apache está sendo executado como um usuário específico e geralmente não é root, o que significa que os cron jobs só podem ser alterados para o usuário apache, a menos que seja concedido crontab -uprivilégio ao usuário apache.

ajreal
fonte
4
'Crontab -r' não apagaria todos os trabalhos do usuário? Existe alguma maneira de deletar uma linha específica de trabalho no crontabs do usuário? Carregar, pesquisar e excluir a linha encontrada parece ser a única maneira.
datasn.io
3
Você pode usar
canais em
7
Boa solução, mas shell_exec('crontab -l')retornará apenas a última linha. Eu usei exec('crontab -l', $output). Então implode o array $ output em uma string (com \ n como cola).
David Fairbanks
1
@Rahul se provedores de servidor não forneceu comandos shell como system(), passthru(), shell_exec()e exec(), tente usar o painel de controle que vem com a hospedagem, tais como cPanel ou Plesk.
Raptor
3
isso continuará acrescentando o mesmo trabalho a cada vez em um arquivo. (marcada) existe uma maneira de remover os trabalhos correspondentes primeiro e, em seguida, escrever um novo?
RT
20

Recentemente, preparamos um miniprojeto (PHP> = 5.3) para gerenciar os arquivos cron para tarefas privadas e individuais. Esta ferramenta conecta e gerencia os arquivos cron para que você possa usá-los, por exemplo, por projeto. Testes de unidade disponíveis :-)

Amostra da linha de comando:

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

Amostra da API:

use php\manager\crontab\CrontabManager;

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

Gerenciando tarefas individuais da 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
fonte
Agradável. Isso certamente será útil ... presumindo que realmente funcione :)
Baraka,
@Pacerier este projeto parece morto e tem alguns problemas. Experimente yzalis / crontab, que é mais ativo.
Jeff Puckett de
10

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

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

Remova um crontab

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

Exemplo

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
fonte
função append_cronjob não funciona para mim. Recebo a saída '-' não existe: Array ([0] => '-' não existe. [1] => uso: arquivo crontab [2] => crontab [-e | -l | -r] [3] => -e (editar crontab do usuário) [4] => -l (listar crontab do usuário) [5] => -r (excluir crontab do usuário))
user1307016
exec ('echo -e " crontab -l\ n'. $ command. '" | crontab -', $ output); está correto. Não estou recebendo crontab para www-data "-": 0: erros de minuto incorreto no arquivo crontab, não é possível instalar.
Rahul Tailwal
O Crontab delimita os trabalhos com quebras de linha (novas linhas). Cada trabalho ocupa uma linha. Portanto, se o crontab vê qualquer coisa diferente de um inteiro na primeira coluna de uma linha, ele lança o erro de “minuto ruim”, uma vez que o argumento minuto é o primeiro que o crontab encontra. confira dougv.com/2006/12/…
RafaSashi
obrigado ... como posso usar cron_TZ usando seu projeto ??
Salem Ahmed
5

Isso deve servir

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

Eu tentei a solução abaixo

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 para: Crontab Class para adicionar, editar e remover Cron Jobs

Sam T
fonte
4

Você pode tentar substituir a EDITORvariável de ambiente com algo como o edqual pode receber uma sequência de comandos de edição sobre a entrada padrão.

Alnitak
fonte
3

Depende de onde você armazena seu crontab:

shell_exec('echo "'. $job .'" >> crontab');
a liberdade
fonte
3

Você pode colocar seu arquivo em /etc/cron.d/ no formato cron. Adicione algum prefixo exclusivo ao nome do arquivo Para listar tarefas cron específicas de script, simplesmente trabalhe com uma lista de arquivos com um prefixo exclusivo. Exclua o arquivo quando quiser desativar o trabalho.

Dmitry Kireev
fonte
Eu gosto mais dessa solução porque ela evita manipular todo o arquivo cron e é fácil de remover em vez de ter que adicionar e remover uma tarefa cron específica em um arquivo cron enorme.
Jovanni G
3

Legal ...
Tente isso para remover um cron job específico (testado).

<?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
fonte
Lembre-se de adicionar exit;depois header('Location: ...');. Além disso, este formulário é realmente muito perigoso, pois pode adicionar cron job para "destruir" o servidor.
Raptor
1
Nota para iniciantes: Na verdade, não envolvemos todas as linhas do PHP em tags PHP. Um no início do PHP e, opcionalmente, um no final serão suficientes.
ekerner
0

A maneira mais fácil é usar o comando shell_exec para executar um script bash, passando os valores como parâmetros. A partir daí, você pode manipular crontabs como faria em qualquer outro script não interativo e também garantir que tenha as permissões corretas usando sudo etc.

Veja isto, Crontab sem crontab -e , para mais informações.

Codemwnci
fonte
Algumas pessoas podem estar em um host compartilhado, então isso pode não funcionar de todo.
TheRealChx101
-1

Em vez do crontab, você também pode usar a fila de tarefas do Google App Engine . Possui uma cota gratuita generosa, é rápido, escalonável e modificável.

Alfred
fonte
3
Por que não simplesmente usar o cronjob?
Pacerier
-1

É simples, você pode fazer o curl para fazer isso, certifique-se de que o curl está instalado no servidor:

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

        • *

    minuto hora dia mês semana

Digamos que você queira enviar esta notificação 14h15 todos os dias. Você pode alterar POST / GET com base em sua API:

15 14 * * * curl --request POST 'url de sua API'

dinesh kandpal
fonte