Como criar programaticamente um novo trabalho cron?


129

Quero poder adicionar programaticamente um novo trabalho cron, qual é a melhor maneira de fazer isso?

Da minha pesquisa , parece que eu poderia despejar o crontab atual e, em seguida, acrescentar um novo, canalizando-o novamente para o crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

Existe uma maneira melhor?


2
Sua solução parece ser boa.
Craig S

No Solaris, remova o traço do último crontab. Você pode adicionar um grep para evitar adicionar uma linha já existente.
31812 Lacroix1547


chaves entre parênteses em vez de parênteses o farão sem gerar um processo. Certifique-se de manter espaços ao redor do aparelho, {...; }
Jay Winston

Respostas:


-25

Sempre funcionou bem para mim.

Você deve considerar um script um pouco mais sofisticado que pode fazer três coisas.

  1. Acrescente uma linha de crontab; assegurando que não existia. Adicionar quando já existe é ruim.

  2. Remova a linha do crontab. Talvez apenas avisando se não existisse.

  3. Uma combinação dos dois recursos acima para substituir a linha crontab.


78
Ele pergunta como e você diz a ele o que?
Cerin

1
E se o usuário ainda não tiver um crontab?
Maxim Egorushkin

132

A melhor maneira de rodar como root é soltar um arquivo no /etc/cron.d

se você usar um gerenciador de pacotes para empacotar seu software, basta colocar os arquivos nesse diretório e eles serão interpretados como se fossem crontabs, mas com um campo extra para o nome de usuário, por exemplo:

Nome do arquivo: /etc/cron.d/per_minute

Conteúdo: * * * * * root /bin/sh /home/root/script.sh


5
Apenas verifique se a versão do cron em uso suporta o /etc/cron.d/. A maioria das distribuições modernas de Linux fazem.
Sleske 06/03/09

8
Esta é a solução mais simples e elegante. Certamente é melhor analisar e editar um crontab existente com outras entradas não relacionadas.
Cerin

13
Uma ressalva em potencial é a frequência com que o cron obtém novas adições a essa pasta (uma vez por hora). Se você espera que seu trabalho comece a funcionar imediatamente, tenha cuidado.
JonathanK

6
@ JonathanK, você sabe se o cron pode ser solicitado a verificar novamente /etc/cron.d/*? É difícil saber se algo está funcionando, se é preciso esperar uma hora para verificar!
halfer

4
como as permissões devem ser definidas para esse arquivo? chmod + x /etc/cron.d/per_minute?
giò

101

A solução do OP tem um erro, pode permitir que as entradas sejam adicionadas duas vezes, use abaixo para corrigir.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
Esta é realmente uma solução melhor, se não descrita. Ele garante que o comando não seja adicionado duas vezes ao crontab.
Bufke

2
Essa dificilmente é uma boa correção para o problema de entrada duplicada. E se outra linha fosse adicionada ao crontab nesse meio tempo?
Hmn

6
Para garantir a exclusividade, logo sortantes uniq, por exemplo:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway 21/03

6
Não há necessidade uniq. Use a -uopção em sort.
papiro 12/12

6
como evitar o crontab para o usuário quando eu editar o crontab pela primeira vez.
Wyx

23

Para adicionar algo ao cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

Para remover isso do cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

a esperança ajudaria alguém


Isto é exatamente o que eu estava procurando, apenas acrescentaria o seguinte: | grep -v '^ #' | para filtrar os comentários
Tjunkie

2
Você realmente não precisa, 2>&1 | grep -v "no crontab"porque quando não há crontab, a linha de saída crontab: no crontab for...é enviada ao stderr. Não há razão para capturar essa saída, enviá-la para stdout e filtrá-la usando grep. Se seu objetivo é evitar ver crontab: no crontab for...em sua saída, use 2> /dev/null | sort.....
matty 2/09/16

6

Se você planeja fazer isso em um cenário de execução única, apenas para fazer algo, dê uma olhada em 'at'


6

Simplesmente mude o editor para o comando tee:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
Cuidado - isso limpa todas as entradas existentes.
starfry

5

Supondo que já exista uma entrada no seu crontab, o comando a seguir deve funcionar relativamente bem. Observe que a $CMDvariável está lá apenas para facilitar a leitura. A classificação antes de filtrar duplicatas é importante, porque uniqfunciona apenas em linhas adjacentes.

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

Se você atualmente possui um crontab vazio, receberá o seguinte erro no stderr:

no crontab for user

Se você quiser evitar isso, adicione um pouco de complexidade e faça algo assim:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

A maioria das soluções aqui é para adicionar linhas ao crontab. Se você precisar de mais controle, poderá controlar todo o conteúdo do crontab.

Você pode usar a tubulação para fazer isso com bastante elegância.

Para reescrever completamente o crontab, faça

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

Deve ser fácil combinar com outras respostas descritas aqui, como

crontab -l | <something> | tee |crontab -

Ou, se você tiver o conteúdo de um arquivo, é ainda mais simples

cat <file> |crontab -

3

Aqui está outra maneira de uma linha, que evita duplicatas

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

E aqui está uma maneira de responder a JohnZ e evitar a no crontab for usermensagem, ou se você precisar operar em um set -euambiente de tipo e não puder fazer nada retornar uma falha (nesse caso, a 2>/dev/nullpeça é opcional):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Ou se você deseja dividir as coisas para que sejam mais legíveis:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Ou, opcionalmente, remova qualquer referência ao seu_command (por exemplo: se o agendamento foi alterado, você só deseja que ele seja programado uma vez). Nesse caso, não precisamos mais uniq(bônus adicional, o pedido de inserção também é preservado):

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -

2

O man crontab também é útil:

CRONTAB (1)

NOME

   crontab - manipulate per-user crontabs (Dillon's Cron)

SINOPSE

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user

3
A parte que diz "substituir crontab de stdin" é na verdade meia resposta :-)
Grodriguez

2

Adicionando à resposta de JohnZ, aqui está a sintaxe para agendar como root se você é um sudoer:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

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

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

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

1

Isso verifica se o seu comando ainda não existe antes de adicioná-lo.

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

Felicidades.


0

Piping stdout para crontabnão instalou o novo crontab para mim no macOS, então encontrei esta solução, usando o teeeditor em um sub shell:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

Se você deseja que a tarefa seja executada como usuário:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

Se você deseja que a tarefa seja executada com privilégios:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

e verifique a tarefa (com ou sem 'sudo'):

crontab -l | sed '/^$/d; /#/d'


-2

Você também pode editar o arquivo de texto da tabela cron diretamente, mas sua solução parece perfeitamente aceitável.


1
Eu ficaria desconfiado disso devido a preocupações com a possibilidade de edições simultâneas causando corrupção de arquivo. O uso do comando crontab da linha de comando deve evitar esse problema.
Craig S

Craig, sem mais pesquisas, eu não teria certeza de que a versão da linha de comando é atômica e segura para as condições de corrida. Provavelmente "bastante seguro" de qualquer maneira.
tuomassalo

"Editar o arquivo diretamente" não é possível sem acesso root (desde que você possa descobrir onde está o arquivo crontab do usuário e como garantir que o daemon cron receba corretamente suas alterações), e "editar" programaticamente parece ser a pergunta. quer conselhos em primeiro lugar.
Tripleee
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.