ManageBackups V2
This commit is contained in:
52
linux/backups_manage/README.md
Normal file
52
linux/backups_manage/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Script de Gerenciamento de Backup
|
||||
|
||||
Script para gerenciamento e rotação de backups em servidores FTP.
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
- **Varredura Dinâmica**: Detecta automaticamente novas pastas de usuários em `/home/ftpuser`.
|
||||
- **Organização Plana**: Arquivos antigos são movidos para `antigos/usuario/`, preservando a estrutura original.
|
||||
- **Limpeza Automática**:
|
||||
- Arquivos com mais de **15 dias** são movidos para a pasta de arquivamento.
|
||||
- Arquivos na pasta de arquivamento com mais de **60 dias** são excluídos permanentemente.
|
||||
- Logs de execução com mais de **30 dias** são removidos.
|
||||
- **Logs Detalhados**: Gera logs diários em `/home/ftpuser/logs/`.
|
||||
|
||||
## Instalação e Uso
|
||||
|
||||
### 1. Dependências
|
||||
O script utiliza apenas bibliotecas padrão do Python 3. Certifique-se de ter o Python 3 instalado:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install python3
|
||||
```
|
||||
|
||||
|
||||
### 2. Configuração do Cron
|
||||
Adicione a seguinte linha ao crontab (`crontab -e` ou `/etc/crontab`) para executar o script diariamente (ex: meia-noite):
|
||||
|
||||
```bash
|
||||
0 0 * * * root /usr/bin/python3 /usr/local/sbin/manage_backups.py
|
||||
```
|
||||
|
||||
### 3. Parametrização e Filtros
|
||||
As configurações podem ser ajustadas no topo do arquivo `manage_backups.py`:
|
||||
|
||||
**Retenção:**
|
||||
```python
|
||||
DIAS_MOVER = 15 # Dias antes de mover para 'antigos'
|
||||
DIAS_EXCLUIR_ANTIGOS = 60 # Dias antes de excluir permanentemente de 'antigos'
|
||||
DIAS_RETENCAO_LOGS = 30 # Dias de retenção dos logs
|
||||
```
|
||||
|
||||
**Filtros (Ignorar Pastas e Arquivos):**
|
||||
Você pode configurar pastas e extensões que o script deve **ignorar completamente** (não mover nem excluir):
|
||||
|
||||
```python
|
||||
# Pastas para ignorar na varredura
|
||||
DIRETORIOS_IGNORAR = ['antigos', 'logs', 'temp']
|
||||
|
||||
# Extensões para ignorar (ex: executáveis, isos)
|
||||
EXTENSOES_IGNORAR = ['.exe', '.iso']
|
||||
```
|
||||
224
linux/backups_manage/manage_backups.py
Normal file
224
linux/backups_manage/manage_backups.py
Normal file
@@ -0,0 +1,224 @@
|
||||
# Manage Backups V2.0 by Teccnia
|
||||
# https://teccnia.com.br
|
||||
|
||||
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
# ==========================================
|
||||
# CONFIGURAÇÃO
|
||||
# ==========================================
|
||||
|
||||
# Diretório base onde estão as pastas dos usuários FTP
|
||||
DIRETORIO_BASE = "/home/ftpuser"
|
||||
|
||||
# Nome das pastas para ignorar na varredura de usuários
|
||||
DIRETORIOS_IGNORAR = ['antigos', 'logs']
|
||||
|
||||
# Extensões para ignorar (não serão movidas nem deletadas)
|
||||
# Exemplo: ['.exe', '.iso']
|
||||
EXTENSOES_IGNORAR = ['.exe', '.iso']
|
||||
|
||||
# Configurações de Retenção
|
||||
DIAS_MOVER = 15 # Arquivos com mais de X dias são movidos para 'antigos'
|
||||
DIAS_EXCLUIR_ANTIGOS = 60 # Pastas em 'antigos' com mais de Y dias são excluídas
|
||||
DIAS_RETENCAO_LOGS = 30 # Logs com mais de Z dias são excluídos
|
||||
|
||||
# ======= NÃO ALTERAR A PARTIR DESTE PONTO!!! =======
|
||||
|
||||
# Nomes de diretórios de sistema
|
||||
NOME_DIR_ANTIGOS = "antigos"
|
||||
NOME_DIR_LOGS = "logs"
|
||||
|
||||
# Caminhos completos (serão definidos dinamicamente se baseados no DIRETORIO_BASE)
|
||||
DIR_LOGS = os.path.join(DIRETORIO_BASE, NOME_DIR_LOGS)
|
||||
DIR_ANTIGOS = os.path.join(DIRETORIO_BASE, NOME_DIR_ANTIGOS)
|
||||
|
||||
# Data atual para organização
|
||||
HOJE = datetime.now()
|
||||
DATA_HOJE_STR = HOJE.strftime('%Y-%m-%d')
|
||||
DATA_LOG_STR = HOJE.strftime('%d%m%Y')
|
||||
|
||||
# ==========================================
|
||||
# CONFIGURAÇÃO DE LOGS
|
||||
# ==========================================
|
||||
def configurar_logger():
|
||||
if not os.path.exists(DIR_LOGS):
|
||||
try:
|
||||
os.makedirs(DIR_LOGS)
|
||||
except Exception as e:
|
||||
print(f"ERRO CRÍTICO: Não foi possível criar diretório de logs {DIR_LOGS}: {e}")
|
||||
exit(1)
|
||||
|
||||
arquivo_log = os.path.join(DIR_LOGS, f"{DATA_LOG_STR}.log")
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.FileHandler(arquivo_log),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
return logging.getLogger()
|
||||
|
||||
# ==========================================
|
||||
# FUNÇÕES
|
||||
# ==========================================
|
||||
|
||||
def idade_arquivo_dias(caminho_arquivo):
|
||||
"""Retorna a idade do arquivo em dias."""
|
||||
timestamp_arquivo = os.path.getmtime(caminho_arquivo)
|
||||
data_arquivo = datetime.fromtimestamp(timestamp_arquivo)
|
||||
diferenca = HOJE - data_arquivo
|
||||
return diferenca.days
|
||||
|
||||
def listar_subdiretorios_usuarios(logger):
|
||||
"""Retorna lista de subdiretórios de usuários, ignorando pastas de sistema."""
|
||||
subdiretorios = []
|
||||
if not os.path.exists(DIRETORIO_BASE):
|
||||
logger.error(f"Diretório base não existe: {DIRETORIO_BASE}")
|
||||
return []
|
||||
|
||||
try:
|
||||
itens = os.listdir(DIRETORIO_BASE)
|
||||
for item in itens:
|
||||
caminho_completo = os.path.join(DIRETORIO_BASE, item)
|
||||
if os.path.isdir(caminho_completo):
|
||||
if item not in DIRETORIOS_IGNORAR:
|
||||
subdiretorios.append(item)
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao listar diretório base: {e}")
|
||||
|
||||
return subdiretorios
|
||||
|
||||
def processar_arquivos_antigos(usuario, logger):
|
||||
"""Move arquivos antigos do diretório do usuário para a pasta de arquivamento."""
|
||||
origem = os.path.join(DIRETORIO_BASE, usuario)
|
||||
destino_base = os.path.join(DIR_ANTIGOS, usuario)
|
||||
|
||||
if not os.path.exists(origem):
|
||||
logger.warning(f"Diretório de origem não encontrado: {origem}")
|
||||
return
|
||||
|
||||
arquivos_movidos = 0
|
||||
try:
|
||||
destino_criado = False
|
||||
|
||||
for arquivo in os.listdir(origem):
|
||||
caminho_arquivo = os.path.join(origem, arquivo)
|
||||
|
||||
if not os.path.isfile(caminho_arquivo):
|
||||
continue
|
||||
|
||||
_, ext = os.path.splitext(arquivo)
|
||||
if ext.lower() in [e.lower() for e in EXTENSOES_IGNORAR]:
|
||||
continue
|
||||
|
||||
idade = idade_arquivo_dias(caminho_arquivo)
|
||||
|
||||
if idade > DIAS_MOVER:
|
||||
if not destino_criado:
|
||||
os.makedirs(destino_base, exist_ok=True)
|
||||
destino_criado = True
|
||||
|
||||
shutil.move(caminho_arquivo, os.path.join(destino_base, arquivo))
|
||||
logger.info(f"Movido: {usuario}/{arquivo} ({idade} dias) -> {destino_base}")
|
||||
arquivos_movidos += 1
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao processar usuário {usuario}: {e}")
|
||||
|
||||
if arquivos_movidos > 0:
|
||||
logger.info(f"Usuário {usuario}: {arquivos_movidos} arquivos movidos.")
|
||||
|
||||
def limpar_arquivos_antigos(logger):
|
||||
"""Remove ARQUIVOS antigos em 'antigos' recursivamente."""
|
||||
if not os.path.exists(DIR_ANTIGOS):
|
||||
return
|
||||
|
||||
logger.info("Verificando limpeza de backups antigos (estrutura plana)...")
|
||||
arquivos_removidos = 0
|
||||
|
||||
try:
|
||||
for root, dirs, files in os.walk(DIR_ANTIGOS):
|
||||
for file in files:
|
||||
caminho_arquivo = os.path.join(root, file)
|
||||
|
||||
# Verificar extensão ignorada
|
||||
_, ext = os.path.splitext(file)
|
||||
if ext.lower() in [e.lower() for e in EXTENSOES_IGNORAR]:
|
||||
continue
|
||||
|
||||
try:
|
||||
idade = idade_arquivo_dias(caminho_arquivo)
|
||||
|
||||
if idade > DIAS_EXCLUIR_ANTIGOS:
|
||||
os.remove(caminho_arquivo)
|
||||
logger.info(f"Removido backup antigo: {caminho_arquivo} ({idade} dias)")
|
||||
arquivos_removidos += 1
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao verificar arquivo {caminho_arquivo}: {e}")
|
||||
|
||||
for root, dirs, files in os.walk(DIR_ANTIGOS, topdown=False):
|
||||
for name in dirs:
|
||||
caminho_dir = os.path.join(root, name)
|
||||
if not os.listdir(caminho_dir): # Se estiver vazio
|
||||
os.rmdir(caminho_dir)
|
||||
logger.debug(f"Removido diretório vazio: {caminho_dir}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao limpar backups antigos: {e}")
|
||||
|
||||
if arquivos_removidos > 0:
|
||||
logger.info(f"Total de backups antigos removidos: {arquivos_removidos}")
|
||||
|
||||
def rotacionar_logs(logger):
|
||||
"""Remove logs antigos."""
|
||||
if not os.path.exists(DIR_LOGS):
|
||||
return
|
||||
|
||||
logger.info("Verificando rotação de logs...")
|
||||
try:
|
||||
for arquivo in os.listdir(DIR_LOGS):
|
||||
caminho_arquivo = os.path.join(DIR_LOGS, arquivo)
|
||||
if os.path.isfile(caminho_arquivo):
|
||||
idade = idade_arquivo_dias(caminho_arquivo)
|
||||
if idade > DIAS_RETENCAO_LOGS:
|
||||
os.remove(caminho_arquivo)
|
||||
logger.info(f"Log removido: {arquivo} ({idade} dias)")
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao rotacionar logs: {e}")
|
||||
|
||||
# ==========================================
|
||||
# MAIN
|
||||
# ==========================================
|
||||
def main():
|
||||
# Inicializa Logger
|
||||
logger = configurar_logger()
|
||||
logger.info("=== Iniciando execução do script de backup ===")
|
||||
logger.info(f"Diretório Base: {DIRETORIO_BASE}")
|
||||
|
||||
# 1. Identificar usuários (subdiretórios)
|
||||
usuarios = listar_subdiretorios_usuarios(logger)
|
||||
logger.info(f"Usuários encontrados: {usuarios}")
|
||||
|
||||
# 2. Processar cada usuário
|
||||
for usuario in usuarios:
|
||||
processar_arquivos_antigos(usuario, logger)
|
||||
|
||||
# 3. Limpar pastas antigas de retenção
|
||||
limpar_arquivos_antigos(logger)
|
||||
|
||||
# 4. Rotacionar logs
|
||||
rotacionar_logs(logger)
|
||||
|
||||
logger.info("=== Execução finalizada com sucesso ===")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user