Optimización de almacenamiento y memoria en Armbian para dispositivos OneCloud

Introducción

Los dispositivos OneCloud (WanKe Yun) que ejecutan Armbian suelen contar con recursos limitados de RAM y almacenamiento eMMC. Para mantener el rendimiento óptimo, es recomendable implementar rutinas automatizadas de limpieza de caché, archivos temporales y gestión de memoria virtual. A continuación se presentan tres scripts robustos diseñados específicamente para este entorno.

  1. Script de Limpieza Integral del Sistema

Este script identifica y elimina paquetes APT obsoletos, archivos temporales huérfanos, logs rotados antiguos y cachés de usuario. Incluye una función de simulación para verificar qué espacio se liberará antes de ejecutar la acción destructiva.

Crea el archivo mediante:

nano /usr/local/bin/armbian_cleaner.sh

Pega el siguiente código:

#!/bin/bash
# Configuración de colores para salida legible
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m' # No Color

VERSION="2.0"
SIMULATE=false
AUTO_YES=false

function show_usage() {
    echo -e "${GREEN}Armbian Cleaner v${VERSION}${NC}"
    echo "Uso: $0 [opciones]"
    echo "  -s, --simulate   Muestra lo que se eliminaría sin borrar nada."
    echo "  -y, --yes        Ejecuta la limpieza sin solicitar confirmación."
    echo "  -h, --help       Muestra esta ayuda."
}

function get_dir_size() {
    local dir="$1"
    if [ -d "$dir" ]; then
        du -sb "$dir" 2>/dev/null | cut -f1
    else
        echo 0
    fi
}

function format_bytes() {
    local bytes=$1
    if (( bytes >= 1073741824 )); then
        printf "%.2f GB" $(echo "$bytes/1073741824" | bc -l)
    elif (( bytes >= 1048576 )); then
        printf "%.2f MB" $(echo "$bytes/1048576" | bc -l)
    elif (( bytes >= 1024 )); then
        printf "%.2f KB" $(echo "$bytes/1024" | bc -l)
    else
        printf "%d B" "$bytes"
    fi
}

function clean_apt_cache() {
    local path="/var/cache/apt/archives"
    local size=$(get_dir_size "$path")
    
    if [[ "$SIMULATE" == true ]]; then
        echo -e "${BLUE}[APT]${NC} Caché detectada: $(format_bytes $size)"
    else
        rm -rf "$path"/*.deb "$path"/*.udeb
        echo -e "${GREEN}[APT]${NC} Caché eliminada."
    fi
}

function clean_temp_dirs() {
    local total=0
    for dir in "/tmp" "/var/tmp"; do
        local size=$(get_dir_size "$dir")
        total=$((total + size))
        
        if [[ "$SIMULATE" == false ]]; then
            find "$dir" -mindepth 1 -delete 2>/dev/null
        fi
    done
    
    if [[ "$SIMULATE" == true ]]; then
        echo -e "${BLUE}[TMP]${NC} Archivos temporales: $(format_bytes $total)"
    else
        echo -e "${GREEN}[TMP]${NC} Directorios temporales purgados."
    fi
}

function clean_old_logs() {
    local count=0
    local freed=0
    
    # Busca logs comprimidos o rotados (ej. *.gz, *.1, *.old)
    while IFS= read -r -d '' file; do
        local fsize=$(stat -c%s "$file" 2>/dev/null || echo 0)
        freed=$((freed + fsize))
        count=$((count + 1))
        
        if [[ "$SIMULATE" == false ]]; then
            rm -f "$file"
        fi
    done < <(find /var/log -type f \( -name "*.gz" -o -name "*.old" -o -regex ".*\.[0-9]+" \) -print0 2>/dev/null)

    if [[ "$SIMULATE" == true ]]; then
        echo -e "${BLUE}[LOG]${NC} Logs rotados ($count): $(format_bytes $freed)"
    else
        echo -e "${GREEN}[LOG]${NC} Se eliminaron $count archivos de log antiguos."
    fi
}

function main() {
    # Parsear argumentos
    while [[ $# -gt 0 ]]; do
        case $1 in
            -s|--simulate) SIMULATE=true ;;
            -y|--yes) AUTO_YES=true ;;
            -h|--help) show_usage; exit 0 ;;
            *) echo -e "${RED}Error: Opción desconocida $1${NC}"; exit 1 ;;
        esac
        shift
    done

    # Verificar permisos root
    if [ "$(id -u)" != "0" ]; then
        echo -e "${RED}Este script requiere privilegios de root.${NC}"
        exit 1
    fi

    echo -e "\n${BLUE}Iniciando escaneo del sistema...${NC}"
    
    # Fase de Escaneo/Limpieza
    clean_apt_cache
    clean_temp_dirs
    clean_old_logs

    if [[ "$SIMULATE" == true ]]; then
        echo -e "\n${YELLOW}Modo simulación activado. Ningún archivo fue borrado.${NC}"
        exit 0
    fi

    # Confirmación interactiva si no se usó -y
    if [[ "$AUTO_YES" == false ]]; then
        echo -en "\n${RED}¿Continuar con la eliminación permanente? (y/N): ${NC}"
        read -r response
        if [[ ! "$response" =~ ^[Yy]$ ]]; then
            echo "Operación cancelada."
            exit 0
        fi
    fi

    echo -e "\n${GREEN}Limpieza completada exitosamente.${NC}"
}

main "$@"

Otorga permisos de ejecución y prueba:

chmod +x /usr/local/bin/armbian_cleaner.sh
sudo armbian_cleaner.sh --simulate
sudo armbian_cleaner.sh --yes

  1. Gestor de Memoria y Liberación de Caché de Kernel

En sistemas con poca RAM, el kernel puede retener datos en caché de página que impiden nuevas asignaciones. Este script monitorea el uso de memoria física y libera la caché de disco (page cache, dentries e inodes) cuando el umbral de uso supera el 85%.

Crea el archivo:

nano /usr/local/bin/memory_guard.sh

Contenido del script:

#!/bin/bash
LOG_FILE="/var/log/memory_guard.log"
THRESHOLD_PERCENT=85

log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# Obtener estadísticas de memoria usando 'free'
# Formato típico: Mem:  Total Used Free Buffers Cached Available
MEM_INFO=$(free -b | awk '/^Mem:/ {print $2, $3, $7}')
TOTAL_MEM=$(echo "$MEM_INFO" | awk '{print $1}')
USED_MEM=$(echo "$MEM_INFO" | awk '{print $2}')
AVAIL_MEM=$(echo "$MEM_INFO" | awk '{print $3}')

if [ -z "$TOTAL_MEM" ] || [ "$TOTAL_MEM" -eq 0 ]; then
    log_message "ERROR: No se pudo leer la información de memoria."
    exit 1
fi

# Calcular porcentaje de uso real (basado en usado vs total)
USAGE_PERCENT=$(awk "BEGIN {printf \"%.2f\", ($USED_MEM/$TOTAL_MEM)*100}")

log_message "Estado Actual -> Total: $(numfmt --to=iec $TOTAL_MEM), Usado: $(numfmt --to=iec $USED_MEM), Uso: ${USAGE_PERCENT}%"

# Comparar con el umbral
if (( $(echo "$USAGE_PERCENT > $THRESHOLD_PERCENT" | bc -l) )); then
    log_message "Umbral superado (${THRESHOLD_PERCENT}%). Iniciando limpieza de caché del kernel..."
    
    # Sincronizar sistemas de archivos primero para evitar corrupción
    sync
    
    # Escribir 3 a drop_caches libera pagecache, dentries e inodes
    if echo 3 > /proc/sys/vm/drop_caches; then
        log_message "Caché liberada correctamente."
        
        # Re-leer memoria para confirmar mejora
        NEW_AVAIL=$(free -b | awk '/^Mem:/ {print $7}')
        IMPROVEMENT=$((NEW_AVAIL - AVAIL_MEM))
        log_message "Memoria disponible incrementada en: $(numfmt --to=iec $IMPROVEMENT)"
    else
        log_message "FALLO: No se pudo escribir en /proc/sys/vm/drop_caches. ¿Permisos insuficientes?"
    fi
else
    log_message "El uso de memoria está dentro del rango seguro. No se realiza ninguna acción."
fi

Configuración de ejecución periódica vía Cron:

chmod +x /usr/local/bin/memory_guard.sh
crontab -e

Añade la siguiente línea al final del editor cron para ejecutarlo cada hora:

0 * * * * /usr/local/bin/memory_guard.sh >/dev/null 2>&1

  1. Limpiador de Artefactos de Usuario y Shell

Los shells como Zsh o Bash generan archivos de autocompletado y historial que pueden acumularce. Además, herramientas como wget dejan rastros de seguridad. Este script elimina estos artefactos específicos del directorio personal.

Crea el archivo:

nano /usr/local/bin/user_artifacts_clean.sh

Contenido:

#!/bin/bash
# Define los patrones de archivos a eliminar en el home directory
TARGET_PATTERNS=(
    ".wget-hsts"
    ".viminfo"
    ".zcompdump*"
    ".bash_history.tmp*"
    "*.log" # Solo en el directorio actual si se ejecuta desde allí, cuidado con esto en producción
)

CURRENT_DIR=$(pwd)
HOME_DIR=$HOME

echo "Limpiando artefactos en $HOME_DIR..."

# Eliminar archivos específicos de configuración/historial temporal
for pattern in "${TARGET_PATTERNS[@]}"; do
    # Buscar solo en el nivel raíz del HOME para mayor seguridad
    files_to_delete=$(find "$HOME_DIR" -maxdepth 1 -type f -name "$pattern" 2>/dev/null)
    
    if [ -n "$files_to_delete" ]; then
        echo "$files_to_delete" | xargs rm -f
        echo "Eliminados archivos coincidentes con patrón: $pattern"
    fi
done

# Nota: La eliminación de *.log en el directorio actual es opcional y peligrosa si se ejecuta en /
# Aquí mostramos cómo limpiar logs específicos de aplicaciones en subdirectorios conocidos si fuera necesario
# find "$HOME_DIR/.config" -name "*.log" -delete

echo "Limpieza de artefactos de usuario finalizada."

Ejecución manual o programada:

chmod +x /usr/local/bin/user_artifacts_clean.sh
/usr/local/bin/user_artifacts_clean.sh

Consideraciones Adicionales

  • Seguridad: Los scripts que utilizan rm -rf deben probarse siempre primero con la opción --simulate o mediante echo en lugar de la eliminación real.
  • Logs: El script de memoria escribe en /var/log/memory_guard.log. Asegúrate de que este archivo no crezca indefinidamente; puedes añadir una rotación simple al principio del script si es necesario.
  • Dependencias: Estos scripts requieren bc, awk, du y find, que están presentes por defecto en casi todas las instalcaiones de Armbian/Debian.

Etiquetas: Armbian OneCloud bash scripting System Maintenance Linux Memory Management

Publicado el 10-7 00:50