Esta é uma pergunta canônica sobre o uso do cron e crontab.
Você foi direcionado aqui porque a comunidade tem certeza de que a resposta para sua pergunta pode ser encontrada abaixo. Se sua pergunta não for respondida abaixo, as respostas ajudarão você a coletar informações que ajudarão a comunidade a ajudá-lo. Essas informações devem ser editadas em sua pergunta original.
A resposta para ' Por que meu crontab não está funcionando e como posso solucioná-lo? ' pode ser visto abaixo. Isso aborda o cron
sistema com o crontab destacado.
Como corrigir todos os seus problemas / problemas relacionados ao crontab (Linux)
Primeiro, terminologia básica:
Em seguida, educação sobre o cron:
Cada usuário em um sistema pode ter seu próprio arquivo crontab. A localização dos arquivos crontab root e do usuário dependem do sistema, mas geralmente estão abaixo
/var/spool/cron
de .Existe um
/etc/crontab
arquivo de todo o sistema, o/etc/cron.d
diretório pode conter fragmentos crontab que também são lidos e acionados pelo cron. Algumas distribuições Linux (por exemplo, Red Hat) também possuem/etc/cron.{hourly,daily,weekly,monthly}
diretórios, scripts dentro dos quais serão executados a cada hora/dia/semana/mês, com privilégio de root.root sempre pode usar o comando crontab; usuários regulares podem ou não ter acesso. Quando você edita o arquivo crontab com o comando
crontab -e
e o salva, o crond verifica sua validade básica, mas não garante que seu arquivo crontab esteja formado corretamente. Existe um arquivo chamadocron.deny
que especificará quais usuários não podem usar o cron. Acron.deny
localização do arquivo depende do sistema e pode ser excluída, o que permitirá que todos os usuários usem o cron.Se o computador não estiver ligado ou o daemon crond não estiver em execução, e a data/hora para a execução de um comando tiver passado, o crond não recuperará e executará consultas anteriores.
detalhes do crontab, como formular um comando:
Um comando crontab é representado por uma única linha. Você não pode usar
\
para estender um comando por várias linhas. O sinal de hash (#
) representa um comentário que significa que qualquer coisa nessa linha é ignorada pelo cron. Espaços em branco à esquerda e linhas em branco são ignorados.%
Tenha MUITO cuidado ao usar o sinal de porcentagem ( ) em seu comando. A menos que eles sejam escapados\%
, eles são convertidos em novas linhas e tudo após o primeiro não escapado%
é passado para o seu comando em stdin.Existem dois formatos para arquivos crontab:
Crontabs do usuário
Todo o sistema
/etc/crontab
e/etc/cron.d
fragmentosObserve que o último requer um nome de usuário. O comando será executado como o usuário nomeado.
Os primeiros 5 campos da linha representam a(s) hora(s) em que o comando deve ser executado. Você pode usar números ou, quando aplicável, nomes de dia/mês na especificação de hora.
,
) é usada para especificar uma lista, por exemplo, 1,4,6,8, o que significa executar em 1,4,6,8.-
) e podem ser combinados com listas, por exemplo, 1-3,9-12, o que significa entre 1 e 3 e depois entre 9 e 12./
caractere pode ser usado para introduzir um passo, por exemplo, 2/5, o que significa começar em 2 e depois a cada 5 (2,7,12,17,22...). Eles não enrolam além do final.*
) em um campo significa todo o intervalo para esse campo (por exemplo,0-59
para o campo minuto).*/2
, significa começar no mínimo para o campo relevante, depois a cada 2, por exemplo, 0 para minutos (0,2...58), 1 para meses (1,3 ... 11) etc.Depurando comandos cron
Checar o e-mail!
Por padrão, o cron enviará qualquer saída do comando para o usuário em que está executando o comando. Se não houver saída, não haverá correio. Se você deseja que o cron envie e-mails para uma conta diferente, você pode definir a variável de ambiente MAILTO no arquivo crontab, por exemplo
Capture a saída você mesmo
Você pode redirecionar stdout e stderr para um arquivo. A sintaxe exata para capturar a saída pode variar dependendo de qual shell cron está usando. Aqui estão dois exemplos que salvam toda a saída em um arquivo em
/tmp/mycommand.log
:Veja os registros
O Cron registra suas ações via syslog, que (dependendo da sua configuração) geralmente vai para
/var/log/cron
ou/var/log/syslog
.Se necessário, você pode filtrar as instruções cron com, por exemplo,
Agora que vimos o básico do cron, onde estão os arquivos e como usá-los, vamos ver alguns problemas comuns.
Verifique se o cron está em execução
Se o cron não estiver em execução, seus comandos não serão agendados ...
deve te dar algo como
ou
Se não reinicie
ou
Pode haver outros métodos; use o que sua distro fornece.
cron executa seu comando em um ambiente restrito.
Quais variáveis de ambiente estão disponíveis provavelmente serão muito limitadas. Normalmente, você obterá apenas algumas variáveis definidas, como
$LOGNAME
,$HOME
e$PATH
.De particular interesse é que o
PATH
é restrito a/bin:/usr/bin
. A grande maioria dos problemas "meu script cron não funciona" são causados por esse caminho restritivo . Se o seu comando estiver em um local diferente, você pode resolver isso de duas maneiras:Forneça o caminho completo para seu comando.
Forneça um PATH adequado no arquivo crontab
Se o seu comando requer outras variáveis de ambiente, você também pode defini-las no arquivo crontab.
cron executa seu comando com cwd == $HOME
Independentemente de onde o programa que você executa resida no sistema de arquivos, o diretório de trabalho atual do programa quando o cron for executado será o diretório inicial do usuário . Se você acessar arquivos em seu programa, precisará levar isso em consideração se usar caminhos relativos ou (de preferência) apenas usar caminhos totalmente qualificados em todos os lugares e evitar muita confusão para todos.
O último comando no meu crontab não é executado
O Cron geralmente requer que os comandos sejam finalizados com uma nova linha. Edite seu crontab; vá para o final da linha que contém o último comando e insira uma nova linha (pressione enter).
Verifique o formato crontab
Você não pode usar um crontab formatado pelo usuário para /etc/crontab ou os fragmentos em /etc/cron.de vice-versa. Um crontab formatado pelo usuário não inclui um nome de usuário na 6ª posição de uma linha, enquanto um crontab formatado pelo sistema inclui o nome de usuário e executa o comando como esse usuário.
Eu coloco um arquivo em /etc/cron.{hourly,diariamente,weekly,monthly} e ele não roda
#!/bin/sh
no topo)Bugs relacionados à data cron
Se sua data foi alterada recentemente por um usuário ou atualização do sistema, fuso horário ou outro, o crontab começará a se comportar de forma irregular e exibirá bugs bizarros, às vezes funcionando, às vezes não. Esta é a tentativa do crontab de tentar "fazer o que você quer" quando o tempo muda por baixo dele. O campo "minuto" se tornará ineficaz depois que a hora for alterada. Nesse cenário, apenas asteriscos seriam aceitos. Reinicie o cron e tente novamente sem se conectar à internet (para que a data não tenha a chance de ser redefinida para um dos servidores de horário).
Sinais de porcentagem, novamente
Para enfatizar o conselho sobre os sinais de porcentagem, aqui está um exemplo do que o cron faz com eles:
irá criar o arquivo ~/cron.out contendo as 3 linhas
Isso é particularmente intrusivo ao usar o
date
comando. Certifique-se de escapar dos sinais de porcentagemComo usar
sudo
em cron jobsao executar como um usuário não root,
irá abrir o crontab do usuário, enquanto
irá abrir o crontab do usuário root. Não é recomendado executar comandos sudo em um cron job, portanto, se você estiver tentando executar um comando sudo no cron de um usuário, tente mover esse comando para o cron do root e remova o sudo do comando.
Debian Linux e seus derivados (Ubuntu, Mint, etc) possuem algumas peculiaridades que podem impedir que seus cron jobs sejam executados; em particular, os arquivos em
/etc/cron.d
,/etc/cron.{hourly,daily,weekly,monthly}
devem:O último fere regularmente usuários desavisados; em particular, qualquer script em uma dessas pastas chamada
whatever.sh
,mycron.py
,testfile.pl
, etc. não será executado, nunca.Na minha experiência, este ponto em particular tem sido de longe o motivo mais frequente para um cronjob não executável no Debian e derivados.
Veja
man cron
mais detalhes, se necessário.Se seus cronjobs pararem de funcionar, verifique se sua senha não expirou.
Haverá mensagens
/var/log/messages
semelhantes a esta abaixo que mostram problemas com a autenticação do usuário:Horários incomuns e irregulares
O Cron é considerado um agendador muito básico e a sintaxe não permite facilmente que um administrador formule agendas um pouco mais incomuns.
Considere o seguinte trabalho que normalmente seria explicado como "executar a
command
cada 5 minutos" :contra:
que nem sempre é executado a
command
cada 7 minutos .Lembre-se que o /caractere pode ser usado para introduzir um passo, mas que os passos não vão além do final de uma série, por exemplo,
*/7
que corresponde a cada 7 minutos a partir dos minutos0-59
, ou seja, 0,7,14,21,28,35,42,49, 56 mas entre uma hora e outra haverá apenas 4 minutos entre os lotes , depois que00:56
uma nova série começar em01:00
,01:07
etc. (e os lotes não serão executados em01:03
,01:10
,01:17
etc.).O que fazer em vez disso?
Crie vários lotes
Em vez de um único trabalho cron, crie vários lotes que combinados resultem no agendamento desejado.
Por exemplo, para executar um lote a cada 40 minutos (00:00, 00:40, 01:20, 02:00 etc.), crie dois lotes, um que seja executado duas vezes nas horas pares e outro que execute apenas nas horas ímpares:
Run your batches less frequently
Rather than running your batch every 7 minutes, which is a difficult schedule to break down in multiple batches, simply run it every 10 minutes instead.
Start your batches more frequently (but prevent multiple batches from running concurrently)
Many odd schedules evolve because the batch runtimes increase/fluctuate and then the batches get scheduled with a bit of additional safety margin to prevent subsequent runs of the same batch from overlapping and running concurrently.
Instead, think differently and create a cronjob that will fail gracefully when a previous run has not finished yet, but which will run otherwise. See this Q&A:
That will almost immediately start a new run once the previous run of /usr/local/bin/frequent_cron_job has completed.
Start your batches more frequently (but exit gracefully when the conditions are not right)
Since cron syntax is limited you may decide to place more complex conditions and logic in the batch job itself (or in a wrapper script around the existing batch job). That allows you to utilize the advanced capabilities of your favorite scripting languages, to comment your code and will prevent hard-to-read constructs in the crontab entry itself.
In bash the
seven-minute-job
would then look something like something like:Which you can then safely (attempt) to run every minute:
A different, but similar problem would to schedule a batch to run on the first Monday of every month (or the second Wednesday) etc. Simply schedule the batch to run every Monday and exit when date is neither between the 1st or 7th and the day of the week is not Monday.
Which you can then safely (attempt) to run every Monday:
Don't use cron
If your needs are complex you might consider using a more advanced product that is designed to run complex schedules (distributed over multiple servers) and that supports triggers, job dependencies, error handling, retries and retry monitoring etc. The industry jargon would be "enterprise" job scheduling and/or "workload automation".
Específico do PHP
Se você tiver algum trabalho cron como:
E em caso de erros, espere que eles sejam enviados a você, mas não - verifique isso.
PHP por padrão não envia erros para STDOUT. @veja https://bugs.php.net/bug.php?id=22839
Para corrigir isso, adicione no php.ini do cli ou na sua linha (ou no seu bash wrapper para PHP) estes:
A 1ª configuração permitirá que você tenha fatais como 'Memory oops' e a 2ª - para redirecioná-los todos para STDERR. Somente depois que você pode dormir bem, todos serão enviados para o e-mail do seu root em vez de apenas logados.
Adding my answer from here for completeness, and adding another potentially helpful resource:
The
cron
user has a different$PATH
than you do:A frequent problem users make with
crontab
entries is that they forget thatcron
runs in a differentenvironment
than they do as a logged-in user. For example, a user creates a program or script in his$HOME
directory, and enters the following command to run it:The command runs perfectly from his command line. The user then adds that command to his
crontab
, but finds this does not work:The reason for the failure in this case is that
./
is a different location for thecron
user than it is for the logged-in user. That is, theenvironment
is different! The PATH is part of theenvironment
, and it is usually different for thecron
user. Complicating this issue is that theenvironment
forcron
is not the same for all *nix distributions, and there are multiple versions ofcron
A simple solution to this particular problem is to give the
cron
user a complete path specification in thecrontab
entry:What is the
cron
user'senvironment
?In some instances, we may need to know the complete
environment
specification forcron
on our system (or we may just be curious). What is theenvironment
for thecron
user, and how is it different from ours? Further, we may need to know theenvironment
for anothercron
user -root
for example... what is theroot
user'senvironment
usingcron
? One way to learn this is to askcron
to tell us:~/
) as follows (or with the editor of your choice):/home/you/envtst.sh.out
. This output will show your current environment as the$USER
you're logged in as:crontab
for editing:crontab
:ANSWER: The output file
/home/you/envtst.sh.out
will contain a listing of theenvironment
for the "root cron user". Once you know that, adjust yourcrontab
entry accordingly.I can't specify the schedule I need in my
crontab
entry:The schedule entry for
crontab
is of course defined inman crontab
, and you should read this. However, readingman crontab
, and understanding the schedule are two different things. And trial-and-error on a schedule specification can become very tedious. Fortunately, there is a resource that can help: the crontab guru.. Enter your schedule specification, and it will explain the schedule in plain English language.Finally, and at risk of being redundant with one of the other answers here, do not get trapped into thinking that you are limited to a single
crontab
entry because you have one job to schedule. You are free to use as manycrontab
entries as you need to get the schedule you need.As @Seamus said, 99% of my crontab problems come from having different environmental variables or different
PATH
variables so crontab can't find the script and it fails silently. Therefore my solution was to write a wrapper script that would:PATH
variable to the same one I'm used toPYTHONPATH
to my custom one to include all of my common functionsDISPLAY
ANDDBUS
variables so that gui apps like notify-send messages actually make it to the screennice ionice -c3
to save on resources.stdout
andstderr
of the script in the "logs" directory so that when something goes wrong I can actually find out what happened.Now if I want to launch a script I just edit mycrontab with crontab -e to:
and it runs the script just as if I was trying to from the terminal without any aggravation. This was originally a BASH script, but it got hung up on arguments with spaces so I rewrote it all in python. It will even launch GUI apps into the userspace:
Make sure you double check your
$PATH
and$PYTHONPATH
variables in case you need to edit them to be different.