Questão Por que os scripts crontab não estão funcionando?


Frequentemente, crontab os scripts não são executados no horário ou conforme o esperado. Existem inúmeras razões para isso:

  1. notação crontab errada
  2. problema de permissões
  3. variáveis ​​ambientais

Este wiki da comunidade tem como objetivo agregar as principais razões para crontab scripts não estão sendo executados como esperado. Escreva cada motivo em uma resposta separada.

Por favor inclua um motivo por resposta - detalhes sobre o porquê não foi executado - e conserte (s) por esse motivo.

Por favor escreva apenas problemas específicos do cron, por ex. comandos que executam como esperado a partir do shell mas executam erroneamente pelo cron.


455


origem


Você deve fechar crontab -e para o cron ter efeito. Por exemplo, usando vim eu edito o arquivo e uso :w para escrevê-lo, mas o trabalho não é adicionado ao cron até que eu saia também. Então eu não vou ver o trabalho até depois que eu :q Além disso. - DutGRIFF
Acho que a melhor maneira de depurar o cron é verificar o syslog e encontrar os problemas. - Suneel Kumar
No meu caso - o e-mail estava indo para a minha pasta de SPAM, então ..... verifique se antes de passar horas na depuração: D - almaruf
Interrupções de energia elétrica - Josef Klimuk


Respostas:


Ambiente diferente

Cron passa um conjunto mínimo de variáveis ​​de ambiente para seus trabalhos. Para ver a diferença, adicione um trabalho falso assim:

* * * * * env> /tmp/env.output

Esperar por /tmp/env.output para ser criado, remova o trabalho novamente. Agora compare o conteúdo de /tmp/env.output com a saída de env executado em seu terminal regular.

Uma pegadinha comum aqui é a PATH variável de ambiente sendo diferente. Talvez o seu script cron use o comando somecommand encontrado em /opt/someApp/bin, que você adicionou ao PATH dentro /etc/environment? cron ignora PATH a partir desse arquivo, então runnning somecommand a partir do seu script irá falhar quando executado com o cron, mas funciona quando executado em um terminal. Vale notar que as variáveis ​​de /etc/environment serão passados ​​para as tarefas agendadas, mas não as variáveis ​​que o cron define especificamente, como PATH.

Para contornar isso, basta definir o seu próprio PATH variável no topo do script. Por exemplo.

#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

Alguns preferem apenas usar caminhos absolutos para todos os comandos. Eu recomendo contra isso. Considere o que acontece se você quiser executar seu script em um sistema diferente e, nesse sistema, o comando está em /opt/someAppv2.2/bin em vez de. Você teria que passar pelo script inteiro substituindo /opt/someApp/bin com /opt/someAppv2.2/bin em vez de apenas fazer uma pequena edição na primeira linha do script.

Você também pode definir a variável PATH no arquivo crontab, que será aplicada a todas as tarefas do cron. Por exemplo.

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

15 1 * * * backupscript --incremental /home /root

431



Eu acho que me apaixonei por isso, e newline no final ... dupla whammy. - WernerCD
+1 para env, Eu tinha esquecido completamente desse comando e pensado que o PATH estava funcionando. Foi realmente diferente no meu caso. - Izkata
@pbr Se esses diretórios forem graváveis ​​para outros, o sistema já estará comprometido. - geirha
@br Um sysadmin pode inadvertidamente excluir o sistema de arquivos raiz. Você não pode se proteger contra os administradores de sistema fazendo erros bobos. Se você instalar uma versão mais recente de um intérprete que não seja compatível com versões anteriores, esperaria uma quebra independente. A maneira sã de lidar com isso é instalá-lo como um comando diferente. Por exemplo. você tem a versão 2.x do python e instala o python 3, você o instala como python3, não como python. E quanto a / opt / someApp / bin, por que não teria permissões / propriedade sãs? qualquer administrador sã garantiria permissões / propriedade sãs nos arquivos do sistema. - geirha
@pbr Parece que podemos continuar para sempre, sim. Eu ainda não consigo ver porque é uma má idéia usar o PATH. Se você sentir vontade de discutir isso em um meio mais adequado para discussão, você vai me encontrar no #ubuntu e #bash, entre outros canais, no irc.freenode.net - geirha


Minha melhor pegadinha: se você esquecer de adicionar uma nova linha no final do crontab Arquivo. Em outras palavras, o arquivo crontab deve terminar com uma linha vazia.

Abaixo está a seção relevante nas man pages para este problema (man crontab então pule para o final):

   Although cron requires that each entry in a crontab end  in  a  newline
   character,  neither the crontab command nor the cron daemon will detect
   this error. Instead, the crontab will appear to load normally. However,
   the  command  will  never  run.  The best choice is to ensure that your
   crontab has a blank line at the end.

   4th Berkeley Distribution      29 December 1993               CRONTAB(1)

291



isso é tão difícil, por que não foi consertado em tantos anos de cron? - Capi Etheriel
Parece ser corrigido no Vixie cron: man crontab no Ubuntu 10.10 diz que "o cron requer que cada entrada em um crontab termine em um caractere de nova linha. Se a última entrada em um crontab estiver faltando a nova linha, o cron irá considerar o crontab (pelo menos parcialmente) quebrado e se recusará a instalá-lo." (E a data no final é 19 de abril de 2010.) - Marius Gedminas
@barraponto Este é realmente um bug em novos editores de texto. O personagem "newline" deve ser um terminação de linha caractere, então a linha final em um arquivo de texto deve terminar em um caractere de nova linha que não é mostrado no editor. Vi e vim usam o caractere corretamente, e o cron foi construído antes que os novos editores iniciassem seu comportamento estranho ... Por isso, o jogo salva e inclui uma linha em branco. - Izkata
Se você editar o crontab usando crontab -e ele verificará a sintaxe do arquivo antes de permitir um salvamento, incluindo uma verificação de nova linha. - Tom Harrison Jr
@ Chan-HoSuh, de acordo com a página man "cron requer que cada entrada em um crontab termine em um caractere de nova linha. Se a última entrada em um crontab não tiver a nova linha, o cron irá considerar o crontab (pelo menos parcialmente) quebrado e se recusar a instale-o." Este comportamento será invocado durante a edição, em seguida, salvando o crontab usando o -e opção, e é independente do editor. - Tom Harrison Jr


O daemon Cron não está em execução. Eu realmente estraguei tudo isso alguns meses atrás.

Tipo:

pgrep cron 

Se você não vê nenhum número, então o cron não está rodando. sudo /etc/init.d/cron start pode ser usado para iniciar o cron.

EDIT: Em vez de invocar scripts de inicialização através de /etc/init.d, use o serviço utilidade, e.

sudo service cron start

125



Obrigado por me mostrar pgrep. Eu continuei fazendo ps -ef | grep foo - ripper234
Você também pode usar pidof cron que omitirá resultados para outras aplicações que também tenham a palavra 'cron', como crontab. - Pithikos
Estranho, tudo isso não me dá nada para mostrar que o cron está rodando, mas se eu correr sudo service cron start eu recebo start: Job is already running: cron - Colleen
service crond start se o seu centos / RHEL - Srihari Karanth


Os nomes de arquivo do script em cron.d/, cron.daily/, cron.hourly/, etc., não deve conter ponto (.), caso contrário, as partes de execução irão ignorá-las.

Veja run-parts (8):

   If neither the --lsbsysinit option nor the --regex option is given then
   the names must consist entirely of upper and lower case  letters,  dig‐
   its, underscores, and hyphens.

   If  the  --lsbsysinit  option  is given, then the names must not end in
   .dpkg-old  or .dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong  to
   one  or more of the following namespaces: the LANANA-assigned namespace
   (^[a-z0-9]+$);   the   LSB   hierarchical   and   reserved   namespaces
   (^_?([a-z0-9_.]+-)+[a-z0-9]+$);  and  the  Debian cron script namespace
   (^[a-zA-Z0-9_-]+$).

Então, se você tem um script cron backup.sh, analyze-logs.pl dentro cron.daily/ diretório, é melhor remover os nomes das extensões.


83



É um recurso que não é um bug - ele mantém coisas como myscript.backup ou myscript.original ou myscript.rpm-new sendo executadas ao lado do myscript. - pbr
@br: faz sentido. Pelo menos, teria sido útil para a depuração se run-parts --test (ou outra opção imaginária como --debug iria produzir os arquivos que ele ignora, incluindo o motivo. - Rabarberski
Se este é um recurso, não é um bom :( Muitas pessoas usam ponto no nome do arquivo (backup.sh é o mais comum). Se você quiser que um script pare de executar, o método mais lógico será remova-o do diretório "cron.d". - MatuDuke
Este é um recurso tão ruim que é efetivamente um bug. É uma prática comum exigir um final específico (como ".list" ou ".cron" ou algo assim) se as pessoas quiserem ter certeza de que as coisas só serão executadas quando pretendido. Escolher arbitrariamente o ponto como um provável separador para ".bak" ou ".temp" ou qualquer outra coisa, é completamente imprevisível, exceto na maneira como irá confundir as pessoas de maneira previsível. Endings legítimos como ".sh" e ".pl" têm sido amplamente utilizados por décadas. Muitas pessoas usam "_bak" ou "_temp" ou "-bak" em vez de um ponto, no entanto. Esta é uma escolha horrível de design; é um bug de design na melhor das hipóteses. - Teekin


Em muitos ambientes o cron executa comandos usando sh, enquanto muitas pessoas assumem que vai usar bash.

Sugestões para testar ou corrigir isso para um comando com falha:

  • Tente executar o comando em sh para ver se funciona
  • Envolva o comando em um subshell bash para ter certeza de que ele será executado no bash:
    bash -c "mybashcommand"
  • Diga ao cron para executar todos os comandos no bash definindo o shell no topo do seu crontab:
    SHELL=/bin/bash
  • Se o comando for um script, verifique se o script contém um shebang:
    #!/bin/bash

55



sugestão bash é muito útil, problema corrigido com o meu cron. - Maxim Galushka
Isso só me causou 1hr de violino / solução de problemas. Ainda mais desconcertante se você não está ciente do problema é o script será executado manualmente muito bem se você é típico shell é bashmas não com cron. Obrigado! - Hendy
Há muito tempo encontrei algo relacionado: o comando source está no bash mas não sh. No cron / sh, use um período: . envfile ao invés de source envfile. - kungphu


Eu tive alguns problemas com os fusos horários. O Cron estava sendo executado com o novo fuso horário de instalação. A solução foi reiniciar o cron:

sudo service cron restart

34



Sim, depois de alterar o fuso horário em um sistema, é necessário reiniciar todos os serviços que se preocupam com a hora ou reinicializar. Eu prefiro a reinicialização, para ter certeza de que peguei tudo. - pbr
Oh pelo amor de Deus, matou horas sobre isso. Tentei reiniciar o serviço depois * * * * * touch /tmp/cronworks não fez nada, ainda há RELOAD no cronlog. - НЛО


Se o seu comando crontab tem um % símbolo nele, cron tenta interpretá-lo. Então, se você estivesse usando qualquer comando com um % nela (como uma especificação de formato para o comando date) você precisará escapar dela.

Isso e outras boas dicas aqui:
http://www.pantz.org/software/cron/croninfo.html


29



Isto é o que tem causado o meu trabalho Cron a falhar durante a última semana. Finalmente descobri que minha Data não tinha um caractere de escape (barra invertida para qualquer outra pessoa procurando pelo que o caractere de escape é). Yay! - Valien
Veja também Como posso executar date dentro de um trabalho de guia cron? - Jared Beck
Este também me mordeu. Obrigado! - stefansundin


O caminho absoluto deve ser usado para scripts:

Por exemplo, /bin/grep deve ser usado em vez de grep:

# m h  dom mon dow   command
0 0 *  *  *  /bin/grep ERROR /home/adam/run.log &> /tmp/errors

Ao invés de:

# m h  dom mon dow   command
0 0 *  *  *  grep ERROR /home/adam/run.log &> /tmp/errors

Isso é especialmente complicado, porque o mesmo comando funcionará quando executado a partir do shell. A razão é que cron não tem o mesmo PATH variável de ambiente como o usuário.


28



veja geirha answer, você pode (deve) definir o PATH do cron - Capi Etheriel
Bzzt você NÃO precisa definir o PATH - usar caminhos absolutos é a melhor prática aqui. "porque um executável pode estar em outro lugar em algum outro computador" não trunfo "Eu quero que ele execute exatamente este programa e não algum outro alguém colocado no caminho na frente do meu programa original" - pbr
Sim, isso foi para mim, fora do cron eu poderia executar o comando diretamente, dentro do cron ele precisava de completo /usr/bin/whatever caminho - Anentropic


Também é possível que a senha do usuário tenha expirado. Mesmo a senha do root pode expirar. Você pode tail -f /var/log/cron.log e você verá o cron falhar com a senha expirada. Você pode definir a senha para nunca expirar fazendo isso: passwd -x -1 <username>

Em alguns sistemas (Debian, Ubuntu), o log para o cron não está habilitado por padrão. Dentro /etc/rsyslog.conf ou /etc/rsyslog.d/50-default.conf a linha:

# cron.*                          /var/log/cron.log

deve ser editado (sudo nano /etc/rsyslog.conf) descomentado para:

cron.*                          /var/log/cron.log

Depois disso, você precisa reiniciar o rsyslog via

/etc/init.d/rsyslog restart

ou

service rsyslog restart 

Fonte: Ativar o log de crontab no Debian Linux

Em alguns sistemas (Ubuntu), o arquivo de log separado para o cron não está habilitado por padrão, mas os logs relacionados ao cron estão aparecendo no arquivo syslog. Pode-se usar

cat /var/log/syslog | grep cron

para visualizar mensagens relacionadas ao cron.


23



Eu tenho o Debian (wheezy) mas não há /etc/init.d/rsyslog, apenas inetutils-syslogd e sysklogd. Eu tenho que instalar algo ou apenas reiniciar um dos dois? - hgoebl


Cron está chamando um script que não é executável.

Correndo chmod +x /path/to/scrip o script se torna executável e deve resolver esse problema.


21



Isso não é exclusivo para crone facilmente rastreável, simplesmente tentando executar /path/to/script da linha de comando. - Adam Matan
Se você está acostumado a executar scripts com . scriptname ou sh scriptname ou bash scriptname, então isso se torna um cronproblema específico. - Eliah Kagan