DevOps & CI/CD

Boas Práticas de Cron, at e Automação de Tarefas Agendadas no Linux para Times Ágeis

16 min de leitura

Boas Práticas de Cron, at e Automação de Tarefas Agendadas no Linux para Times Ágeis

Entendendo Agendamento de Tarefas no Linux O agendamento de tarefas é um dos pilares da automação em sistemas Linux. Diferentemente de sistemas operacionais com interface gráfica que permitem agendar tarefas facilmente, no Linux você controla esse mecanismo através de ferramentas de linha de comando poderosas e flexíveis. A necessidade de automatizar tarefas surge em qualquer ambiente: backups periódicos, limpeza de logs, sincronização de dados, scripts de monitoramento. Sem agendamento, você teria que executar essas ações manualmente ou manter processos sempre rodando, desperdiçando recursos. Existem dois principais mecanismos nativos para agendamento no Linux: cron e at. Ambos servem propósitos diferentes. Cron é ideal para tarefas recorrentes (diárias, horárias, semanais), enquanto at é melhor para executar uma tarefa uma única vez em um momento específico. Neste artigo, exploraremos ambos em profundidade, desde conceitos fundamentais até casos de uso práticos. Cron: Automação Recorrente O que é Cron e Como Funciona Cron é um daemon (serviço de fundo) que executa comandos ou scripts em

<h2>Entendendo Agendamento de Tarefas no Linux</h2>

<p>O agendamento de tarefas é um dos pilares da automação em sistemas Linux. Diferentemente de sistemas operacionais com interface gráfica que permitem agendar tarefas facilmente, no Linux você controla esse mecanismo através de ferramentas de linha de comando poderosas e flexíveis. A necessidade de automatizar tarefas surge em qualquer ambiente: backups periódicos, limpeza de logs, sincronização de dados, scripts de monitoramento. Sem agendamento, você teria que executar essas ações manualmente ou manter processos sempre rodando, desperdiçando recursos.</p>

<p>Existem dois principais mecanismos nativos para agendamento no Linux: <strong>cron</strong> e <strong>at</strong>. Ambos servem propósitos diferentes. Cron é ideal para tarefas recorrentes (diárias, horárias, semanais), enquanto at é melhor para executar uma tarefa uma única vez em um momento específico. Neste artigo, exploraremos ambos em profundidade, desde conceitos fundamentais até casos de uso práticos.</p>

<h2>Cron: Automação Recorrente</h2>

<h3>O que é Cron e Como Funciona</h3>

<p>Cron é um daemon (serviço de fundo) que executa comandos ou scripts em intervalos regulares pré-definidos. Ele está disponível em praticamente todos os sistemas Unix-like (Linux, macOS, BSD). O cron lê um arquivo de configuração chamado <strong>crontab</strong> (tabela de cron) de cada usuário e verifica a cada minuto se existe alguma tarefa agendada para ser executada naquele momento.</p>

<p>O arquivo crontab não é editado diretamente no sistema de arquivos. Em vez disso, você usa o comando <code>crontab -e</code>, que abre um editor de texto temporário. Quando você salva e fecha o editor, cron automaticamente valida a sintaxe e armazena o arquivo em um local seguro (geralmente <code>/var/spool/cron/crontabs/</code> ou <code>/var/spool/cron/</code>).</p>

<h3>Sintaxe e Formato do Crontab</h3>

<p>A sintaxe do crontab segue um padrão específico com cinco campos, seguidos do comando a executar:</p>

<pre><code>┌───────────── minuto (0 - 59)

│ ┌───────────── hora (0 - 23)

│ │ ┌───────────── dia do mês (1 - 31)

│ │ │ ┌───────────── mês (1 - 12)

│ │ │ │ ┌───────────── dia da semana (0 - 7, onde 0 e 7 representam domingo)

│ │ │ │ │

│ │ │ │ │

  • comando_a_executar</code></pre>

<p>Cada campo aceita números, intervalos (com hífen <code>-</code>), listas (com vírgula <code>,</code>), ou o asterisco <code>*</code> (que significa &quot;qualquer valor&quot;). Também existe o operador <code>/</code> para definir incrementos. Vamos a alguns exemplos práticos:</p>

<pre><code class="language-bash"># Executar todo dia às 2 da manhã

0 2 * /usr/local/bin/backup.sh

A cada 15 minutos, toda hora

/15 * /usr/local/bin/check_status.sh

De segunda a sexta às 9 da manhã

0 9 1-5 /usr/local/bin/weekly_report.sh

No primeiro dia de cada mês às 00:00

0 0 1 /usr/local/bin/monthly_cleanup.sh

A cada 6 horas

0 /6 /usr/local/bin/sync_data.sh

Toda segunda às 18:30

30 18 1 /usr/local/bin/deploy_staging.sh</code></pre>

<h3>Criando e Gerenciando Crontabs</h3>

<p>Para editar seu crontab pessoal, execute:</p>

<pre><code class="language-bash">crontab -e</code></pre>

<p>Isso abrirá o editor padrão do seu sistema (vi, nano, etc.). Adicione suas tarefas, salve e saia. Para listar suas tarefas agendadas:</p>

<pre><code class="language-bash">crontab -l</code></pre>

<p>Para remover completamente seu crontab:</p>

<pre><code class="language-bash">crontab -r</code></pre>

<p>Se você é administrador e precisa gerenciar o crontab de outro usuário:</p>

<pre><code class="language-bash">sudo crontab -u nomedousuario -e

sudo crontab -u nomedousuario -l</code></pre>

<h3>Exemplo Prático: Script de Backup Agendado</h3>

<p>Vamos criar um script de backup real que será executado diariamente. Primeiro, crie o script:</p>

<pre><code class="language-bash">#!/bin/bash

/usr/local/bin/backup_home.sh

BACKUP_DIR=&quot;/backups/home&quot;

SOURCE_DIR=&quot;/home/usuario&quot;

DATE=$(date +%Y%m%d_%H%M%S)

BACKUP_FILE=&quot;$BACKUP_DIR/backup_$DATE.tar.gz&quot;

Criar diretório se não existir

mkdir -p &quot;$BACKUP_DIR&quot;

Executar backup com compressão

tar -czf &quot;$BACKUP_FILE&quot; &quot;$SOURCE_DIR&quot; 2&gt;&amp;1 &gt;&gt; /var/log/backup.log

Remover backups mais antigos que 30 dias

find &quot;$BACKUP_DIR&quot; -type f -name &quot;backup_*.tar.gz&quot; -mtime +30 -delete

echo &quot;[$(date &#039;+%Y-%m-%d %H:%M:%S&#039;)] Backup concluído: $BACKUP_FILE&quot; &gt;&gt; /var/log/backup.log</code></pre>

<p>Torne o script executável:</p>

<pre><code class="language-bash">sudo chmod +x /usr/local/bin/backup_home.sh</code></pre>

<p>Agora, adicione ao crontab para executar diariamente às 3 da manhã:</p>

<pre><code class="language-bash">sudo crontab -e</code></pre>

<p>Adicione esta linha:</p>

<pre><code>0 3 * /usr/local/bin/backup_home.sh</code></pre>

<h3>Trabalhando com Variáveis e Saída</h3>

<p>Dentro do crontab, você pode definir variáveis de ambiente que serão usadas por seus comandos. Isso é útil para definir o shell, PATH, e outras configurações:</p>

<pre><code class="language-bash">SHELL=/bin/bash

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

MAILTO=admin@empresa.com

HOME=/root

Executar script Python com saída redirecionada

0 1 * /usr/bin/python3 /opt/scripts/generate_report.py &gt;&gt; /var/log/report.log 2&gt;&amp;1

Executar e enviar saída por email

0 6 * /usr/local/bin/system_health_check.sh 2&gt;&amp;1 | mail -s &quot;Relatório Diário&quot; admin@empresa.com</code></pre>

<p>A variável <code>MAILTO</code> é especialmente útil: qualquer saída do comando (stdout e stderr) será enviada para esse endereço de email.</p>

<h2>At: Execução Única em Tempo Específico</h2>

<h3>Diferenças Entre At e Cron</h3>

<p>Enquanto cron é para tarefas recorrentes, <code>at</code> é para executar uma tarefa <strong>uma única vez</strong> em um momento específico no futuro. Você especifica a data e hora exatas, e o at garante que o comando seja executado naquele momento. Isso é perfeito para manutenções programadas, testes únicos, ou tarefas que não precisam ser repetidas.</p>

<p>O daemon atd gerencia as tarefas agendadas com at. Certifique-se de que está rodando:</p>

<pre><code class="language-bash">sudo systemctl status atd

sudo systemctl start atd

sudo systemctl enable atd # Para iniciar automaticamente</code></pre>

<h3>Usando o Comando At</h3>

<p>A sintaxe básica do at é simples. Você especifica o tempo de execução seguido do comando:</p>

<pre><code class="language-bash">at [hora] [data]</code></pre>

<p>Vamos aos exemplos práticos:</p>

<pre><code class="language-bash"># Executar amanhã às 14:00

echo &quot;cd /var/www &amp;&amp; ./deploy.sh&quot; | at 14:00 tomorrow

Executar em uma data específica

echo &quot;mysqldump -u root -p12345 database &gt; /backups/db_backup.sql&quot; | at 10:30 2024-12-25

Executar daqui a 2 horas

echo &quot;/usr/local/bin/system_cleanup.sh&quot; | at now + 2 hours

Executar daqui a 30 minutos

echo &quot;systemctl restart nginx&quot; | at now + 30 minutes

Executar em 3 dias

echo &quot;/home/usuario/importante.sh&quot; | at 09:00 + 3 days</code></pre>

<p>Para agendar usando um script completo, você pode fazer:</p>

<pre><code class="language-bash">at 22:00 today &lt;&lt; &#039;EOF&#039;

#!/bin/bash

DATE=$(date +%Y%m%d)

mysqldump -u root -psenha database &gt; /backups/db_$DATE.sql

gzip /backups/db_$DATE.sql

EOF</code></pre>

<h3>Listando e Removendo Tarefas At</h3>

<p>Para listar todas as suas tarefas agendadas:</p>

<pre><code class="language-bash">atq</code></pre>

<p>Este comando mostra um número de ID para cada tarefa, a data/hora e outras informações.</p>

<p>Para visualizar o conteúdo de uma tarefa específica:</p>

<pre><code class="language-bash">at -c [ID]</code></pre>

<p>Para remover uma tarefa:</p>

<pre><code class="language-bash">atrm [ID]</code></pre>

<p>Exemplo completo:</p>

<pre><code class="language-bash"># Agendar uma tarefa

at 18:30 today

tar -czf /backups/quick_backup.tar.gz /home/dados

Ctrl+D # Pressione Ctrl+D para finalizar

Listar

atq

Saída: 1 Wed Dec 20 18:30:00 2024 a nomedousuario

Remover a tarefa

atrm 1</code></pre>

<h3>Exemplo Prático: Manutenção Programada com At</h3>

<p>Imagine que você precisa fazer uma manutenção no servidor em uma data específica. Crie um script:</p>

<pre><code class="language-bash">#!/bin/bash

/usr/local/bin/maintenance.sh

LOG_FILE=&quot;/var/log/maintenance.log&quot;

echo &quot;[$(date)] Iniciando manutenção...&quot; &gt;&gt; &quot;$LOG_FILE&quot;

Parar serviços

systemctl stop nginx &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

systemctl stop php-fpm &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

Fazer backup do banco de dados

mysqldump -u root -psenha todosbancos &gt; /backups/pre_maintenance_$(date +%s).sql

Executar atualizações

apt-get update &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

apt-get upgrade -y &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

Reiniciar serviços

systemctl start php-fpm &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

systemctl start nginx &gt;&gt; &quot;$LOG_FILE&quot; 2&gt;&amp;1

echo &quot;[$(date)] Manutenção concluída com sucesso&quot; &gt;&gt; &quot;$LOG_FILE&quot;</code></pre>

<p>Agora, agende para executar em 3 dias às 22:00:</p>

<pre><code class="language-bash">echo &quot;/usr/local/bin/maintenance.sh&quot; | at 22:00 + 3 days</code></pre>

<p>Verifique a agenda:</p>

<pre><code class="language-bash">atq

at -c 1 # Visualiza a tarefa</code></pre>

<h2>Monitoramento, Logs e Troubleshooting</h2>

<h3>Verificando Logs do Cron</h3>

<p>O cron mantém registros de tudo que executa. Para visualizar esses logs no Ubuntu/Debian:</p>

<pre><code class="language-bash">grep CRON /var/log/syslog</code></pre>

<p>Em CentOS/RHEL:</p>

<pre><code class="language-bash">tail -f /var/log/cron</code></pre>

<p>Para ver especificamente se seu script foi executado:</p>

<pre><code class="language-bash">grep &quot;backup_home.sh&quot; /var/log/syslog</code></pre>

<h3>Capturando e Monitorando Saída</h3>

<p>Um erro comum é não capturar a saída dos comandos cron. Se seu script funciona manualmente mas não funciona agendado, geralmente é por falta de path absoluto ou variáveis de ambiente. Sempre redirecione saída para um arquivo de log:</p>

<pre><code class="language-bash"># Bom - captura stdout e stderr

0 2 * /usr/local/bin/backup.sh &gt;&gt; /var/log/backup.log 2&gt;&amp;1

Melhor - com timestamp

0 2 * /usr/local/bin/backup.sh &gt;&gt; /var/log/backup.log 2&gt;&amp;1 ; echo &quot;[$(date)] Backup executado&quot; &gt;&gt; /var/log/backup.log</code></pre>

<h3>Problemas Comuns e Soluções</h3>

<p><strong>Problema: Script não executa no cron, mas executa manualmente</strong></p>

<p>Solução: Use paths absolutos para tudo. O cron não herda o PATH do seu usuário completamente.</p>

<pre><code class="language-bash"># Errado

0 2 * backup.sh

Correto

0 2 * /usr/local/bin/backup.sh</code></pre>

<p><strong>Problema: Cron executa mas variáveis de ambiente não estão disponíveis</strong></p>

<p>Solução: Defina as variáveis no crontab ou carregue um arquivo de configuração no script:</p>

<pre><code class="language-bash"># No seu script, carregue variáveis

#!/bin/bash

source /etc/environment

source /home/usuario/.bashrc

Ou no crontab

JAVA_HOME=/usr/lib/jvm/java-11

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

0 2 * /usr/local/bin/java_app.sh</code></pre>

<p><strong>Problema: At não está funcionando</strong></p>

<p>Solução: Verifique se o daemon está rodando e se você tem permissão:</p>

<pre><code class="language-bash">sudo systemctl status atd

Se não estiver rodando:

sudo systemctl start atd

sudo systemctl enable atd

Verifique se você está na lista de permissão

cat /etc/at.allow # Se existir, você deve estar aqui

cat /etc/at.deny # Se você está aqui, será negado</code></pre>

<h3>Boas Práticas de Segurança</h3>

<p>Nunca coloque senhas diretamente nos scripts ou crontabs. Use arquivos de configuração protegidos:</p>

<pre><code class="language-bash">#!/bin/bash

/usr/local/bin/secure_backup.sh

Carrega credenciais de arquivo protegido

source /etc/myapp.conf # chmod 600

Usa a variável

mysqldump -u root -p&quot;$DB_PASSWORD&quot; mydatabase &gt; /backups/backup.sql</code></pre>

<p>Arquivo de configuração:</p>

<pre><code class="language-bash"># /etc/myapp.conf

chmod 600 /etc/myapp.conf

DB_PASSWORD=&quot;sua_senha_aqui&quot;

DB_USER=&quot;root&quot;

DB_NAME=&quot;mydatabase&quot;</code></pre>

<p>Restrinja permissões nos arquivos crontab:</p>

<pre><code class="language-bash">ls -la /var/spool/cron/crontabs/

Deve mostrar: -rw------- 1 usuario crontab</code></pre>

<h2>Conclusão</h2>

<p>Você aprendeu que <strong>agendamento de tarefas é essencial para qualquer infraestrutura Linux</strong>, e dominar cron e at o tornará um administrador muito mais eficiente. Cron é sua ferramenta principal para tarefas recorrentes — backups, limpeza, sincronização — enquanto at resolve o problema de executar algo uma única vez em um momento específico. O terceiro ponto crucial é entender que <strong>logs e redirecionamento de saída são não-negociáveis</strong>: sem capturar a saída dos seus scripts agendados, você ficará cego quando algo não funcionar. Sempre use paths absolutos, defina variáveis de ambiente explicitamente, e monitore os logs do sistema.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://man7.org/linux/man-pages/man5/crontab.5.html" target="_blank" rel="noopener noreferrer">Man Page Crontab - Linux Manual Pages</a></li>

<li><a href="https://man7.org/linux/man-pages/man1/at.1.html" target="_blank" rel="noopener noreferrer">Man Page At - Linux Manual Pages</a></li>

<li><a href="https://www.gnu.org/software/coreutils/manual/" target="_blank" rel="noopener noreferrer">GNU Coreutils - Schedule Commands with At</a></li>

<li><a href="https://www.digitalocean.com/community/tutorials/how-to-use-cron-to-automate-tasks-on-a-vps" target="_blank" rel="noopener noreferrer">Digital Ocean - How To Use Cron to Automate Tasks</a></li>

<li><a href="https://tldp.org/LDP/sag/html/index.html" target="_blank" rel="noopener noreferrer">The Linux System Administrator&#039;s Guide</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

Dominando GitHub Actions Avançado: Matrix Builds, Environments e OIDC em Projetos Reais
Dominando GitHub Actions Avançado: Matrix Builds, Environments e OIDC em Projetos Reais

Matrix Builds: Executando Testes em Múltiplas Configurações A funcionalidade...

Estratégias de Testes em Pipelines CI: Unit, Integration e Smoke Tests na Prática
Estratégias de Testes em Pipelines CI: Unit, Integration e Smoke Tests na Prática

Fundamentos de Estratégias de Testes em Pipelines CI A integração contínua (C...

Como Usar Gerenciamento de Processos no Linux: systemd, journald e Serviços em Produção
Como Usar Gerenciamento de Processos no Linux: systemd, journald e Serviços em Produção

Entendendo o systemd: O Coração do Linux Moderno O systemd é o sistema de ini...