Como configurar um trabalho cron de raiz corretamente

36

Tentei configurar um trabalho cron do root para executar um script Bash como root, para executar no minuto 7,37, a cada hora, todos os dias do mês, todos os meses. Este script está localizado /usr/bine nomeado tunlrupdate.sh. Ele atualiza o DNS do Tunlr.

$ ls -l /usr/bin/tunlrupdate.sh 
-rwxr-xr-x 1 root root 2133 Sep 24 15:42 /usr/bin/tunlrupdate.sh

Este script Bash está disponível aqui .

Quando chamado, o script grava o que está acontecendo em um log localizado em /var/log/tunlr.log

Para adicionar este trabalho cron do root, usei o padrão para o crontab do root

sudo crontab -e

E inseriu essas 2 linhas no final. Espero que o cron execute o script como root.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * root /usr/bin/tunlrupdate.sh

Um comando posterior sudo crontab -lconfirmou que o trabalho cron foi inserido.

Eu reiniciei o Ubuntu e estava verificando no arquivo de log se o trabalho cron foi iniciado corretamente. No entanto, não há nada no arquivo de log, o que /var/log/tunlr.logsignifica que o trabalho nunca foi iniciado com êxito.

Eu verifiquei se eu executava o script na linha de comando

sudo /usr/bin/tunlrupdate.sh

o arquivo de log é atualizado de acordo.

Por que esse trabalho cron não está sendo executado conforme o planejado no meu sistema?

ATUALIZAÇÃO 1: Todas as soluções propostas até agora não funcionam. Agradeço a Olli por uma CLI para listar o log do sistema sudo grep CRON /var/log/syslog. No entanto, recebi um erro CRON

CRON[13092]: (root) CMD (  [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ]
&& find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php
/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete)

com o PATH sugerido = inserção e uso do caminho absoluto da raiz para funções no script ou sem as soluções sugeridas aqui. Eu ainda recebo esse erro.

Após algumas pesquisas, identifiquei o erro no arquivo, /usr/lib/php5/maxlifetimeconforme explicado aqui :Change #!/bin/sh -e --> #!/bin/sh -x

Em seguida, listando o log de erros CRON no meu sistema

sudo grep CRON /var/log/syslog
Feb 11 18:07:01 Marius-PC CRON[14067]: (root) CMD (root /usr/bin/tunlrupdate.sh)
Feb 11 18:07:01 Marius-PC CRON[14066]: (root) MAIL (mailed 1 byte of output; but got
status 0x00ff, #012)

Ainda não consigo executar o script bash. Desta vez, nenhum erro é mostrado no log. Para obter garantia de que esse não era o conteúdo do script, reduzi o script para as três linhas a seguir:

#!/bin/bash
LOGFILE=/var/log/tunlr.log
echo $LOGFILE >> $LOGFILE

Ainda não recebi o trabalho do cron. Nada está escrito no arquivo de log. Então, mesmo pode ser um script vazio não será executado no cron? Eu não entendo. Eu sei que tentando um script reduzido a estas 2 linhas:

#!/bin/bash
exit 0

E ainda o mesmo log de erros. O script cron não passa por ...

Antonio
fonte
Se você deseja criar um cronjob "root", você deve ser root e digitar crontab -e. Além disso, você só precisa fazer o login como root (tipo de console "su root") e depois crontab -e (sudo não é necessário neste caso).
Wolfgang
Bem. Não vejo o ponto da sua resposta? Digitar $ sudo crontab -e fez o trabalho conforme relatado por $ sudo crontab -l, ou seja, a linha que descreve o novo trabalho foi adicionada ao cron da raiz. Por si só, o trabalho não está presente no cron do usuário, por exemplo, $ crontab -l não mostra que nenhum trabalho cron foi adicionado aqui.
Antonio
@WolfgangVogl ele usou "sudo", que funciona como esperado.
Alexis Wilke

Respostas:

68

Se você deseja executar um script como um usuário normal :

crontab -e

E adicione a linha:

07,37 * * * * /usr/bin/tunlrupdate.sh

Se você deseja executar seu script como root :

sudo crontab -e

E adicione a mesma linha:

07,37 * * * * /usr/bin/tunlrupdate.sh
Guillaume
fonte
@NineCattoRules Se você não soltar a saída, o que vê?
Angelo Fuchs
@AngeloFuchs comentário antigo ... certamente eu tentei esse comando como root (em sudo crontab -evez de crontab -e). Ou qualquer outra coisa, de qualquer maneira ele funciona
NineCattoRules
10

Bem, finalmente a solução de trabalho. No syslog, vi o repetitivo e intrigante:

CRON[18770]: (root) CMD (root /usr/bin/tunlrupdate.sh)

Parece que a raiz não foi reconhecida como um cmd. Como eu já usei o cron da raiz usando $ sudo /usr/bin/tunlrupdate.sh. Então tentei com o script original (corrigido um erro na data UNIX cmd:% m que é mês foi usado por minutos que é% M) o seguinte (que remove a raiz da linha cron):

$ sudo crontab -e
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * /usr/bin/tunlrupdate.sh

Isso acabou sendo a solução final. [Embora eu tenha encontrado várias publicações indicando a linha incorreta com raiz na linha cron. Isso foi um erro].

Antonio
fonte
Bom ponto Olli. Eu concordo com você nisso. Para referência, o usuário crontab é armazenado em / var / spool / cron / crontabs / nome do usuário ou em root / var / spool / cron / crontabs / root. Veja esta página askubuntu.com/questions/216692/where-is-the-user-crontab-stored A pasta que contém já existe e fornece o nome do usuário.
Antonio
Bem, você não precisa dessas informações, pois só deve editar os arquivos crontab com o crontabcomando (exceto os arquivos crontab abaixo /etc).
Olli
1
@Antonio as pontuações com o campo nome de usuário são usadas apenas /etc/crontab(o crontab em todo o sistema). Usando sudo crontab -evocê está trabalhando com crontab do root, que normalmente pode ser encontrado em/var/spool/cron/crontabs
Matijs
2

Um "problema" com o cron é a falta de variáveis ​​de ambiente (por razões óbvias de segurança). Você provavelmente está perdendo PATH e HOME. Você pode definir aqueles no script diretamente ou no arquivo crontab.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
PATH=/usr/bin
07,37 * * * * root /usr/bin/tunlrupdate.sh

Você precisará testar até que todas as variáveis ​​necessárias sejam definidas conforme exigido pelo script.

Alexis Wilke
fonte
1
Esta é a única resposta aqui que realmente funcionou para mim. Copiei as instruções SHELL e PATH do /etc/crontabarquivo e colei-as no sudo crontab -ee o comando foi executado como root sem problemas. Obrigado!
Terrance #
0

Geralmente, as mensagens de erro do Cron são enviadas por email. Você pode verificar se há um email para o root sudo mailou apenas verificando o conteúdo de /var/mail/root, por exemplo sudo less /var/mail/root.


Se as mensagens de email não ajudarem, verifique também /var/log/syslog:

sudo grep CRON /var/log/syslog

Como Alexis Wilke já disse, o cron possui um mecanismo diferente para definir variáveis ​​de ambiente.

Seu script precisa

PATH=/sbin:/bin:/usr/bin

para o crontab. HOMEnão deveria ser necessário. Você deve usar caminhos absolutos em seus scripts, por exemplo, em /bin/datevez de date. Você pode encontrar caminhos adequados para cada comando com which command_name, por exemplo

$ which date
/bin/date
Olli
fonte
Executando o CRON do grep sugerido em / var / log / syslog, obtive o seguinte 11 de fevereiro 14:37:01 Marius-PC CRON [7826]: (root) CMD (root /usr/bin/tunlrupdate.sh) 11 de fevereiro 14: 37:01 Marius-PC CRON [7825]: (root) MAIL (enviou 1 byte de saída; mas obteve o status 0x00ff, # 012) 11 de fevereiro 14:39:01 Marius-PC CRON [7849]: (root) CMD ( [-x / usr / lib / php5 / maxlifetime] && [-d / var / lib / php5] && find / var / lib / php5 / -depth -mindepth 1 -maxdepth 1 -tipo f -cmin + $ (/ usr / lib / php5 / maxlifetime)! -execdir fuser -s {} 2> / dev / null \; -delete) Se adicionar alguma definição para o PATH no cron, isso não afetará meu sistema $ PATH?
Antonio
Essa saída diz que tentou enviar algo por email, mas falhou. Isso significa que você não está recebendo essa mensagem de erro /var/mail/root. Você pode consertar isso ou tentar com #PATH=...
Olli
@Antonio, em alternativa, usar essa versão corrigida
Olli
Obrigado. Sei que não configurei o e-mail do sistema e sabia que isso não ocorreu. Eu já havia modificado o script para usar o caminho absoluto para qualquer função chamada. A última coisa que foi minha pergunta anterior: uma definição PATH no crontab não vai mexer com a variável $ PATH do meu sistema?
Antonio
1
Nesse meio tempo, eu estava ocupado corrigindo um erro no formato da data do script original. Ele estava usando% m (que é para o mês NÃO minuto) em vez de% M ... #
Antonio
0

Você pode adicionar esta linha no seu script. Portanto, depois de verificar os cron logs e confirmar que seu trabalho foi executado, você pode obter o mesmo $ PATH de crontabs.

/bin/echo $PATH > /root/path.txt

E provavelmente a melhor coisa que você pode fazer para diagnosticar problemas nos scripts cron é obter todas as variáveis ​​de ambiente do SO com o comando env no seu script. Então, basta adicionar esta linha ao seu script. Então você pode analisar a saídaallEvnVars.txt

/usr/bin/env > /root/allEvnVars.txt

Outro truque é direcionar a saída do script para algum lugar. Adicionando o /root/log.log. Dessa forma, toda a saída do script será mantida em/root/log.log

07,37 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log

Além disso, você pode agendar o script para executar cada minuto para facilitar os testes e verificações.

*/1 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log
Cassio Seffrin
fonte