107.2 Agendamento de tarefas
Vamos ver as possibilidades para fazermos o agendamento de tarefas no Linux, seja usando o Cron, AT ou até mesmo o SystemD.
Cron
O crontab é utilizado para agendar tarefas que serão executados periodicamente no sistema, ao contrário do comando at, que só vai executar comandos pontualmente.
Há dois tipos de crontab, são eles: a de usuários e a do sistema. Ambas são arquivos que contem tabelas com informação de quando o comando especificado deve ser executado, sendo que cada linha corresponde a um único agendamento. O crontab é gerenciado pelo daemon crond, que a cada um minuto verifica se há algum agendamento que deve ser executado e, se houver, executa-o.
O crontab do sistema fica localizado no arquivo /etc/crontab e já possui agendamentos para realizar as tarefas que se encontram
nos diretórios /etc/cron.{hourly,daily,weekly,monthly,d}.
$ ls -lhd /etc/cron.{hourly,daily,weekly,monthly,d}
drwxr-xr-x 2 root root 4.0K Jun 7 11:56 /etc/cron.d
drwxr-xr-x 2 root root 4.0K Apr 2 12:46 /etc/cron.daily
drwxr-xr-x 2 root root 4.0K Apr 2 12:32 /etc/cron.hourly
drwxr-xr-x 2 root root 4.0K Apr 2 12:32 /etc/cron.monthly
drwxr-xr-x 2 root root 4.0K Apr 2 12:44 /etc/cron.weekly
# Dentro de cada uma dessas pastas existem arquivos de Cron para serem executados de tempos em tempos.
# Se você ver um comando 'run-parts' no cron do sistema, esse comando vai executar todos os scripts dentro do diretório.

Vamos ver como funcionam cada opção do Crontab.
| Opção | Descrição |
|---|---|
| Minuto | Os minutos variam de 0-59. |
| Hora | As horas variam de 0-23. |
| Dia | Os dias variam de 1-31. |
| Mês | Os meses variam de 1-12. |
| Dia da semana | Os dias da semana variam de 0-7, sendo 0 e 7 domingo. |
| Usuário | Um usuário válido no sistema no qual o cron será executado. |
| Comando | O comando que será executado, pode ser um script também. |
| Opções | Abaixo todas as opção são válidas desde minuto até dia da semana |
| * | Representa todas as possibilidades, qualquer valor. |
| , | Separa valores por vírgula. |
| - | Identifica um range de valores. |
| / | Especifica “pulos” de valores, por exemplo: se no campo hora utilizarmos "*/4" o comando será executado as 0,4,8,12,16,20. |
Vamos ver alguns exemplo para assimilar melhor isso.
# Todo dia, no mês de Agosto, as 00:05:
5 0 * 8 * ...
# Todo dia 1 de qualquer mês, as 14:15:
15 14 1 * * ...
# Toda Segunda até Sexta, as 22:00:
0 22 * * 1-5
# Roda a cada 2 horas e 23 minutos, sempre entre as 00:00 e 20:00 :
23 0-20/2 * * *
# Essa opção acima iria rodar todo dia as:
# as 04:23:00
# as 06:23:00
# as 08:23:00
# as 10:23:00
# as 12:23:00
# as 14:23:00
## Parte do período foi omitido.
# Todo domingo as 4:05 :
5 4 * * sun
# A cada 2 meses, todo dia 1° as 00:00 e 12:00 :
0 0,12 1 */2 *
# As 00:00 de todo domingo:
@weekly
Você não deve usar script que exija interação com o usuário.
As opções abaixo substituem as 5 opções do Cron (minuto, hora, dia do mês, mês e dia da semana).
| Opção | Descrição |
|---|---|
| @reboot | Especifica execução quando a máquina for reiniciada. |
| @yearly ou @annually | Especificam execução uma vez ao ano, equivale a 0 0 1 1 *. Roda as 00:00, todo dia 1° do mês 1 (Janeiro). |
| @monthly | Especifica execução somente uma vez ao mês, equivale a 0 0 1 * *. Roda as 00:00, todo dia 1°. |
| @weekly | Especifica execução somente uma vez na semana, equivale a 0 0 * * 0. Roda as 00:00 de todo domingo. |
| @daily ou @midnight | Especifica execução uma vez ao dia, equivale a 0 0 * * *. Roda as 00:00 de todo dia. |
| @hourly | Especifica execução somente uma vez a cada hora, equivale a 0 * * *. Roda toda hora com zero minutos (13:00, 14:00, 15:00...). |
Ativando os logs do Crontab
Para ativar os logs do crontab precisamos editar o arquivo /etc/rsyslog.d/50-default.conf do rsyslog, modifique a linha abaixo, removendo o # do começo da linha:
##### Antes:
#cron.* /var/log/cron.log
##### Depois de editar:
cron.* /var/log/cron.log
Se preferir, pode criar esse arquivo, mas o sistema vai criar para você:
# Crie o arquivo:
sudo touch /var/log/cron.log
# Aplicando as permissões do arquivo:
sudo chmod 640 /var/log/cron.log
# Aplicando Dono e Grupo dono corretos:
sudo chown syslog.adm /var/log/cron.log
Editando o Crontab
Segue algumas opções para o comando crontab:
| Opção | Descrição |
|---|---|
| -r | Remove o arquivo crontab do usuário logado e adiciona um vazio (faz um reset). |
| -e | Edita o arquivo do crontab do usuário logado. |
| -l (L minusculo) | Lista os agendamentos do cron do usuário logado. |
| -u (username) | Muda o usuário, precisa ser root. |
O arquivo do Cron para o sistema fica em /etc/crontab.
Já os Cron dos usuários ficam em /var/spool/cron/crontabs/:
# Exibindo os crontab ativos dos usuários:
sudo ls /var/spool/cron/crontabs/
vagrant
# No caso, só possui o crontab do usuário vagrant.
cront.{allow,deny}
Existe 2 arquivos de controle do Cron, ele ficam em /etc/cront.{allow,deny}, o arquivo cron.allow vai permitir que o usuário que estiverem dentro dele use o Cron, caso algum usuário esteja fora desse arquivo, mesmo que você não esteja negando ele, ele não poderá usar, só é permitido o uso quem estiver dentro desse arquivo, e os usuários que estiverem dentro de cront.deny não poderão usar.
O .allow tem prioridade sobre o .deny, então por mais que negue um usuário e ele esteja no allow, ele poderá executar. Vale ressaltar que usar os dois arquivos em conjunto não faz muito sentido, já que o .allow nega o uso de quem estiver fora dele, sendo assim, pode usar um ou outro.
No Debian, e distribuições baseadas como o Ubuntu, se ambos arquivos não existem, o uso dos recursos da cron é liberado para todos os usuários. No entanto, em sistemas baseados em RedHat, como o CentOS, na inexistência dos arquivos, o uso é bloqueado a todos os usuários, exceto para o usuário root.
Anacron
O conceito de funcionamento dos agendamentos de tarefas via cron pode ser aplicado a um outro agendador de tarefas chamado anacron. Este agendador possui a função de executar tarefas que por algum motivo não foram executadas, geralmente pelo fato da máquina estar desligada no momento agendado para execução.
Seu arquivo fica em /etc/anacrontab.
AT
O comando at pode agendar tarefas de forma semelhante ao cron, mas ele só roda uma vez. O at permite o controle dos usuários que podem agendar comandos através dos arquivos /etc/at.allow e /etc/at.deny.
Estes arquivos são organizados no formato de um usuário por linha. Durante o agendamento é verificado primeiro o arquivo /etc/at.allow (listando quem pode executar o comando) e depois /etc/at.deny.
Caso eles não existam, o agendamento de comando é permitido a todos os usuários.
Utilize nos comandos do script e no agendador, sempre o (path) caminho completo do aplicativo a ser executado, exemplo para o comando
tar, use/bin/tar, também na linha de comando que inserir no cron use o caminho completo para o script, por exemplo, executar um script que está em/home/fulano, use a linha:/home/fulano/nome-do-scripte não somentenome-do-script.Muito cuidado com scripts, o comodismo pode cair no esquecimento e não atualizar o script de backup quando incluir novos serviços, diretórios ou usuários, monitore constantemente, teste e avalie o que está sendo feito.
Uma forma de agendar tarefas com at é da seguinte forma:
### Para agendar uma tarefa para daqui 3 horas, digite:
$ at now +3hour
# Depois disso você vai cair no shell do AT, pode ver porque o prompt vai mudar, provavelmente para 'at> '.
# Agora você deve digitar o que precisar ser agendado, por exemplo: Você pode agendar um bkp, rodar um script, voce deve colocar o caminho completo do script aqui.
# Para finalizar você roda Ctrl+d, e o job será criado.
# Outra forma seria:
$ at 15:16
# Ou até mesmo:
$ at 10:00am 14052021
| Comando | Descrição |
|---|---|
| at | Comando at. |
| atq | Lista os jobs criados pelo comando at, igual at -l. |
SystemD Timer
É um recurso do SystemD para fazer o agendamento de tarefas.
Para lista os agendamentos ativo rode o comando sudo systemctl list-timers, veja abaixo:

A UNIT sempre terá o mesmo nome do SERVICE, você sempre terá um .timer e um .services. Você consegue notar para quando é o agendamento e quanto tempo falta para a execução dele.
Vamos ver a sintaxe de um .timer padrão:
$ cat /lib/systemd/system/apt-daily.timer
[Unit]
Description=Daily apt download activities
[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
Persistent=true
[Install]
WantedBy=timers.target
# Olhe em OnCalendar, o 1° asterisco é o Ano, o 2° é o Mês e o 3° é o Dia. Ele vai toda todo ano, todo mês e todo dia as 6:00 e as 18:00.
### Vamos dar uma olhada nuns exemplos:
# Das 6 até as 12h:
*-*-* 6..12:00
# Nas Segundas-feiras, as 7h:
Mon *-*-* 7:00
# Das Segundas até Sexta, as 10h:
Mon..Fri *-*-* 10:00
# Terça e quinta, as 13h:
Tue..Thu *-*-* 13:00
# Se quiser pode colocar ':' deopis dos minutos para especificar os segundos.
Em sistemas Redhat, você deve substituir o
Mon..FriporMon-Fri.
Vamos ver algumas opções do .timer:
| Opções | Descrição |
|---|---|
| OnCalendar | Especificamos quando vai todar o agendamento. |
| RandomizedDelaySec | Significa que o agendamento não vai rodar no momento especificado certinho, ele vai randomizar o agendamento com um delay para não rodar muita coisa junta.RandomizedDelaySec=12h significa que ele vai rodar com um delay de até 12 horas. |
| Persistent | Assim que o servicço é executado ele é gravado em disco. Muito bom para executar agendamentos perdidos por algum motivo. Só pode ser usado se OnCalendar estiver em uso. |
| OnBootSec | Define um cronômetro relativo a quando a máquina foi inicializada. Ex.: OnBootSec=15min. |
| OnUnitActiveSec | Diz para rodar a cada tempo, por ex.: OnUnitActiveSec=1d, a cada 24 horas depois que o sistema fica ativo . |
Para mais detalhes, olhe aqui, similar a man systemd.timer, Além disso, veja também man systemd.time.
Vamos criar um exemplo de agendamento:
# Vamos começar criando o '.service':
sudo vim /lib/systemd/system/exemplo.service
### Start example service ###
[Unit]
Description=Exemplo systemd-timer
ConditionACPower=true
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'date >> /tmp/teste_systemd-time.txt'
### End example service ###
##############################################################
# Agora vamos criar o '.timer':
sudo vim /lib/systemd/system/exemplo.timer
### Start example timer ###
[Unit]
Description=Teste systemd timer
[Timer]
OnCalendar=*-*-* 21:25:00
AccuracySec=1us
[Install]
WantedBy=timers.target
### End example timer ###
Agora vamos iniciar o serviço:
# Recarregue o damon do systemD:
sudo systemctl daemon-reload
# Inicie o timer:
sudo systemctl start exemplo.timer
# Verifique o status:
sudo systemctl status exemplo
SystemD Run
Similar ao at, mas roda sob o SystemD.
# Rodar um comando daqui 1 minuto:
date && sudo systemd-run --on-active=1m --timer-property=AccuracySec=1us /usr/bin/echo $(date) >> /tmp/novo
# Se for rodar sem root, acrescente a opção '--no-ask-password'.