Fundamentos de la Gestión de Directorios
La gestión eficiente de directorios es fundamental para mantener sistemas organizados, seguros y fáciles de mantener. Como administrador de sistemas, dominarás técnicas avanzadas para crear, organizar, sincronizar y mantener estructuras de directorios complejas.
Creación
Estructuras complejas con permisos específicos
Sincronización
Mantener directorios actualizados y consistentes
Seguridad
Control de acceso y permisos avanzados
Monitoreo
Seguimiento de cambios y uso del espacio
Principios de Organización
- Jerarquía lógica: Estructura que refleja la función y relaciones
- Nomenclatura consistente: Convenciones claras para nombres
- Separación de responsabilidades: Datos, configuración, logs separados
- Escalabilidad: Estructura que crece ordenadamente
- Mantenibilidad: Fácil de respaldar, limpiar y reorganizar
Creación Avanzada de Directorios
Más allá del simple mkdir
, aprenderemos técnicas avanzadas para crear estructuras complejas con permisos específicos y metadatos.
Creación de Estructuras Complejas
# Crear estructura completa de proyecto
mkdir -p proyecto/{src,docs,tests,config,logs,tmp,backups}
mkdir -p proyecto/src/{main,lib,utils}
mkdir -p proyecto/docs/{api,user,dev}
mkdir -p proyecto/tests/{unit,integration,performance}
# Verificar estructura creada
tree proyecto/
proyecto/
├── backups/
├── config/
├── docs/
│ ├── api/
│ ├── dev/
│ └── user/
├── logs/
├── src/
│ ├── lib/
│ ├── main/
│ └── utils/
├── tests/
│ ├── integration/
│ ├── performance/
│ └── unit/
└── tmp/
# Crear con permisos específicos
mkdir -m 755 public_dir # rwxr-xr-x
mkdir -m 700 private_dir # rwx------
mkdir -m 775 shared_dir # rwxrwxr-x
# Crear directorios con propietario específico (como root)
sudo mkdir -p /opt/miapp/{bin,etc,var,log}
sudo chown -R usuario:grupo /opt/miapp
sudo chmod -R 755 /opt/miapp
Script para Estructuras Estandarizadas
#!/bin/bash
# create_project_structure.sh - Generador de estructura estándar de proyectos
PROJECT_NAME="$1"
PROJECT_TYPE="${2:-web}" # web, api, desktop, mobile
if [[ -z "$PROJECT_NAME" ]]; then
echo "Uso: $0 nombre_proyecto [tipo]"
echo "Tipos disponibles: web, api, desktop, mobile"
exit 1
fi
# Validar que no existe el directorio
if [[ -d "$PROJECT_NAME" ]]; then
echo "❌ Error: El directorio '$PROJECT_NAME' ya existe"
exit 1
fi
echo "🏗️ Creando estructura de proyecto: $PROJECT_NAME (tipo: $PROJECT_TYPE)"
# Función para crear estructura web
create_web_structure() {
local project="$1"
# Estructura básica
mkdir -p "$project"/{src,public,docs,tests,config,scripts,logs}
# Subdirectorios específicos web
mkdir -p "$project"/src/{components,pages,styles,assets,utils,hooks}
mkdir -p "$project"/public/{images,css,js,fonts}
mkdir -p "$project"/tests/{unit,e2e,integration}
mkdir -p "$project"/docs/{design,api,deployment}
mkdir -p "$project"/config/{development,production,testing}
# Archivos básicos
touch "$project"/README.md
touch "$project"/.gitignore
touch "$project"/package.json
echo "node_modules/\n*.log\ndist/\nbuild/" > "$project"/.gitignore
}
# Función para crear estructura API
create_api_structure() {
local project="$1"
mkdir -p "$project"/{src,tests,docs,config,scripts,logs,data}
mkdir -p "$project"/src/{controllers,models,routes,middleware,utils,services}
mkdir -p "$project"/tests/{unit,integration,load}
mkdir -p "$project"/docs/{api,swagger,postman}
mkdir -p "$project"/config/{database,auth,cors}
mkdir -p "$project"/data/{migrations,seeds,backups}
touch "$project"/README.md
touch "$project"/.env.example
touch "$project"/server.js
}
# Función para crear estructura desktop
create_desktop_structure() {
local project="$1"
mkdir -p "$project"/{src,resources,docs,tests,build,dist}
mkdir -p "$project"/src/{main,renderer,shared,assets}
mkdir -p "$project"/resources/{icons,images,fonts}
mkdir -p "$project"/tests/{unit,integration,ui}
mkdir -p "$project"/build/{scripts,configs}
touch "$project"/README.md
touch "$project"/main.js
touch "$project"/package.json
}
# Crear estructura según el tipo
case "$PROJECT_TYPE" in
"web")
create_web_structure "$PROJECT_NAME"
;;
"api")
create_api_structure "$PROJECT_NAME"
;;
"desktop")
create_desktop_structure "$PROJECT_NAME"
;;
"mobile")
mkdir -p "$PROJECT_NAME"/{src,assets,tests,docs,android,ios}
mkdir -p "$PROJECT_NAME"/src/{components,screens,services,utils,store}
mkdir -p "$PROJECT_NAME"/assets/{images,fonts,sounds}
;;
*)
echo "❌ Tipo de proyecto no reconocido: $PROJECT_TYPE"
exit 1
;;
esac
# Establecer permisos apropiados
chmod 755 "$PROJECT_NAME"
find "$PROJECT_NAME" -type d -exec chmod 755 {} \;
find "$PROJECT_NAME" -type f -exec chmod 644 {} \;
# Crear archivo de información del proyecto
cat > "$PROJECT_NAME"/project_info.txt << EOF
Proyecto: $PROJECT_NAME
Tipo: $PROJECT_TYPE
Creado: $(date)
Usuario: $(whoami)
Hostname: $(hostname)
Estructura creada por: create_project_structure.sh
EOF
# Mostrar estructura creada
echo "✅ Estructura creada exitosamente"
echo
echo "📁 Estructura del proyecto:"
tree "$PROJECT_NAME" -L 3 2>/dev/null || find "$PROJECT_NAME" -type d | head -20
echo
echo "📋 Próximos pasos:"
echo " cd $PROJECT_NAME"
echo " git init"
echo " # Comenzar desarrollo"
# Usar el script generador
$ chmod +x create_project_structure.sh
# Crear proyecto web
$ ./create_project_structure.sh mi-web-app web
🏗️ Creando estructura de proyecto: mi-web-app (tipo: web)
✅ Estructura creada exitosamente
📁 Estructura del proyecto:
mi-web-app/
├── config/
│ ├── development/
│ ├── production/
│ └── testing/
├── docs/
│ ├── api/
│ ├── deployment/
│ └── design/
├── logs/
├── public/
│ ├── css/
│ ├── fonts/
│ ├── images/
│ └── js/
├── scripts/
├── src/
│ ├── assets/
│ ├── components/
│ ├── hooks/
│ ├── pages/
│ ├── styles/
│ └── utils/
└── tests/
├── e2e/
├── integration/
└── unit/
Copia y Sincronización
La copia y sincronización eficientes de directorios son cruciales para respaldos, despliegues y mantenimiento de sistemas distribuidos.
Copia Inteligente con rsync
# Sincronización básica (local)
rsync -av /origen/ /destino/
# -a: modo archivo (preserva permisos, fechas, enlaces)
# -v: verbose (mostrar progreso)
# Sincronización con exclusiones
rsync -av --exclude='*.log' --exclude='tmp/' /proyecto/ /respaldo/
# Sincronización con progreso detallado
rsync -av --progress --stats /datos/ /backup/
# Sincronización en seco (simular sin hacer cambios)
rsync -av --dry-run /origen/ /destino/
# Sincronización remota
rsync -av -e ssh /local/ usuario@servidor:/remoto/
# Sincronización bidireccional (cuidado con conflictos)
rsync -av --delete /dir1/ /dir2/
rsync -av --delete /dir2/ /dir1/
# Sincronización con filtros complejos
rsync -av \
--include='*.php' \
--include='*.js' \
--include='*/' \
--exclude='*' \
/proyecto/src/ /produccion/src/
Script de Sincronización Avanzada
#!/bin/bash
# advanced_sync.sh - Sincronizador avanzado de directorios
# Configuración
SOURCE_DIR="$1"
TARGET_DIR="$2"
CONFIG_FILE="$3"
LOG_DIR="/var/log/sync"
LOG_FILE="$LOG_DIR/sync_$(date +%Y%m%d_%H%M%S).log"
# Crear directorio de logs
mkdir -p "$LOG_DIR"
# Función de logging
log_message() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# Validar argumentos
if [[ $# -lt 2 ]]; then
echo "Uso: $0 [archivo_config]"
echo "Ejemplo: $0 /home/user/docs /backup/docs sync.conf"
exit 1
fi
# Cargar configuración si existe
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
log_message "INFO" "Configuración cargada desde: $CONFIG_FILE"
else
# Configuración por defecto
EXCLUDE_PATTERNS=(
"*.tmp"
"*.log"
"*.cache"
".DS_Store"
"Thumbs.db"
"node_modules/"
".git/"
"*.pyc"
"__pycache__/"
)
SYNC_OPTIONS="-av"
BANDWIDTH_LIMIT=""
COMPRESSION=true
DELETE_EXCLUDED=false
MAKE_BACKUP=true
BACKUP_DIR="backups/"
fi
log_message "INFO" "Iniciando sincronización"
log_message "INFO" "Origen: $SOURCE_DIR"
log_message "INFO" "Destino: $TARGET_DIR"
# Verificar que el directorio origen existe
if [[ ! -d "$SOURCE_DIR" ]]; then
log_message "ERROR" "Directorio origen no existe: $SOURCE_DIR"
exit 1
fi
# Crear directorio destino si no existe
if [[ ! -d "$TARGET_DIR" ]]; then
log_message "INFO" "Creando directorio destino: $TARGET_DIR"
mkdir -p "$TARGET_DIR" || {
log_message "ERROR" "No se pudo crear directorio destino"
exit 1
}
fi
# Construir comando rsync
RSYNC_CMD="rsync $SYNC_OPTIONS"
# Agregar exclusiones
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
RSYNC_CMD+=" --exclude='$pattern'"
done
# Opciones adicionales
if [[ "$COMPRESSION" == true ]]; then
RSYNC_CMD+=" -z"
fi
if [[ -n "$BANDWIDTH_LIMIT" ]]; then
RSYNC_CMD+=" --bwlimit=$BANDWIDTH_LIMIT"
fi
if [[ "$DELETE_EXCLUDED" == true ]]; then
RSYNC_CMD+=" --delete"
fi
if [[ "$MAKE_BACKUP" == true ]]; then
RSYNC_CMD+=" --backup --backup-dir=$BACKUP_DIR"
fi
# Agregar progreso y estadísticas
RSYNC_CMD+=" --progress --stats"
# Agregar directorios
RSYNC_CMD+=" '$SOURCE_DIR/' '$TARGET_DIR/'"
log_message "INFO" "Ejecutando comando: $RSYNC_CMD"
# Ejecutar sincronización
start_time=$(date +%s)
eval "$RSYNC_CMD" 2>&1 | tee -a "$LOG_FILE"
exit_code=${PIPESTATUS[0]}
end_time=$(date +%s)
duration=$((end_time - start_time))
# Evaluar resultado
if [[ $exit_code -eq 0 ]]; then
log_message "SUCCESS" "Sincronización completada exitosamente en ${duration}s"
else
log_message "ERROR" "Sincronización falló con código de salida: $exit_code"
fi
# Generar estadísticas
log_message "INFO" "Generando estadísticas post-sincronización"
{
echo "=== ESTADÍSTICAS DE SINCRONIZACIÓN ==="
echo "Fecha: $(date)"
echo "Origen: $SOURCE_DIR"
echo "Destino: $TARGET_DIR"
echo "Duración: ${duration}s"
echo "Código de salida: $exit_code"
echo
echo "Espacio utilizado:"
du -sh "$SOURCE_DIR" 2>/dev/null | awk '{print " Origen: " $1}'
du -sh "$TARGET_DIR" 2>/dev/null | awk '{print " Destino: " $1}'
echo
echo "Archivos más recientes en destino:"
find "$TARGET_DIR" -type f -newer "$LOG_FILE" 2>/dev/null | head -10 || echo " Ninguno"
} >> "$LOG_FILE"
# Cleanup de logs antiguos (mantener últimos 30 días)
find "$LOG_DIR" -name "sync_*.log" -type f -mtime +30 -delete 2>/dev/null
log_message "INFO" "Log guardado en: $LOG_FILE"
exit $exit_code
Archivo de Configuración
# sync.conf - Archivo de configuración para advanced_sync.sh
# Patrones a excluir
EXCLUDE_PATTERNS=(
"*.tmp"
"*.log"
"*.pid"
"*.swp"
"*.cache"
".DS_Store"
"Thumbs.db"
"node_modules/"
".git/"
"*.pyc"
"__pycache__/"
"venv/"
".env"
"database.sqlite"
)
# Opciones de rsync
SYNC_OPTIONS="-av --partial --timeout=300"
# Límite de ancho de banda (KB/s) - vacío para sin límite
BANDWIDTH_LIMIT="1000"
# Usar compresión (true/false)
COMPRESSION=true
# Eliminar archivos del destino que no existen en origen
DELETE_EXCLUDED=true
# Crear respaldos de archivos modificados
MAKE_BACKUP=true
BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)/"
# Usar el script
$ chmod +x advanced_sync.sh
$ ./advanced_sync.sh /home/user/proyecto /backup/proyecto sync.conf
Análisis de Uso del Espacio
El monitoreo del uso del espacio en directorios es esencial para mantener sistemas eficientes y prevenir problemas de almacenamiento.
Herramientas de Análisis
# Uso básico con du
$ du -h /var/log | sort -hr | head -10
2.1G /var/log
1.8G /var/log/apache2
256M /var/log/syslog
89M /var/log/auth.log
45M /var/log/kern.log
# Análisis por profundidad
$ du -h --max-depth=2 /opt | sort -hr
1.5G /opt
890M /opt/google
512M /opt/microsoft
256M /opt/local/bin
128M /opt/local/lib
# Solo directorios (sin archivos individuales)
$ du -sh */ | sort -hr
3.2G Videos/
1.8G Documents/
567M Pictures/
234M Downloads/
# Encontrar archivos grandes
$ find /var -type f -size +100M -exec du -h {} + | sort -hr
2.1G /var/log/huge.log
567M /var/lib/mysql/database.sql
234M /var/cache/large_file.cache
Analizador Avanzado de Espacio
#!/bin/bash
# disk_analyzer.sh - Analizador avanzado de uso de disco
TARGET_DIR="${1:-.}"
REPORT_FILE="disk_analysis_$(date +%Y%m%d_%H%M%S).html"
THRESHOLD_MB=100
# Función para convertir bytes a formato legible
human_readable() {
local bytes=$1
local units=("B" "KB" "MB" "GB" "TB")
local unit=0
while [[ $bytes -gt 1024 && $unit -lt 4 ]]; do
bytes=$((bytes / 1024))
((unit++))
done
echo "${bytes}${units[$unit]}"
}
# Generar reporte HTML
cat > "$REPORT_FILE" << 'EOF'
Análisis de Uso de Disco
EOF
# Header del reporte
cat >> "$REPORT_FILE" << EOF
📊 Análisis de Uso de Disco
Directorio analizado: $(realpath "$TARGET_DIR")
Fecha: $(date)
Host: $(hostname)
EOF
echo "🔍 Analizando directorio: $TARGET_DIR"
echo "📊 Generando reporte: $REPORT_FILE"
# 1. RESUMEN GENERAL
echo "" >> "$REPORT_FILE"
echo "📋 Resumen General
" >> "$REPORT_FILE"
TOTAL_SIZE=$(du -sb "$TARGET_DIR" 2>/dev/null | cut -f1)
TOTAL_FILES=$(find "$TARGET_DIR" -type f 2>/dev/null | wc -l)
TOTAL_DIRS=$(find "$TARGET_DIR" -type d 2>/dev/null | wc -l)
cat >> "$REPORT_FILE" << EOF
Métrica Valor
Tamaño Total $(human_readable $TOTAL_SIZE)
Archivos $TOTAL_FILES
Directorios $TOTAL_DIRS
Última modificación $(stat -c %y "$TARGET_DIR" 2>/dev/null | cut -d'.' -f1)
EOF
echo "" >> "$REPORT_FILE"
# 2. TOP DIRECTORIOS
echo "" >> "$REPORT_FILE"
echo "📁 Top 10 Directorios por Tamaño
" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo "Directorio Tamaño % del Total Barra " >> "$REPORT_FILE"
du -sb "$TARGET_DIR"/* 2>/dev/null | sort -nr | head -10 | while read size path; do
percentage=$(( (size * 100) / TOTAL_SIZE ))
bar_width=$(( percentage > 100 ? 100 : percentage ))
# Determinar clase de color
if [[ $percentage -gt 50 ]]; then
bar_class="progress-critical"
elif [[ $percentage -gt 25 ]]; then
bar_class="progress-warning"
else
bar_class=""
fi
cat >> "$REPORT_FILE" << EOF
$(basename "$path")
$(human_readable $size)
${percentage}%
EOF
done
echo "
" >> "$REPORT_FILE"
# 3. ARCHIVOS GRANDES
echo "" >> "$REPORT_FILE"
echo "📄 Archivos Más Grandes
" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo "Archivo Tamaño Directorio Última Modificación " >> "$REPORT_FILE"
find "$TARGET_DIR" -type f -size +${THRESHOLD_MB}M 2>/dev/null | \
xargs ls -la 2>/dev/null | sort -k5 -nr | head -20 | \
while read -r permissions links owner group size month day time_or_year filepath; do
filename=$(basename "$filepath")
dirpath=$(dirname "$filepath" | sed "s|^$TARGET_DIR/||")
cat >> "$REPORT_FILE" << EOF
$filename
$(human_readable $size)
$dirpath
$month $day $time_or_year
EOF
done
echo "
" >> "$REPORT_FILE"
# 4. ANÁLISIS POR TIPO DE ARCHIVO
echo "" >> "$REPORT_FILE"
echo "🎯 Análisis por Tipo de Archivo
" >> "$REPORT_FILE"
# Crear archivo temporal para estadísticas por extensión
TEMP_FILE=$(mktemp)
find "$TARGET_DIR" -type f 2>/dev/null | while read file; do
extension="${file##*.}"
if [[ "$extension" == "$(basename "$file")" ]]; then
extension="sin_extension"
fi
size=$(stat -c%s "$file" 2>/dev/null || echo 0)
echo "$extension $size"
done > "$TEMP_FILE"
echo "" >> "$REPORT_FILE"
echo "Extensión Archivos Tamaño Total % del Total " >> "$REPORT_FILE"
awk '{ext[$1]++; size[$1]+=$2} END {
for(e in ext) print ext[e], size[e], e
}' "$TEMP_FILE" | sort -nr | head -15 | while read count total_size ext; do
percentage=$(( (total_size * 100) / TOTAL_SIZE ))
cat >> "$REPORT_FILE" << EOF
.$ext
$count
$(human_readable $total_size)
${percentage}%
EOF
done
echo "
" >> "$REPORT_FILE"
# 5. ARCHIVOS ANTIGUOS (no modificados en 6 meses)
echo "" >> "$REPORT_FILE"
echo "🕰️ Archivos Antiguos (sin modificar >6 meses)
" >> "$REPORT_FILE"
OLD_FILES=$(find "$TARGET_DIR" -type f -mtime +180 2>/dev/null | wc -l)
OLD_SIZE=$(find "$TARGET_DIR" -type f -mtime +180 2>/dev/null -exec stat -c%s {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
if [[ $OLD_FILES -gt 0 ]]; then
cat >> "$REPORT_FILE" << EOF
⚠️ Archivos antiguos detectados:
- Cantidad: $OLD_FILES archivos
- Espacio ocupado: $(human_readable $OLD_SIZE)
- % del total: $(( (OLD_SIZE * 100) / TOTAL_SIZE ))%
EOF
else
echo "✅ No se encontraron archivos antiguos
" >> "$REPORT_FILE"
fi
echo "" >> "$REPORT_FILE"
# Cerrar HTML
echo "" >> "$REPORT_FILE"
# Cleanup
rm -f "$TEMP_FILE" 2>/dev/null
echo "✅ Análisis completado"
echo "📄 Reporte generado: $REPORT_FILE"
echo "🌐 Abrir con: firefox $REPORT_FILE"
# Mostrar resumen en terminal
echo
echo "📊 RESUMEN RÁPIDO:"
echo " Tamaño total: $(human_readable $TOTAL_SIZE)"
echo " Archivos: $TOTAL_FILES"
echo " Directorios: $TOTAL_DIRS"
if [[ $OLD_FILES -gt 0 ]]; then
echo " ⚠️ Archivos antiguos: $OLD_FILES ($(human_readable $OLD_SIZE))"
fi
Permisos y Seguridad Avanzada
La gestión de permisos en directorios va más allá de rwx básico. Exploraremos ACLs, atributos extendidos y técnicas avanzadas de seguridad.
Permisos Especiales
# Crear directorio compartido con SGID
mkdir /shared/project
chmod 2775 /shared/project # rwxrwsr-x
chgrp developers /shared/project
# Verificar que funciona
ls -ld /shared/project
drwxrwsr-x 2 root developers 4096 oct 15 10:30 /shared/project
# Todos los archivos creados heredarán el grupo 'developers'
touch /shared/project/test.txt
ls -l /shared/project/test.txt
-rw-r--r-- 1 usuario developers 0 oct 15 10:31 test.txt
# Configurar directorio temporal con sticky bit
mkdir /tmp/shared
chmod 1777 /tmp/shared # rwxrwxrwt
ls -ld /tmp/shared
drwxrwxrwt 2 root root 4096 oct 15 10:32 /tmp/shared
# ACLs (Access Control Lists) - más granular
# Instalar herramientas ACL si no están disponibles
# sudo apt-get install acl
# Dar permisos específicos a usuario
setfacl -m u:alice:rx /proyecto/datos
setfacl -m g:developers:rwx /proyecto/src
# Ver ACLs
getfacl /proyecto/datos
# file: proyecto/datos
# owner: root
# group: root
# user::rwx
# user:alice:r-x
# group::r-x
# mask::r-x
# other::---
# Establecer ACLs por defecto (para nuevos archivos)
setfacl -d -m g:developers:rwx /proyecto/src
# Remover ACLs
setfacl -x u:alice /proyecto/datos
Auditor de Seguridad de Directorios
#!/bin/bash
# security_audit.sh - Auditor de seguridad para directorios
AUDIT_DIR="${1:-.}"
REPORT_FILE="security_audit_$(date +%Y%m%d_%H%M%S).txt"
echo "🔒 AUDITORÍA DE SEGURIDAD DE DIRECTORIOS" > "$REPORT_FILE"
echo "===========================================" >> "$REPORT_FILE"
echo "Directorio: $(realpath "$AUDIT_DIR")" >> "$REPORT_FILE"
echo "Fecha: $(date)" >> "$REPORT_FILE"
echo "Usuario: $(whoami)" >> "$REPORT_FILE"
echo >> "$REPORT_FILE"
# Función para logging
audit_log() {
echo "$1" | tee -a "$REPORT_FILE"
}
# 1. PERMISOS PELIGROSOS
audit_log "🚨 1. VERIFICACIÓN DE PERMISOS PELIGROSOS"
audit_log "============================================"
# Directorios escribibles por todos
WORLD_WRITABLE=$(find "$AUDIT_DIR" -type d -perm -002 2>/dev/null)
if [[ -n "$WORLD_WRITABLE" ]]; then
audit_log "⚠️ ADVERTENCIA: Directorios escribibles por todos:"
echo "$WORLD_WRITABLE" | while read dir; do
perms=$(ls -ld "$dir" | cut -d' ' -f1)
audit_log " $perms $dir"
done
else
audit_log "✅ No se encontraron directorios escribibles por todos"
fi
audit_log ""
# Archivos SUID/SGID
SUID_FILES=$(find "$AUDIT_DIR" -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null)
if [[ -n "$SUID_FILES" ]]; then
audit_log "⚠️ ADVERTENCIA: Archivos con SUID/SGID:"
echo "$SUID_FILES" | while read file; do
perms=$(ls -l "$file" | cut -d' ' -f1)
audit_log " $perms $file"
done
else
audit_log "✅ No se encontraron archivos SUID/SGID"
fi
audit_log ""
# 2. PROPIETARIOS SOSPECHOSOS
audit_log "👤 2. VERIFICACIÓN DE PROPIETARIOS"
audit_log "=================================="
# Archivos sin propietario (UID no existe)
NO_OWNER=$(find "$AUDIT_DIR" -nouser 2>/dev/null)
if [[ -n "$NO_OWNER" ]]; then
audit_log "⚠️ ADVERTENCIA: Archivos sin propietario válido:"
echo "$NO_OWNER" | head -10 | while read file; do
stat_info=$(stat -c "%n %u:%g %a" "$file" 2>/dev/null)
audit_log " $stat_info"
done
total_no_owner=$(echo "$NO_OWNER" | wc -l)
if [[ $total_no_owner -gt 10 ]]; then
audit_log " ... y $((total_no_owner - 10)) más"
fi
else
audit_log "✅ Todos los archivos tienen propietario válido"
fi
audit_log ""
# Archivos sin grupo válido
NO_GROUP=$(find "$AUDIT_DIR" -nogroup 2>/dev/null)
if [[ -n "$NO_GROUP" ]]; then
audit_log "⚠️ ADVERTENCIA: Archivos sin grupo válido:"
echo "$NO_GROUP" | head -5 | while read file; do
audit_log " $file"
done
else
audit_log "✅ Todos los archivos tienen grupo válido"
fi
audit_log ""
# 3. ARCHIVOS EJECUTABLES SOSPECHOSOS
audit_log "⚡ 3. VERIFICACIÓN DE EJECUTABLES"
audit_log "==============================="
# Scripts sin extensión ejecutables
SUSPICIOUS_SCRIPTS=$(find "$AUDIT_DIR" -type f -executable \! -name "*.sh" \! -name "*.py" \! -name "*.pl" \! -name "*.rb" 2>/dev/null | grep -v "/bin/" | head -10)
if [[ -n "$SUSPICIOUS_SCRIPTS" ]]; then
audit_log "⚠️ ADVERTENCIA: Scripts ejecutables sin extensión:"
echo "$SUSPICIOUS_SCRIPTS" | while read script; do
file_type=$(file "$script" | cut -d':' -f2)
audit_log " $script -$file_type"
done
else
audit_log "✅ No se encontraron scripts sospechosos"
fi
audit_log ""
# 4. ARCHIVOS TEMPORALES Y BASURA
audit_log "🗑️ 4. VERIFICACIÓN DE ARCHIVOS TEMPORALES"
audit_log "========================================"
TEMP_PATTERNS=("*.tmp" "*.temp" "*~" "*.bak" "*.swp" "core")
for pattern in "${TEMP_PATTERNS[@]}"; do
temp_files=$(find "$AUDIT_DIR" -name "$pattern" -type f 2>/dev/null | wc -l)
if [[ $temp_files -gt 0 ]]; then
total_size=$(find "$AUDIT_DIR" -name "$pattern" -type f -exec stat -c%s {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
audit_log " $pattern: $temp_files archivos ($(( total_size / 1024 ))KB)"
fi
done
audit_log ""
# 5. ENLACES SIMBÓLICOS
audit_log "🔗 5. VERIFICACIÓN DE ENLACES SIMBÓLICOS"
audit_log "======================================="
# Enlaces rotos
BROKEN_LINKS=$(find "$AUDIT_DIR" -type l \! -exec test -e {} \; -print 2>/dev/null)
if [[ -n "$BROKEN_LINKS" ]]; then
audit_log "⚠️ ADVERTENCIA: Enlaces simbólicos rotos:"
echo "$BROKEN_LINKS" | head -10 | while read link; do
target=$(readlink "$link")
audit_log " $link -> $target (no existe)"
done
else
audit_log "✅ Todos los enlaces simbólicos son válidos"
fi
audit_log ""
# Enlaces que apuntan fuera del directorio auditado
EXTERNAL_LINKS=$(find "$AUDIT_DIR" -type l -exec readlink {} \; | grep "^/" | grep -v "^$(realpath "$AUDIT_DIR")" 2>/dev/null | wc -l)
if [[ $EXTERNAL_LINKS -gt 0 ]]; then
audit_log "ℹ️ INFO: $EXTERNAL_LINKS enlaces apuntan fuera del directorio auditado"
else
audit_log "✅ Todos los enlaces son internos"
fi
audit_log ""
# 6. RESUMEN FINAL
audit_log "📊 6. RESUMEN DE AUDITORÍA"
audit_log "========================"
total_files=$(find "$AUDIT_DIR" -type f 2>/dev/null | wc -l)
total_dirs=$(find "$AUDIT_DIR" -type d 2>/dev/null | wc -l)
total_links=$(find "$AUDIT_DIR" -type l 2>/dev/null | wc -l)
audit_log "Total de archivos: $total_files"
audit_log "Total de directorios: $total_dirs"
audit_log "Total de enlaces: $total_links"
# Calcular puntuación de seguridad (simple)
security_score=100
[[ -n "$WORLD_WRITABLE" ]] && security_score=$((security_score - 20))
[[ -n "$SUID_FILES" ]] && security_score=$((security_score - 15))
[[ -n "$NO_OWNER" ]] && security_score=$((security_score - 10))
[[ -n "$NO_GROUP" ]] && security_score=$((security_score - 5))
[[ -n "$BROKEN_LINKS" ]] && security_score=$((security_score - 5))
audit_log ""
if [[ $security_score -ge 80 ]]; then
audit_log "🟢 PUNTUACIÓN DE SEGURIDAD: $security_score/100 (BUENA)"
elif [[ $security_score -ge 60 ]]; then
audit_log "🟡 PUNTUACIÓN DE SEGURIDAD: $security_score/100 (MEDIA)"
else
audit_log "🔴 PUNTUACIÓN DE SEGURIDAD: $security_score/100 (BAJA)"
fi
audit_log ""
audit_log "📄 Reporte completo guardado en: $REPORT_FILE"
# Mostrar resumen en pantalla
echo
echo "🔒 AUDITORÍA COMPLETADA"
echo "Puntuación de seguridad: $security_score/100"
echo "Reporte guardado en: $REPORT_FILE"
Ejercicio Práctico Final
Proyecto: Sistema Integral de Gestión de Directorios
Crea un sistema completo que integre todas las técnicas aprendidas:
#!/bin/bash
# directory_manager.sh - Sistema integral de gestión de directorios
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/dir_manager.conf"
LOG_FILE="$SCRIPT_DIR/logs/directory_manager.log"
# Crear directorio de logs
mkdir -p "$SCRIPT_DIR/logs"
# Configuración por defecto
DEFAULT_BACKUP_DIR="/backup"
DEFAULT_SYNC_OPTIONS="-av --progress"
DEFAULT_SECURITY_LEVEL="medium"
# Cargar configuración
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
fi
# Función de ayuda
show_help() {
cat << EOF
Directory Manager - Sistema integral de gestión de directorios
Uso: $0 [comando] [opciones]
Comandos disponibles:
create - Crear estructura de proyecto
sync - Sincronizar directorios
analyze - Análizar uso del espacio
audit - Auditoría de seguridad
backup - Crear respaldo
monitor - Monitorear cambios
cleanup - Limpiar archivos temporales
status - Estado del sistema
Tipos de proyecto para 'create':
web, api, desktop, mobile, data, docs
Ejemplos:
$0 create mi-proyecto web
$0 sync /home/user/docs /backup/docs
$0 analyze /var/log
$0 audit /opt/aplicacion
Para configuración avanzada, edita: $CONFIG_FILE
EOF
}
# Función de logging
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Comando: create
cmd_create() {
local name="$1"
local type="${2:-web}"
if [[ -z "$name" ]]; then
echo "Error: Especifica el nombre del proyecto"
exit 1
fi
log_message "Creando proyecto: $name (tipo: $type)"
# Usar el script create_project_structure.sh si existe
if [[ -x "$SCRIPT_DIR/create_project_structure.sh" ]]; then
"$SCRIPT_DIR/create_project_structure.sh" "$name" "$type"
else
# Implementación básica
mkdir -p "$name"/{src,docs,tests,config}
chmod 755 "$name"
log_message "Estructura básica creada para $name"
fi
}
# Comando: sync
cmd_sync() {
local source="$1"
local target="$2"
if [[ -z "$source" || -z "$target" ]]; then
echo "Error: Especifica directorio origen y destino"
exit 1
fi
log_message "Sincronizando $source -> $target"
# Usar advanced_sync.sh si existe
if [[ -x "$SCRIPT_DIR/advanced_sync.sh" ]]; then
"$SCRIPT_DIR/advanced_sync.sh" "$source" "$target"
else
# Sincronización básica
rsync -av --progress "$source/" "$target/"
fi
}
# Comando: analyze
cmd_analyze() {
local directory="${1:-.}"
log_message "Analizando uso del espacio: $directory"
if [[ -x "$SCRIPT_DIR/disk_analyzer.sh" ]]; then
"$SCRIPT_DIR/disk_analyzer.sh" "$directory"
else
echo "📊 Análisis básico de $directory:"
du -sh "$directory"/* 2>/dev/null | sort -hr | head -10
fi
}
# Comando: audit
cmd_audit() {
local directory="${1:-.}"
log_message "Auditando seguridad: $directory"
if [[ -x "$SCRIPT_DIR/security_audit.sh" ]]; then
"$SCRIPT_DIR/security_audit.sh" "$directory"
else
echo "🔒 Auditoría básica de seguridad:"
find "$directory" -type f -perm -002 2>/dev/null | head -5
fi
}
# Comando: backup
cmd_backup() {
local directory="$1"
local backup_name="backup_$(basename "$directory")_$(date +%Y%m%d_%H%M%S)"
local backup_path="$DEFAULT_BACKUP_DIR/$backup_name"
if [[ -z "$directory" ]]; then
echo "Error: Especifica el directorio a respaldar"
exit 1
fi
log_message "Creando respaldo: $directory -> $backup_path"
mkdir -p "$DEFAULT_BACKUP_DIR"
tar -czf "$backup_path.tar.gz" -C "$(dirname "$directory")" "$(basename "$directory")" 2>/dev/null
if [[ $? -eq 0 ]]; then
log_message "Respaldo creado exitosamente: $backup_path.tar.gz"
echo "✅ Respaldo guardado en: $backup_path.tar.gz"
else
log_message "Error al crear respaldo"
echo "❌ Error al crear respaldo"
exit 1
fi
}
# Comando: monitor
cmd_monitor() {
local directory="${1:-.}"
log_message "Iniciando monitoreo de: $directory"
if command -v inotifywait >/dev/null 2>&1; then
echo "👁️ Monitoreando cambios en $directory (Ctrl+C para detener)"
inotifywait -m -r -e create,delete,modify,move "$directory" 2>/dev/null | \
while read path event file; do
log_message "EVENTO: $event en $path$file"
echo "[$(date '+%H:%M:%S')] $event: $path$file"
done
else
echo "⚠️ inotify-tools no está instalado. Monitoreando básico..."
echo "Para monitoreo avanzado instala: sudo apt-get install inotify-tools"
# Monitoreo básico con watch
watch -n 5 "find '$directory' -newer '$LOG_FILE' 2>/dev/null | head -10"
fi
}
# Comando: cleanup
cmd_cleanup() {
local directory="${1:-.}"
local temp_patterns=("*.tmp" "*.temp" "*~" "*.bak" ".DS_Store" "Thumbs.db")
log_message "Limpiando archivos temporales en: $directory"
echo "🧹 Limpiando archivos temporales..."
local total_removed=0
local total_size=0
for pattern in "${temp_patterns[@]}"; do
files_found=$(find "$directory" -name "$pattern" -type f 2>/dev/null)
if [[ -n "$files_found" ]]; then
count=$(echo "$files_found" | wc -l)
size=$(echo "$files_found" | xargs stat -c%s 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
echo "$files_found" | xargs rm -f 2>/dev/null
echo " Removidos: $count archivos $pattern ($(( size / 1024 ))KB)"
total_removed=$((total_removed + count))
total_size=$((total_size + size))
fi
done
if [[ $total_removed -gt 0 ]]; then
log_message "Limpieza completada: $total_removed archivos, $(( total_size / 1024 ))KB liberados"
echo "✅ Limpieza completada: $total_removed archivos removidos"
else
echo "✨ No se encontraron archivos temporales"
fi
}
# Comando: status
cmd_status() {
echo "📊 ESTADO DEL SISTEMA DE GESTIÓN DE DIRECTORIOS"
echo "=============================================="
echo
echo "📁 Configuración:"
echo " Directorio de trabajo: $SCRIPT_DIR"
echo " Archivo de configuración: $CONFIG_FILE"
echo " Log: $LOG_FILE"
echo " Directorio de respaldos: $DEFAULT_BACKUP_DIR"
echo
echo "🔧 Herramientas disponibles:"
tools=("rsync" "tree" "inotifywait" "setfacl" "getfacl")
for tool in "${tools[@]}"; do
if command -v "$tool" >/dev/null 2>&1; then
echo " ✅ $tool"
else
echo " ❌ $tool (no instalado)"
fi
done
echo
echo "📊 Estadísticas de logs:"
if [[ -f "$LOG_FILE" ]]; then
line_count=$(wc -l < "$LOG_FILE")
last_entry=$(tail -1 "$LOG_FILE" 2>/dev/null | cut -d']' -f1 | tr -d '[')
echo " Líneas en log: $line_count"
echo " Última entrada: $last_entry"
else
echo " No hay archivo de log"
fi
echo
echo "💾 Espacio en disco:"
df -h . | tail -1 | awk '{printf " Disponible: %s de %s (%s usado)\n", $4, $2, $5}'
}
# Función principal
main() {
case "$1" in
"create")
cmd_create "$2" "$3"
;;
"sync")
cmd_sync "$2" "$3"
;;
"analyze")
cmd_analyze "$2"
;;
"audit")
cmd_audit "$2"
;;
"backup")
cmd_backup "$2"
;;
"monitor")
cmd_monitor "$2"
;;
"cleanup")
cmd_cleanup "$2"
;;
"status")
cmd_status
;;
"help"|"--help"|"-h"|"")
show_help
;;
*)
echo "Comando no reconocido: $1"
echo "Usa '$0 help' para ver comandos disponibles"
exit 1
;;
esac
}
# Ejecutar función principal
main "$@"
Para usar el sistema:
# Hacer executable
chmod +x directory_manager.sh
# Ver ayuda
./directory_manager.sh help
# Crear proyecto
./directory_manager.sh create mi-web-app web
# Sincronizar directorios
./directory_manager.sh sync /home/user/docs /backup/docs
# Analizar uso del espacio
./directory_manager.sh analyze /var/log
# Auditoría de seguridad
./directory_manager.sh audit /opt/aplicacion
# Crear respaldo
./directory_manager.sh backup /home/user/proyecto
# Ver estado del sistema
./directory_manager.sh status