Agendando tarefas no Linux – um guia para o bom uso do cron

A tarefa de administração de servidores envolve frequentemente a execução de certas atividades em períodos de tempo prédefinido. Executar estas tarefas manualmente poderia acarretar em desperdício de recursos humanos, por isso todo sistema operacional possui um tipo de agendador de tarefas que permite que tarefas repetitivas sejam executadas sem a intervenção do usuário. No Linux nós temos  o cron como agendador de tarefas e que é bastante flexível. Ele é o alvo deste texto que espero ser útil.

Tarefas agendadas

Existem inúmeras tarefas em um computador que merecem a atenção de um agendador de tarefas para serem executadas periodicamente. Estas vão desde analisadores de logs até antivirus, backup, ferramentas para organização do sistema entre outras.

Estas tarefas em regras gerais precisam ser executadas sem a intervenção do usuário que apenas deixaria por conta do sistema o trabalho ficar “tomando conta do relógio” para verificar quando deverá executar a tarefa desejada.

Cron: O agendador do Linux

No Linux este trabalho de “tomar conta do relógio” é feito pelo cron. O daemon crond verifica a cada minuto se deve ou não executar alguma tarefa prédefinida e caso tenha alguma ele a executará sem que o usuário tenha que intervir de qualquer maneira.

Neste ponto é importante enfatizar esta informação. As ferramentas, utilitários e aplicativos que estarão sob o controle do cron, não devem esperar qualquer interação do usuário pois elas são executadas em background.

Em outras palavras, caso elas necessitem de alguma resposta do usuário ela ficará parada esperando por esta resposta indefinidamente sem nunca terminar a execução pois não rodam em um terminal acessível. Ciente disso, certifique-se que a sua ferramenta nunca espere que o usuário responda com uma tecla, ou clique do mouse.

O Cron trabalha com dois tipos de configuração, ou agendamento de tarefas. A que parte do usuário comum do sistema e a que parte do proprio sistema e que é configurada pelo instalador de algumas  ferramentas ou pelo administrador do sistema.

Agenda do usuário

No diretório /var/spool/cron/crontabs – que só pode ser lido pelo usuário root e por membros do grupo crontab – estão os arquivos de configuração do cron por usuário.

Cada arquivo abaixo deste diretório é nomeado com login do usuário responsável e embora o primeiro impulso seja abri-los em um editor de textos para alterá-los, nunca faça isso ou as coisas poderão não funcionar como se espera.

Para editar as tarefas do seu usuário você deve usar o comando crontab a partir da linha de comandos, conforme abaixo:

crontab -e

Este comando abrirá o editor padrão do seu sistema para que você possa editar as tarefas programadas e então recarregará arquivo. Caso queira listar as tarefas ali registradas sem precisar abrir o editor de textos você pode chamar assim:

crontab -l

Um alerta importante é que o utilitário crontab as vezes se perde dentro de sessões criadas com o comando “su”, então se você tiver que alterar as tarefas de algum usuário que não o seu próprio é fortemente recomendado que você informe ao crontab qual é o usuário a ser tratado.

su -c "crontab -u outrousuario -e"

Adiante veremos como são compostas as linhas de configuração deste arquivo.

Agendas do sistema

A forma mais prática de agendar uma tarefa no Linux é  copiar ou criar um link para seu script, ferramenta, utilitário etc dentro dos diretórios /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly onde serão executadas a cada hora, diariamente, semanalmente ou mensalmente, sem que você tenha muito o que se preocupar.

O horário de execução destes arquivos variam de acordo com a configuração padrão da sua distribuição. Veja que estes diretórios não recebem um arquivo de configuração da tarefa no formato do cron, mas sim a própria ferramenta que deve ser um arquivo binário, ou script em qualquer linguagem e com permissão de execução pelo root.

Este é apenas um meio fácil e não muito flexivel de agendar tarefas, caso precise algo mais personalizado e especifico você deverá usar as agendas do sistema que são registradas de duas maneiras diferentes. No arquivo /etc/crontab ou ainda com um aquivo de configuração ou link simbólico para ele dentro do diretório /etc/cron.d.

A diferença entre ambas as opções é que na primeira nós editamos o arquivo /etc/crontab e incluímos uma linha de configuração para a tarefa que deverá ser executada. Na segunda nós adicionamos um arquivo com a configuração desejada dentro do diretório /etc/cron.d. Na prática embora ambos sejam independentes um do outro, funcionam da mesma forma e apesar disso, o manual do cron sugere que você sempre use o /etc/crontab ao invés de /etc/cron.d, deixando este último para os instaladores de pacotes etc.

Conforme veremos adiante, há uma sutil diferença entre a configuração de uma tarefa por parte do usuário e uma por parte do sistema. Esta diferença trata apenas do nome do usuário que será responsável pela tarefa do sistema.

Configuração de tarefas

Os arquivos de configuração do cron são formados basicamente por dois tipos de linhas. As linhas de atribuição de variáveis de ambiente e linhas de configuração de tarefas.

Por exemplo as duas linhas a seguir configuram as variáveis de ambiente SHELL e PATH:

SHELL=/bin/bash
PATH=/bin:/usr/bin

Enquanto que a linha abaixo configura uma tarefa de backup definida por algum usuário:

0 20 * * * /opt/sysbackup/start-backup

As linhas de configuração de tarefas do usuário, conforme vemos neste último exemplo, possuem 6 campos de configuração que são os seguintes:

minutos hora dia-do-mês mês dia-da-semana comando [ENTER]

No caso daquela configuração temos:

  •  minutos = 0 (poderia ser qualquer valor entre 0 e 59)
  •  hora = 20  (poderia ser qualquer valor entre 0 e 24 – sendo 0 e 24 equivalentes a meia-noite)
  •  dia-do-mês = * (poderia ser qualquer valor entre 1-31)
  •  mês = * (poderia ser qualquer valor entre 1 e 12)
  •  dia-da-semana = * (poderia ser qualquer valor entre 0 e 7, sendo 0 e 7 equivalentes a domingo)
  •  comando = /opt/sysbackup/start-backup (qualquer comando com o path completo)

Para tarefas que serão executadas pelo sistema (/etc/crontab ou /etc/cron.d) existem 7 campos. Sendo o campo adicional – conforme já tinha comentado antes – o login do usuário que executará a tarefa e que deverá vir antes do comando.

minutos hora dia-do-mês mês dia-da-semana usuário comando [ENTER]

É importantissimo salientar aqui que cada linha de configuração deve terminar obrigatoriamente com “\n” (ou para ficar mais claro com um ENTER). Este lembrete se aplica quando escrevemos várias linhas de configuração e descobrimos que a última linha nunca é chamada.

Embora o manual informe este detalhe, é comum que muita gente não se atente a isso simplesmente porque costuma dar ENTER no final das linhas de forma inconsciente e ai no dia que esquece de fazer isso as coisas não funcionam e entram em desespero sem saber porque não funciona se sempre funcionou.

Isso ocorre porque faltou o ENTER no final da última linha, como alguns editores de texto não deixam isso claro eu, particularmente, convencionei que todos os meus arquivos contém um “#-FIM-” na última linha. Isso obriga a ter um ENTER ao final da última linha de configuração que sempre era vítima de não funcionamento e também não prejudica o trabalho já que linhas iniciando com “#” são apenas consideradas como comentários.

Exemplos de agendamento de tarefas

As linhas de configuração de tarefas devem ter os 6 ou 7 campos descritos anteriormente e na prática se parecerão com as linhas de exemplo abaixo.

0 8 10 6 * comando

Isto executaria o “comando” as 8:00 do dia 10/Junho em qualquer dia da semana (observe que ignoramos o dia da semana).

O “*” quando usado desta forma indica que este campo deve ser ignorado.

0 8 * * 7 comando

Isto executaria o “comando” as 8:00 do domingo (não importa qual seja o dia do mês e nem qual seja o mês, o valor 7 no quinto campo indica o domingo)

0 8 10 * * comando

Isto executaria o “comando” as 8:00 do dia 10 (não importa o mês e nem o dia da semana)

0 8 * * * comando

Isto executaria o “comando” as 8:00 (todos os dias de todos os meses em qualquer dia da semana)

* * * * * comando

Isto executaria o “comando” todos os minutos, ou seja, a cada minuto de cada hora em todos os dias do mês e da semana todos os meses.

Simplificando as linhas de configuração

Os campos de data/hora possuem alguns facilitadores que simplificam a sintaxe das linhas de configuração de tarefas.

Por exemplo se desejamos que um comando seja executado a cada 2 horas fariamos de uma destas duas formas abaixo:

* 0,2,4,6,8,10,12,14,16,18,20,22 * * * comando

ou, de forma simplificada:

* */2 * * * comando

Veja que o “*/2” simplificou a linha e significa a mesma coisa (um intervalo de 2h em 2h). Para executarmos uma determinada tarefa apenas durante o expediente de trabalho poderiamos agir assim:

0 8-17 * * 1-5 comando

Isso executaria o “comando” as 8:00, 9:00, 10:00 etc até as 17:00 de segunda-feira até sexta-feira (1-5). Veja que o cron considera o 0 e o 7 como domingo, 1 corresponde a segunda e 6 corresponde a sábado e ainda que o símbolo “-” indica um intervalo contínuo de dias, horas, minutos etc.

Lembre-se então que, como visto nestes exemplos, os valores podem ser separados por “,” ou por “-” e ainda tem o facilitador /2, /3 etc que permitem uma enorme flexibilidade no ajuste de horários.

Veja um exemplo complexo com todos eles abaixo:

0,30 8-17/3 * * 1-5 comando

“Traduzindo” esta linha, o “comando” será executado duas vezes a cada hora (com intervalos de 30m entre eles), em horário comercial (de 8h as 17h) a cada 3 horas, durante os dias úteis da semana.

Para entender bastaria distrinchar cada parte da configuração assim:

  • 0,30 no campo de minutos indicam que o evento ocorrerá de 30m em 30m, sempre quando os minutos forem 00 ou 30;
  • 8-17 equivale ao intervalo de 8h até 17h. Como colocamos um /3 então temos que 8-17/3 equivale a intervalos de três horas iniciando as 8h e terminando as 17h. Ou seja, 8h, 11h, 14h, 17h. Juntando ambas as informações de horário teremos que o “comando” seria executado as 8:00, 8:30, 11:00, 11:30, 14:00, 14:30, 17:00
  • Por último nós ainda informamos que o dia da semana deverá estar entre 1 e 5, ou seja, de segunda a sexta-feira.

Claro que dificilmente você terá que se deparar com uma configuração complexa assim, mas se precisar sabe que é possível faze-la.

Voltando a simplicidade, havendo necessidade de executar um comando de hora em hora poderiamos considerar as seguintes alternativas:

0 * * * * comando

ou então:

@hourly comando

O facilitador “@hourly” corresponde a configuração “0 * * * *” e assim como ele nós temos alguns outros tão úteis quanto. A saber:

  • @reboot  – No boot do sistema
  • @yearly – Equivale a “0 0 1 1 *”
  • @annually – O mesmo que @yearly
  • @monthly – Equivale a “0 0 1 * *”
  • @weekly – Equivale a “0 0 * * 0”
  • @daily – Equivale a “0 0 * * *”
  • @midnight – O mesmo que @daily
  • @hourly – Equivale a “0 * * * *”

Considerações finais

Isto é o básico que se precisa saber para que uma tarefa possa ser agendada com sucesso entretanto existem ainda algumas peculiaridades que vale a pena registrar para melhorar a experiência do usuário novato no assunto e são estas que descrevo abaixo.

Os nomes das tarefas

O nome das tarefas (arquivos) dentro de /etc/cron.d e /etc/cron.{daily,weekly,monthly} devem seguir a uma convenção já definida nos primórdios da criação dos sistemas POSIX, ou do contrário elas serão desconsideradas mesmo que o seu conteúdo esteja corretamente definido.

Isso significa que arquivos cujo o nome tenha algo além de letras maiúsculas (A-Z), letras minúsculas (a-z), algarísmos (0-9), underscore (_) e hifen (-) não serão executados, mesmo que estejam corretos.

Só a título de advertência, veja que se você tentar iniciar um script chamado “backup.sh”, ficará só na tentativa, pois “.” não consta na lista de caracteres permitidos e então o seu arquivo será silenciosamente ignorado.

A solução é remover o “.sh” ou então configurar o cron em modo LSB (Linux Standard Base), o que no caso do Ubuntu e do Debian é feito descomentando a linha LSBNAMES=’-l’ dentro do arquivo /etc/default/cron e reiniciando o processo do cron.

Agendando tarefas pelo modo gráfico

Embora o Cron seja uma ferramenta para linha de comandos, não é preciso abrir um terminal para agendar tarefas do usuário. Usuários do Gnome podem contar com o gnome-schedule que é uma ferramenta gráfica para este tipo de atividades. Da mesma forma usuários do KDE podem contar com o kde-config-cron (anteriormente empacotada como Kcron) que tem a mesma função.

Agendando tarefas com interface gráfica

Já disse anteriormente que tarefas que requeiram interação do usuário não devem ser agendadas pois os comandos não são executados em um terminal acessível, entretanto, quando trata-se de tarefas com interface gráfica é possível fazer uma gambiarra que resolve parcialmente este problema.

Considerando que meu usuário esteja logado no sistema em uma sessão gráfica (gnome, KDE etc) bastaria saber qual é esta seção e então forçar a saída para ela. Para descobrir qual é a seção gráfica do seu usuário basta que pela linha de comandos você digite:

echo $DISPLAY

A saída deverá ser algo como:

echo $DISPLAY
:0

Já sabendo esta informação, na frente do seu comando com interface gráfica basta colocar a instrução a seguir:

DISPLAY=:0

Veja entretanto que este display é exclusivo deste usuário então não adianta incluir a tarefa como outro usuário, pois ela não funcionará a não ser fazendo outra gambiarra com o xhost (assunto para outro longo texto).

Desta forma, para que todos os dias as 12h o comando zenity mostre uma mensagem informando que está na hora do almoço. bastaria fazer uma configuração assim:

0 12 * * * DISPLAY=:0 zenity –info –text “Hora do almoço”

Arquivando as saídas dos comandos

É comum que alguns comandos produzam informações de saída que seriam lidas no terminal, caso fossem chamados pela linha de comandos. Quando estas informações são úteis e o seu programa não as guarda em local algum para consulta futura, você as perde a não ser que use o bom e velho redirecionamento do shell. O que é feito com um “>>nome-do-arquivo”. Por exemplo:

@daily /opt/backup/startbackup >>${HOME}/backup.log 2>&1

Neste exemplo a saída do meu programa de backup adicionará as suas mensagens ao arquivo backup.log dentro do meu diretório home. O “2>&1” é um redirecionamento especial que informa que a saída de erros deve ser despejada no console padrão.

Isso permite que até mesmo estas mensagens de erro que de outra maneira seriam perdidas, sejam registradas no meu backup.log, também. Obviamente, se as mensagens forem irrelevantes você poderá descartá-las redirecionando-as para /dev/null. Por exemplo:

@daily /opt/backup/startbackup >/dev/null 2>&1

Tarefas do sistema

Por fim, não custa mais do que alguns bytes relembrar que todos os exemplo dados referem-se a configuração do agendador de tarefas para o usuário. Aquela feita via “crontab -e”, para que estas configurações funcionem pelo lado do sistema é preciso que se informe o nome do usuário que executará a tarefa antes do nome da ferramenta. Por exemplo:

0,30 8-17/3 * * 1-5 usuario comando
@hourly usuario comando

Referências

  • Cron manual page for system administration. Disponível via comando “man 8 cron”
  • Run-parts manual page for system administration. Disponível via comando “man 8 run-parts”
  • Crontab manual page for executable programs. Disponível via comando “man 1 crontab”
  • Crontab manual page for file formats. Disponível via comando “man 5 crontab”

 

Um comentário em “Agendando tarefas no Linux – um guia para o bom uso do cron”

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.