Skip to main content

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.

crontab


Vamos ver como funcionam cada opção do Crontab.

OpçãoDescrição
MinutoOs minutos variam de 0-59.
HoraAs horas variam de 0-23.
DiaOs dias variam de 1-31.
MêsOs meses variam de 1-12.
Dia da semanaOs dias da semana variam de 0-7, sendo 0 e 7 domingo.
UsuárioUm usuário válido no sistema no qual o cron será executado.
ComandoO comando que será executado, pode ser um script também.
OpçõesAbaixo 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çãoDescrição
@rebootEspecifica execução quando a máquina for reiniciada.
@yearly ou @annuallyEspecificam execução uma vez ao ano, equivale a
0 0 1 1 *. Roda as 00:00, todo dia 1° do mês 1 (Janeiro).
@monthlyEspecifica execução somente uma vez ao mês, equivale a 0 0 1 * *. Roda as 00:00, todo dia 1°.
@weeklyEspecifica execução somente uma vez na semana, equivale a 0 0 * * 0. Roda as 00:00 de todo domingo.
@daily ou @midnightEspecifica execução uma vez ao dia, equivale a 0 0 * * *. Roda as 00:00 de todo dia.
@hourlyEspecifica 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çãoDescrição
-rRemove o arquivo crontab do usuário logado e adiciona um vazio (faz um reset).
-eEdita 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-script e não somente nome-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

ComandoDescrição
atComando at.
atqLista 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:

example_list-timers

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..Fri por Mon-Fri.


Vamos ver algumas opções do .timer:

OpçõesDescrição
OnCalendarEspecificamos quando vai todar o agendamento.
RandomizedDelaySecSignifica 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.
PersistentAssim 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.
OnBootSecDefine um cronômetro relativo a quando a máquina foi inicializada. Ex.: OnBootSec=15min.
OnUnitActiveSecDiz 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'.