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

525

Geralmente, os crontabscripts não são executados dentro do cronograma ou conforme o esperado. Existem inúmeras razões para isso:

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

Este wiki da comunidade visa agregar os principais motivos para os crontabscripts não serem executados conforme o esperado. Escreva cada motivo em uma resposta separada.

Inclua um motivo por resposta - detalhes sobre por que ele não foi executado - e as correções por esse motivo.

Por favor, escreva apenas problemas específicos do cron, por exemplo, comandos que são executados conforme o esperado do shell, mas executados erroneamente pelo cron.

Adam Matan
fonte
12
Você deve fechar crontab -epara que o cron tenha efeito. Por exemplo, usando o vim, edito o arquivo e o uso :wpara 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 :qtambém.
24414 Dutticriver
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, por isso ..... verificar que, antes de passar horas na depuração: D
almaruf
Interrupções de eletricidade
Josef Klimuk 21/03

Respostas:

501

Ambiente diferente

O Cron passa um conjunto mínimo de variáveis ​​de ambiente para seus trabalhos. Para ver a diferença, adicione um trabalho fictício como este:

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

Aguarde /tmp/env.outputa criação e remova o trabalho novamente. Agora compare o conteúdo de /tmp/env.outputcom a saída de envexecução em seu terminal regular.

Uma "pegadinha" comum aqui é a PATHvariável de ambiente ser diferente. Talvez o seu script cron usa o comando somecommandencontrado em /opt/someApp/binque você adicionou a PATHem /etc/environment? O cron ignora PATHesse arquivo; portanto, a execução somecommanddo seu script falhará quando executada com o cron, mas funcionará quando executada em um terminal. Vale ressaltar que as variáveis ​​from /etc/environmentserão passadas para os trabalhos cron, mas não as variáveis ​​que o cron se define especificamente, como PATH.

Para contornar isso, basta definir sua própria PATHvariável na parte superior 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 usar apenas caminhos absolutos para todos os comandos. Eu recomendo contra isso. Considere o que acontece se você deseja executar seu script em um sistema diferente e, nesse sistema, o comando está dentro /opt/someAppv2.2/bin. Você teria que passar pelo script inteiro substituindo /opt/someApp/binpor, em /opt/someAppv2.2/binvez 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á aplicado a todos os trabalhos 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
geirha
fonte
5
Acho que me apaixonei por isso, e nova linha no final ... duplo golpe.
WernerCD
6
+1 por env, eu tinha esquecido completamente esse comando e pensei que PATH estava funcionando. Na verdade, era um pouco diferente no meu caso.
precisa saber é o seguinte
8
@pbr Se esses diretórios forem graváveis ​​para outros, o sistema já estará comprometido.
Geirha #
6
@pbr Um administrador de sistema pode excluir involuntariamente o sistema de arquivos raiz. Você não pode se proteger contra administradores de sistemas cometendo erros tolos. 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 independentemente. A maneira sensata de lidar com isso é instalá-lo como um comando diferente. Por exemplo, você tem o python versão 2.xe instala o python 3, instala-o como python3, não python. E quanto a / opt / someApp / bin, por que diabos não teria permissões / propriedade sãs? qualquer administrador sensato garantiria permissões / propriedade sensatas nos arquivos do sistema.
Geirha #
2
@pbr Parece que poderíamos continuar para sempre, sim. Ainda não entendi por que é uma má idéia usar PATH. Se você sentir vontade de discutir isso ainda mais em um meio mais adequado para a discussão, você vai me encontrar em #ubuntu e #bash, entre outros canais, em irc.freenode.net
geirha
336

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

Abaixo está a seção relevante nas páginas do manual para esse problema ( man crontabpule 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)
user4124
fonte
91
este é um showstopper, como é que ele não foi corrigido em tantos anos de cron?
Capi Etheriel
2
Parece ser corrigido no Vixie cron: man crontabno Ubuntu 10.10 diz "cron requer que cada entrada em um crontab termine com um caractere de nova linha. Se a última entrada em um crontab estiver ausente da nova linha, o cron considerará o crontab (pelo menos parcialmente) quebrado e se recusar a instalá-lo. " (E a data no final é de 19 de Abril de 2010.)
Marius Gedminas
19
@ barraponto Este é realmente um bug em novos editores de texto. O caractere "nova linha" deve ser um caractere de terminação de linha ; portanto, a linha final em um arquivo de texto deve terminar em um caractere de nova linha que não seja mostrado no editor. O Vi e o vim usam o personagem corretamente, e o cron foi construído antes dos novos editores iniciarem seu comportamento estranho ... Portanto, reproduzi-lo e salvar e incluir uma linha em branco.
Izkata 18/01/12
6
Se você editar o crontab, crontab -eele verificará a sintaxe do arquivo antes de permitir um salvamento, incluindo uma verificação de nova linha.
Tom Harrison Jr
2
@ Chan-HoSuh, de acordo com a página de manual "cron exige que cada entrada em um crontab termine com um caractere de nova linha. Se a última entrada em um crontab estiver ausente da nova linha, o cron considerará o crontab (pelo menos parcialmente) quebrado e se recusará a instale-o." Esse comportamento será chamado ao editar e salvar o crontab usando a -eopção e é independente do editor.
Tom Harrison Jr
139

O daemon Cron não está sendo executado. Eu realmente estraguei tudo isso há alguns meses atrás.

Tipo:

pgrep cron 

Se você não vir um número, o cron não está sendo executado. sudo /etc/init.d/cron startpode ser usado para iniciar o cron.

EDIT: Em vez de chamar scripts init através do /etc/init.d, use o utilitário de serviço, por exemplo

sudo service cron start

EDIT: Você também pode usar o systemctl no Linux moderno, por exemplo

sudo systemctl start cron
usuário
fonte
47
Obrigado por me mostrar pgrep. Eu continuei fazendo ps -ef | grep foo
ripper234
4
Você também pode usar o pidof cronque omitirá resultados para outros aplicativos que também tenham a palavra 'cron', como crontab.
Pithikos 11/03/14
Estranho, todos eles me dar nada para mostrar cron está em execução, mas se eu corro sudo service cron starteu recebostart: Job is already running: cron
Colleen
1
service crond startif its centos / RHEL
Srihari Karanth
91

O script nomes de arquivos em cron.d/, cron.daily/, cron.hourly/, etc., não devem conter pontos ( .), caso contrário run-parts irá ignorá-los.

Veja peças de execução (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_-]+$).

Portanto, se você tiver um script cron backup.sh, analyze-logs.plno cron.daily/diretório, é melhor remover os nomes das extensões.

Xiè Jìléi
fonte
10
É um recurso, não um bug - ele mantém coisas como myscript.backup ou myscript.original ou myscript.rpm-new funcionando ao lado de myscript.
PBR
@ pbr: faz sentido. Pelo menos teria sido útil para depuração, se run-parts --test(ou outra opção imaginário como --debugsaída seria os arquivos que ele ignora incluindo a razão.
Rabarberski
8
Se esse é um recurso, não é interessante :( Muitas pessoas usam ponto no nome do arquivo (backup.sh é o mais comum). Se você deseja que um script pare de executar, o método mais lógico será remova-o do diretório "cron.d".
MatuDuke 16/05
7
Esse é um recurso tão ruim que efetivamente é um bug. É prática comum exigir um final específico (como ".list" ou ".cron" ou algo assim) se as pessoas quiserem garantir que as coisas só sejam executadas quando pretendidas. Escolher arbitrariamente o ponto como um provável separador para ".bak" ou ".temp" ou qualquer outra coisa, é completamente imprevisível, exceto na maneira em que previsivelmente confundirá as pessoas. Finais 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. Essa é uma péssima escolha de design; é um bug de design, na melhor das hipóteses.
Teekin
68

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

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

  • Tente executar o comando shpara ver se funciona:

    sh -c "mycommand"
    
  • Embrulhe o comando em um subshell bash para garantir que ele seja executado no bash:

    bash -c "mybashcommand"
    
  • Diga ao cron para executar todos os comandos no bash, configurando o shell na parte superior do seu crontab:

    SHELL=/bin/bash
    
  • Se o comando for um script, verifique se o script contém um shebang:

    #!/bin/bash
    
Olorin
fonte
sugestão bash é muito útil, problema corrigido com o meu cron.
Maxim Galushka
Isso só me causou 1 hora de mexer / solucionar problemas. Ainda mais desconcertante, se você não está ciente do problema, o script será executado manualmente muito bem se você é um shell típico bash, mas não o é cron. Obrigado!
Hendy
Há muito tempo, encontrei algo relacionado: O comando sourceestá no bash, mas não no sh. No cron / sh, use um ponto: em . envfilevez de source envfile.
kungphu
O @Clockwork sh "mycommand"diz shpara executar o mycommand como um arquivo de script. Você quis dizer sh -c "mycommand"? De qualquer forma, essa resposta parece ser sobre como executar o comando especificamente no bash, então por que você adicionou o comando shaqui?
Olorin 8/02
@ Olorin Pelo meu entendimento, o objetivo do primeiro ponto foi tentar executá-lo com sh, para ver se o problema realmente veio do fato de o cron executá-lo com sh em vez de bash. Por outro lado, tenho pouco conhecimento sobre o assunto, então posso estar errado.
Clockwork
40

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

sudo service cron restart
luissquall
fonte
6
Sim, depois de alterar o fuso horário em um sistema, é preciso reiniciar todos os serviços que se importam com o horário, ou reiniciar. Prefiro a reinicialização, para ter certeza de que peguei tudo.
PBR
Oh, pelo amor de Deus, matou horas com isso. Tentei reiniciar o serviço depois * * * * * touch /tmp/cronworksnão fez nada, ainda existe RELOADno cronlog.
НЛО
36

O caminho absoluto deve ser usado para scripts:

Por exemplo, /bin/grepdeve 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. O motivo é que cronnão possui a mesma PATHvariável de ambiente que o usuário.

Adam Matan
fonte
3
veja geirha resposta, você pode (deve) definir PATH do cron
Capi Etheriel
9
Bzzt. você NÃO precisa definir o CAMINHO - 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 seja executado exatamente este programa e não algum outro alguém colocou no caminho na frente do meu programa original"
PBR
1
sim era isso para mim, fora do cron eu poderia executar o comando diretamente, dentro do cron que precisava completo /usr/bin/whatevercaminho
Anentropic
32

Se o seu comando crontab possui um %símbolo, o cron tenta interpretá-lo. Portanto, se você estava usando algum comando com um %(como uma especificação de formato para o comando date), será necessário escapá-lo.

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

JMS
fonte
Foi isso que causou a falha no meu trabalho de Cron na última semana. Por fim, descobri que meu Date não tinha um caractere de escape (barra invertida para outras pessoas procurando qual era o caractere de escape). Yay!
Valien
25

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

Ao executar, chmod +x /path/to/scripo script se torna executável e deve resolver esse problema.

jato
fonte
5
Isso não é exclusivo crone é facilmente rastreável, simplesmente tentando executar a /path/to/scriptpartir da linha de comando.
Adam Matan
4
Se você está acostumado a executar scripts com . scriptnameou sh scriptnameou bash scriptname, isso se torna um cronproblema específico.
Elias Kagan
24

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

Em alguns sistemas (Debian, Ubuntu), o registro do cron não é ativado por padrão. Em /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: Habilite o log do crontab no Debian Linux

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

cat /var/log/syslog | grep cron -i

para visualizar mensagens relacionadas ao cron.

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

Se o seu cronjob chama aplicativos GUI, você precisa dizer a eles que DISPLAY eles devem usar.

Exemplo: lançamento do Firefox com cron.

Seu script deve conter em export DISPLAY=:0algum lugar.

andrew
fonte
o aplay precisava deste por algum motivo. obrigado #
9404 IljaBek
* * * * * export DISPLAY=:0 && <command>
27417 LoMaPh
15

Problemas com permissões são bastante comuns, receio.

Observe que uma solução comum é executar tudo usando o crontab do root, que às vezes é uma péssima idéia. Definir permissões adequadas é definitivamente um problema amplamente esquecido.

user9521
fonte
Observe que se você tiver uma linha crontab configurada para canalizar a saída para um arquivo que ainda não existe, e o diretório do arquivo for aquele ao qual o usuário cron não tem acesso, a linha não será executada.
Evan Donovan
14

Permissão insegura da tabela cron

Uma tabela cron será rejeitada se sua permissão for insegura

sudo service cron restart
grep -i cron /var/log/syslog|tail -2
2013-02-05T03:47:49.283841+01:00 ubuntu cron[49906]: (user) INSECURE MODE (mode 0600 expected) (crontabs/user)

O problema é resolvido com

# correct permission
sudo chmod 600 /var/spool/cron/crontabs/user
# signal crond to reload the file
sudo touch /var/spool/cron/crontabs
John Peterson
fonte
Primeiro eu mesmo descobri e depois encontrei sua resposta! Ainda muito obrigado! No meu caso, eu havia revertido / restaurado alguns crontabs em / var / spool / cron / crontabs via SVN, o que alterou suas permissões!
Alfonx
12

O script é sensível à localização. Isso está relacionado ao uso sempre de caminhos absolutos em um script, mas não é o mesmo. Seu trabalho cron pode precisar de cdum diretório específico antes da execução, por exemplo, uma tarefa de rake em um aplicativo Rails pode estar na raiz do aplicativo para que o Rake encontre a tarefa correta, sem mencionar a configuração apropriada do banco de dados, etc.

Portanto, uma entrada crontab de

23 3 * * * /usr/bin/rake db:session_purge RAILS_ENV=production

seria melhor como

23 3 * * * cd / var / www / production / current && / usr / bin / rake db: session_purge RAILS_ENV = produção

Ou, para manter a entrada do crontab mais simples e menos quebradiça:

23 3 * * * /home/<user>/scripts/session-purge.sh

com o seguinte código em /home/<user>/scripts/session-purge.sh:

cd / var / www / produção / atual
/ usr / bin / rake db: session_purge RAILS_ENV = produção
pjmorse
fonte
1
Se o script que está sendo chamado do cron for escrito em uma linguagem interpretada como PHP, talvez seja necessário definir o diretório de trabalho no próprio script. Por exemplo, no PHP: chdir(dirname(__FILE__));
Evan Donovan
Só fui pego com este: o script costumava estar na raiz do meu diretório pessoal, mas então eu o mudei (e atualizei o crontab) e não consegui descobrir por que não estava funcionando. Acontece que o script estava usando um caminho relativo, assumindo que era relativo à localização do script, mas na verdade era relativo à raiz do meu diretório pessoal, porque esse era o diretório de trabalho que o cron estava usando, e é por isso que o script trabalhou quando estava na raiz do meu diretório home (porque o diretório de trabalho esperado do roteiro e é real trabalhando apenas aconteceu para coincidir).
Micheal Johnson
11

As especificações do Crontab que funcionavam no passado podem ser quebradas quando movidas de um arquivo crontab para outro. Às vezes, o motivo é que você moveu as especificações de um arquivo crontab do sistema para um arquivo crontab do usuário ou vice-versa.

O formato da especificação da tarefa cron varia entre os arquivos crontab dos usuários (/ var / spool / cron / nome de usuário ou / var / spool / cron / crontabs / nome de usuário) e os crontabs do sistema ( /etc/crontabe os arquivos inseridos /etc/cron.d).

Os crontabs do sistema têm um campo extra 'usuário' logo antes do comando para executar.

Isso causará erros informando coisas como george; command not foundquando você move um comando /etc/crontabou um arquivo /etc/cron.dpara o arquivo crontab do usuário.

Por outro lado, o cron fornecerá erros como /usr/bin/restartxyz is not a valid usernameou similares quando ocorrer o inverso.

pbr
fonte
10

O script cron está chamando um comando com a opção --verbose

Eu tive um script cron falhado em mim porque estava no piloto automático enquanto digitava o script e incluí a opção --verbose:

#!/bin/bash
some commands
tar cvfz /my/archive/file.tar.gz /my/shared/directory
come more commands

O script funcionou bem ao executar a partir do shell, mas falhou ao executar no crontab porque a saída detalhada vai para stdout quando executada no shell, mas em nenhum lugar quando executada no crontab. Correção fácil para remover o 'v':

#!/bin/bash
some commands
tar cfz /my/archive/file.tar.gz /my/shared/directory
some more commands
Aaron Peart
fonte
5
Por que isso está causando uma falha? Problemas de buffer?
Adam Matan
Quaisquer saídas ou erros trriggred via agendador de tarefas é gooing para enviado para o seu mailbox.So nunca devemos esquecer se preocupar com esses erros / output.We pode redirecioná-los para qualquer arquivo ou / dev / null
Nischay
10

A razão mais frequente pela qual vi o cron falhar em um cronograma declarado incorretamente. É necessário especificar um trabalho agendado para 23:15, em 15 23 * * *vez de * * 11 15 *ou 11 15 * * *. O dia da semana para trabalhos após a meia-noite também fica confuso. MF é 2-6depois da meia-noite, não 1-5. As datas específicas geralmente são um problema, pois raramente as usamos * * 3 1 *em 3 de março. Se você não tiver certeza, verifique suas agendas cron online em https://crontab.guru/ .

Se o seu trabalho com plataformas diferentes, usando opções não suportadas, como 2/3especificações em tempo, também pode causar falhas. Esta é uma opção muito útil, mas não universalmente disponível. Também encontrei problemas com listas como 1-5ou 1,3,5.

O uso de caminhos não qualificados também causou problemas. O caminho padrão é geralmente, /bin:/usr/binportanto, apenas os comandos padrão serão executados. Esses diretórios geralmente não têm o comando desejado. Isso também afeta scripts usando comandos não padrão. Outras variáveis ​​de ambiente também podem estar ausentes.

Derrubar completamente um crontab existente me causou problemas. Agora carrego de uma cópia do arquivo. Isso pode ser recuperado do crontab existente usando crontab -lse ele for derrotado. Eu mantenho a cópia do crontab em ~ / bin. É comentado por toda parte e termina com a linha # EOF. Isso é recarregado diariamente a partir de uma entrada do crontab como:

#! / usr / bin / crontab
# Recarregar este crontab
#
54 12 * * * $ {HOME} / bin / crontab

O comando reload acima depende de um crontab executável com um caminho estridente executando o crontab. Alguns sistemas requerem o crontab em execução no comando e especificando o arquivo. Se o diretório for compartilhado em rede, geralmente uso crontab.$(hostname)como o nome do arquivo. Isso acabará corrigindo os casos em que o crontab errado está carregado no servidor errado.

O uso do arquivo fornece um backup do que o crontab deve ser e permite que as edições temporárias (a única vez que eu uso crontab -e) sejam restauradas automaticamente. Existem cabeçalhos disponíveis que ajudam a acertar os parâmetros de agendamento. Eu os adicionei quando usuários inexperientes editariam um crontab.

Raramente, encontrei comandos que exigem entrada do usuário. Eles falham no crontab, embora alguns funcionem com o redirecionamento de entrada.

BillThor
fonte
3
Isso cobre três problemas separados. Eles podem ser divididos em respostas separadas?
Elias Kagan
9
Você pode explicar como é 30 23 * * * traduzido para 23:15?
JYelton
@ JYelton Isso estava obviamente errado, deveria estar 15 23 * * *. Corrigido agora.
Melebius
7

Se você estiver acessando uma conta através de chaves SSH, é possível fazer login na conta, mas não perceber que a senha da conta está bloqueada (por exemplo, devido a tentativas de senha expiradas ou inválidas)

Se o sistema estiver usando o PAM e a conta estiver bloqueada, isso poderá interromper a execução do cronjob. (Eu testei isso no Solaris, mas não no Ubuntu)

Você pode encontrar mensagens como esta em / var / adm / messages:

24 de outubro 07:51:00 mybox cron [29024]: [ID 731128 auth.notice] pam_unix_account: cron tentando validar myuser de conta bloqueada do host local
24 de outubro 07:52:00 mybox cron [29063]: [ID 731128 auth.notice] pam_unix_account: cron tentando validar myuser de conta bloqueada do host local
24 de outubro 07:53:00 mybox cron [29098]: [ID 731128 auth.notice] pam_unix_account: cron tentando validar myuser de conta bloqueada do host local
24 de outubro 07:54:00 mybox cron [29527]: [ID 731128 auth.notice] pam_unix_account: cron tentando validar myuser de conta bloqueada do host local

Tudo o que você precisa fazer é executar:

# passwd -u <NOME DO USUÁRIO>

como root para desbloquear a conta e o crontab deve funcionar novamente.

JohnGH
fonte
7

Se você possui um comando como este:

* * * * * /path/to/script >> /tmp/output

e ele não funciona e você não pode ver nenhuma saída, pode não necessariamente significar que o cron não está funcionando. O script pode estar quebrado e a saída vai para o stderr, que não é passada para / tmp / output. Verifique se não é esse o caso, capturando esta saída também:

* * * * * /path/to/script >> /tmp/output 2>&1

para ver se isso ajuda a detectar seu problema.

Philluminati
fonte
3

=== Alerta do Docker ===

Se você estiver usando o docker,

Eu acho que é apropriado acrescentar que não consegui fazer o cron rodar em segundo plano.

Para executar um trabalho cron dentro do contêiner, usei supervisor e executei cron -f, juntamente com o outro processo.

Edit: Outro problema - eu também não consegui fazê-lo funcionar ao executar o contêiner com a rede HOST. Veja também este problema aqui: https://github.com/phusion/baseimage-docker/issues/144

AlonL
fonte
3

Eu estava escrevendo um script de shell de instalação que cria outro script para limpar dados de transação antigos de um banco de dados. Como parte da tarefa, ele precisava configurar o crontrabalho diário para ser executado em um momento arbitrário, quando a carga do banco de dados era baixa.

Criei um arquivo mycronjobcom cron sched, nome de usuário e comando e copiei para o /etc/cron.ddiretório Minhas duas dicas:

  1. mycronjob o arquivo tinha que pertencer ao root para ser executado
  2. Eu tive que definir as permissões do arquivo para 644 - 664 não seria executado.

Um problema de permissão aparecerá /var/log/syslogcomo algo semelhante a:

Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/crontab)
Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/cron.d/user)

A primeira linha refere-se ao /etc/crontabarquivo e a posterior a um arquivo que eu coloquei abaixo /etc/cront.d.

Izik Golan
fonte
2

Linha escrita de uma maneira que o crontab não entende. Ele precisa ser escrito corretamente. Aqui está o CrontabHowTo .

Canguru
fonte
1
Como isso pode ser depurado?
Adam Matan
A revisão do log de erros do cron é a maneira mais comum. O IIRC 'crontab -e' faz uma análise de sintaxe após a edição do arquivo também - mas isso pode não ser universal.
PBR
2

O daemon Cron pode estar em execução, mas na verdade não está funcionando. Tente reiniciar o cron:

sudo /etc/init.d/cron restart
Phil Dodd
fonte
3
Eu nunca vi esse caso em produção. Não significa que isso não aconteceu - apenas que eu não o vejo nos 30 anos em que uso o UNIX e o Linux. Cron é incrivelmente robusto.
PBR
1
Não tenho certeza, mas acho que isso realmente aconteceu comigo. Eu tentei pidofcron e não tenho nada. Tentei usar o serviceutilitário e disse que o cron já estava em execução. Apenas executei este comando e executei pidofnovamente e recebo um resultado.
Colleen
2

Escrevendo no cron via "crontab -e" com o argumento de nome de usuário em uma linha. Já vi exemplos de usuários (ou administradores de sistemas) escrevendo seus scripts de shell e sem entender por que eles não automatizam. O argumento "user" existe em / etc / crontab, mas não nos arquivos definidos pelo usuário. então, por exemplo, seu arquivo pessoal seria algo como:

# m h dom mon dow command

* * */2  *   *  /some/shell/script

considerando que / etc / crontab seria:

# m h dom mon dow user   command

* * */2  *   *  jdoe   /some/shell/script

Então, por que você faria o último? Bem, dependendo de como você deseja definir suas permissões, isso pode se tornar muito complicado. Escrevi scripts para automatizar tarefas para usuários que não entendem os meandros ou que não querem se preocupar com a labuta. Ao definir permissões para --x------, posso tornar o script executável sem que eles possam lê-lo (e talvez alterá-lo acidentalmente). No entanto, talvez eu queira executar esse comando com vários outros de um arquivo (facilitando a manutenção), mas certifique-se de que a saída do arquivo seja atribuída ao proprietário certo. Fazer isso (pelo menos no Ubuntu 10.10) quebra tanto a incapacidade de ler o arquivo quanto a sua execução, além do problema mencionado anteriormente com a colocação de períodos no / etc / crontab (que, curiosamente, não causa erros durante a execução crontab -e) .

Como exemplo, eu vi instâncias sudo crontab -eusadas para executar um script com permissões de root, com uma correspondente chown username file_outputno shell script. Desleixado, mas funciona. IMHO, a opção mais elegante é colocá-lo /etc/crontabcom o nome de usuário declarado e as permissões apropriadas, file_outputpara o local e o proprietário certos.

da sarna
fonte
"Fazer isso (pelo menos no Ubuntu 10.10) quebra a incapacidade de ler o arquivo e executar ....." Devo esclarecer: / etc / crontab (por padrão) requer permissões de leitura e execução, enquanto você PODE execute "sudo crontab -e" para criar um cronjob que substitua a necessidade da permissão "w" e o problema com extensões como ".sh". Não tive tempo de separar o código cron e verificar por que isso funciona, apenas um detalhe que notei.
Mange
2

Construindo o que Aaron Peart mencionou sobre o modo detalhado, às vezes os scripts que não estão no modo detalhado serão inicializados, mas não serão finalizados, se o comportamento padrão de um comando incluído for gerar uma linha ou mais na tela assim que o proc for iniciado. Por exemplo, escrevi um script de backup para nossa intranet que usava curl, um utilitário que baixa ou carrega arquivos em servidores remotos, e é bastante útil se você puder acessar apenas os arquivos remotos por HTTP. O uso de 'curl http://something.com/somefile.xls ' estava causando a interrupção de um script que eu escrevi e nunca foi concluído porque gera uma nova linha seguida por uma linha de progresso. Eu tive que usar o sinalizador silencioso (-s) para dizer para não gerar nenhuma informação e escrever em meu próprio código para lidar com o erro no download do arquivo.

Sarna
fonte
1
Para programas que não possuem um modo silencioso, você pode redirecionar sua saída para /dev/null. Por exemplo: some-command > /dev/nullIsso redirecionará apenas a saída padrão, e não a saída de erro (que geralmente é o que você deseja, pois deseja ser informado sobre erros). Para redirecionar também a saída de erro, use some-command &> /dev/null.
Eliah Kagan
Sim, esse foi meu primeiro pensamento ao escrever o roteiro mencionado anteriormente. Eu esqueço por que não usei isso, possivelmente algum comportamento não-padrão que contornou a referida solução. Eu sei que o modo detalhado / interativo é o padrão em alguns comandos (estou olhando para VOCÊ, scp!), O que significa que você precisa usar a referida saída para o bom funcionamento dos scripts de shell.
Mange
2

Embora você possa definir variáveis ​​de ambiente em seu crontable, você não está em um script de shell. Portanto, construções como as seguintes não funcionarão:

SOME_DIR=/var/log
MY_LOG_FILE=${SOME_LOG}/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=${BIN_DIR}/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}

Isso ocorre porque as variáveis ​​não são interpretadas no crontable: todos os valores são tomados literalmente. E é o mesmo se você omitir os colchetes. Portanto, seus comandos não serão executados e seus arquivos de log não serão gravados ...

Em vez disso, você deve definir todas as suas variáveis ​​de ambiente diretamente:

SOME_DIR=/var/log
MY_LOG_FILE=/var/log/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=/usr/local/bin/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}
Alexandre
fonte
2

Quando uma tarefa é executada no cron, o stdin é fechado. Os programas que agem de maneira diferente, com base na disponibilidade ou não do stdin, terão um comportamento diferente entre a sessão do shell e o cron.

Um exemplo é o programa goaccesspara analisar arquivos de log do servidor da web. Isso NÃO funciona no cron:

goaccess -a -f /var/log/nginx/access.log > output.html

e goaccessmostra a página de ajuda em vez de criar o relatório. Na concha, isso pode ser reproduzido com

goaccess -a -f /var/log/nginx/access.log > output.html < /dev/null

A correção para isso goaccessé fazê-lo ler o log do stdin em vez de ler o arquivo, portanto, a solução é alterar a entrada do crontab para

cat /var/log/nginx/access.log | goaccess -a > output.html
Martijn de Milliano
fonte
2

No meu caso, cron e crontab tinham proprietários diferentes.

NÃO funcionando eu tinha o seguinte:

User@Uva ~ $ ps -ef | grep cron | grep -v grep
User    2940    7284 pty1     19:58:41 /usr/bin/crontab
SYSTEM   11292     636 ?        22:14:15 /usr/sbin/cro 

Basicamente, eu tive que executar o cron-config e responder às perguntas corretamente. Há um ponto em que fui solicitado a inserir minha senha de usuário Win7 para minha conta 'Usuário'. Pela leitura que fiz, parece que esse é um problema de segurança em potencial, mas sou o único administrador em uma única rede doméstica e, por isso, decidi que estava tudo bem.

Aqui está a sequência de comandos que me motivou:

User@Uva ~ $ cron-config
The cron daemon can run as a service or as a job. The latter is not recommended.
Cron is already installed as a service under account LocalSystem.
Do you want to remove or reinstall it? (yes/no) yes
OK. The cron service was removed.

Do you want to install the cron daemon as a service? (yes/no) yes
Enter the value of CYGWIN for the daemon: [ ] ntsec

You must decide under what account the cron daemon will run.
If you are the only user on this machine, the daemon can run as yourself.
   This gives access to all network drives but only allows you as user.
To run multiple users, cron must change user context without knowing
  the passwords. There are three methods to do that, as explained in
  http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-nopasswd1
If all the cron users have executed "passwd -R" (see man passwd),
  which provides access to network drives, or if you are using the
  cyglsa package, then cron should run under the local system account.
Otherwise you need to have or to create a privileged account.
  This script will help you do so.
Do you want the cron daemon to run as yourself? (yes/no) no

Were the passwords of all cron users saved with "passwd -R", or
are you using the cyglsa package ? (yes/no) no

Finding or creating a privileged user.
The following accounts were found: 'cyg_server' .
This script plans to use account cyg_server.
Do you want to use another privileged account name? (yes/no) yes
Enter the other name: User

Reenter: User


Account User already exists. Checking its privileges.
INFO: User is a valid privileged account.
INFO: The cygwin user name for account User is User.

Please enter the password for user 'User':
Reenter:
Running cron_diagnose ...
... no problem found.

Do you want to start the cron daemon as a service now? (yes/no) yes
OK. The cron daemon is now running.

In case of problem, examine the log file for cron,
/var/log/cron.log, and the Windows event log (using /usr/bin/cronevents)
for information about the problem cron is having.

Examine also any cron.log file in the HOME directory
(or the file specified in MAILTO) and cron related files in /tmp.

If you cannot fix the problem, then report it to [email protected].
Please run the script /usr/bin/cronbug and ATTACH its output
(the file cronbug.txt) to your e-mail.

WARNING: PATH may be set differently under cron than in interactive shells.
         Names such as "find" and "date" may refer to Windows programs.


User@Uva ~ $ ps -ef | grep cron | grep -v grep
    User    2944   11780 ?        03:31:10 /usr/sbin/cron
    User    2940    7284 pty1     19:58:41 /usr/bin/crontab

User@Uva ~ $
KiloOne
fonte
1
Embora bem documentado, isso parece um ponto específico do Cygwin; ele realmente pertence ao askubuntu?
Sxc731 07/02
2

Nos meus servidores RHEL7, os trabalhos raiz do cron eram executados, mas os trabalhos do usuário não. Descobri que sem um diretório inicial, os trabalhos não serão executados (mas você verá bons erros em / var / log / cron). Quando eu criei o diretório inicial, o problema foi resolvido.

Dennis Parslow
fonte
2

Se você editou seu arquivo crontab usando um editor do Windows (via samba ou algo assim) e substituiu as novas linhas por \ n \ r ou apenas \ r, o cron não será executado.

Além disso, se você estiver usando o /etc/cron.d/* e um desses arquivos tiver um \ r, o cron passará pelos arquivos e parará quando encontrar um arquivo incorreto. Não tem certeza se esse é o problema?

Usar:

od -c /etc/cron.d/* | grep \r
Doug
fonte