Exercicis Bash 02: Automatització amb SSH

Nota prèvia: Per fer aquests exercicis necessitareu accés a almenys un servidor remot o màquina virtual. Si no en teniu, podeu crear contenidors Docker o VMs amb VirtualBox/QEMU.

Preparatius

Configurar entorn de proves amb Docker (opcional)

# Crear un contenidor SSH per fer proves
docker run -d --name servidor-ssh \
    -p 2222:22 \
    -e PUID=1000 -e PGID=1000 \
    linuxserver/openssh-server

# Obtenir la contrasenya generada
docker logs servidor-ssh 2>&1 | grep "User password"

# Connectar-se
ssh -p 2222 usuari@localhost

Exercici 1: Configuració de claus SSH (20 minuts)

Part A: Generació i configuració bàsica

  1. Genera una clau SSH Ed25519 amb el teu email
  2. Copia la clau al servidor de pràctiques
  3. Comprova que pots connectar sense contrasenya
  4. Crea un fitxer ~/.ssh/config amb alies per al servidor

Tasques específiques

# 1. Generar clau
ssh-keygen -t ed25519 -C "el_teu_email@exemple.cat"

# 2. Copiar al servidor (adapta amb les teves dades)
ssh-copy-id usuari@servidor.exemple.cat

# 3. Crear configuració
# Editar ~/.ssh/config i afegir:
Host practica
    HostName servidor.exemple.cat
    User usuari
    Port 22
    IdentityFile ~/.ssh/id_ed25519

# 4. Provar
ssh practica "echo 'Funciona!'"

Part B: Script de verificació

Crea un script verificar_ssh.sh que:

Exemple de sortida

=== Verificació de configuració SSH ===

Comprovant clau privada...
✓ Clau privada trobada: /home/usuari/.ssh/id_ed25519
✓ Permisos correctes: 600

Comprovant clau pública...
✓ Clau pública trobada: /home/usuari/.ssh/id_ed25519.pub
✓ Permisos correctes: 644

Provant connexió a practica...
✓ Connexió SSH funciona correctament
Servidor: servidor.exemple.cat
Hostname remot: ubuntu-server

=== Configuració OK ===

Exercici 2: Monitor remot de servidors (40 minuts)

Crea un script monitor.sh que reculli informació de diversos servidors.

Requisits

  1. El script ha de rebre una llista de servidors com a paràmetres

  2. Per cada servidor, ha de recollir:

    • Hostname
    • Uptime
    • Càrrega del sistema (load average)
    • Memòria usada/disponible
    • Disc usat/disponible al sistema root (/)
    • Nombre de processos en execució
    • Temperatura CPU (si està disponible)
  3. Mostrar la informació en format taula

  4. Guardar un log amb timestamp

  5. Alertar si:

    • Càrrega > 2.0
    • Memòria disponible < 20%
    • Disc disponible < 20%

Exemple d'execució

./monitor.sh practica servidor2 servidor3

=== Monitor de Servidors - 2024-01-08 15:30:45 ===

┌────────────────┬─────────────────┬──────────┬──────────────┬──────────────┬────────────┐
│ Servidor       │ Hostname        │ Uptime   │ Load Avg     │ Memòria      │ Disc       │
├────────────────┼─────────────────┼──────────┼──────────────┼──────────────┼────────────┤
│ practica      │ ubuntu-01       │ 15 dies  │ 0.25 [OK]    │ 2.1G/4G [OK] │ 45G/100G   │
│ servidor2      │ debian-web      │ 3 dies   │ 1.85 [OK]    │ 7.5G/8G [⚠]  │ 180G/200G  │
│ servidor3      │ centos-db       │ 45 dies  │ 3.24 [⚠⚠]    │ 14G/16G [OK] │ 890G/1T    │
└────────────────┴─────────────────┴──────────┴──────────────┴──────────────┴────────────┘

⚠ ALERTES:
  - servidor2: Memòria disponible baixa (6%)
  - servidor3: Càrrega alta (3.24)

Log guardat a: /var/log/monitor_20240108_153045.log

Ajuda

#!/bin/bash

# Colors per a l'output
VERMELL='\033[0;31m'
GROC='\033[1;33m'
VERD='\033[0;32m'
NC='\033[0m' # No Color

obtenir_info_servidor() {
    local servidor=$1
    
    # Executar comandes al servidor i capturar resultat
    ssh -o ConnectTimeout=5 "$servidor" << 'EOF'
        echo "HOSTNAME:$(hostname)"
        echo "UPTIME:$(uptime -p | sed 's/up //')"
        echo "LOAD:$(cat /proc/loadavg | awk '{print $1}')"
        echo "MEMORIA_USADA:$(free -g | grep Mem | awk '{print $3}')"
        echo "MEMORIA_TOTAL:$(free -g | grep Mem | awk '{print $2}')"
        echo "DISC_USAT:$(df -h / | tail -1 | awk '{print $3}')"
        echo "DISC_TOTAL:$(df -h / | tail -1 | awk '{print $2}')"
        echo "PROCESSOS:$(ps aux | wc -l)"
EOF
}

# Processar la informació i detectar alertes
processar_servidor() {
    local servidor=$1
    local info=$(obtenir_info_servidor "$servidor")
    
    # Parsejar les dades
    local hostname=$(echo "$info" | grep HOSTNAME | cut -d: -f2)
    local load=$(echo "$info" | grep "^LOAD:" | cut -d: -f2)
    
    # Comprovar alertes
    if (( $(echo "$load > 2.0" | bc -l) )); then
        echo "⚠ $servidor: Càrrega alta ($load)"
    fi
}

Bonus: Afegir opció per enviar les alertes per email o webhook.


Exercici 3: Sincronitzador amb sshFS (40 minuts)

Crea un script sincronitzador.sh que munta un directori remot, sincronitza fitxers, i desmunta.

Requisits

  1. El script ha de acceptar:

    • Servidor remot
    • Directori remot
    • Directori local
    • Acció: pujar (local → remot), baixar (remot → local), sync (bidireccional)
  2. Funcionalitat:

    • Muntar el sistema remot amb sshFS
    • Fer la sincronització amb rsync
    • Mostrar resum de canvis
    • Desmuntar el sistema
    • Gestionar errors (connexió, muntatge, permisos)
  3. Opcions addicionals:

    • --dry-run: Mostrar què es faria sense fer-ho
    • --delete: Eliminar fitxers que no existeixen a l'origen
    • --exclude: Excloure patrons de fitxers

Exemple d'execució

# Pujar fitxers locals al servidor
./sincronitzador.sh pujar practica:/var/www/html ./web-local

=== Sincronitzador de fitxers ===
Servidor: practica
Directori remot: /var/www/html
Directori local: ./web-local
Acció: PUJAR (local → remot)

[1/4] Verificant connexió...
✓ Connexió SSH OK

[2/4] Muntant sistema remot...
✓ Muntat a /tmp/sshfs_mount_12345

[3/4] Sincronitzant fitxers...
Enviant: index.html (15 KB)
Enviant: style.css (3 KB)
Enviant: img/logo.png (45 KB)
Actualitzant: script.js (8 KB)
✓ 4 fitxers processats (71 KB transferits)

[4/4] Desmuntant sistema remot...
✓ Desmuntat correctament

=== Sincronització completada ===
Duració: 2.3 segons

Estructura del script

#!/bin/bash

PUNT_MUNTATGE="/tmp/sshfs_mount_$$"
DRY_RUN=false
DELETE=false
EXCLUDE_PATTERNS=()

muntar_remot() {
    local servidor=$1
    local directori_remot=$2
    
    echo "[2/4] Muntant sistema remot..."
    mkdir -p "$PUNT_MUNTATGE"
    
    sshfs "$servidor:$directori_remot" "$PUNT_MUNTATGE" \
        -o reconnect,ServerAliveInterval=15,ConnectTimeout=10
    
    if [ $? -eq 0 ]; then
        echo "✓ Muntat a $PUNT_MUNTATGE"
        return 0
    else
        echo "✗ Error muntant el sistema remot"
        return 1
    fi
}

desmuntar_remot() {
    echo "[4/4] Desmuntant sistema remot..."
    
    if mountpoint -q "$PUNT_MUNTATGE"; then
        fusermount -u "$PUNT_MUNTATGE" 2>/dev/null || fusermount -uz "$PUNT_MUNTATGE"
        rmdir "$PUNT_MUNTATGE"
        echo "✓ Desmuntat correctament"
    fi
}

sincronitzar() {
    local origen=$1
    local desti=$2
    
    echo "[3/4] Sincronitzant fitxers..."
    
    # Construir comanda rsync
    local rsync_cmd="rsync -avh --progress"
    
    if [ "$DRY_RUN" = true ]; then
        rsync_cmd="$rsync_cmd --dry-run"
    fi
    
    if [ "$DELETE" = true ]; then
        rsync_cmd="$rsync_cmd --delete"
    fi
    
    for pattern in "${EXCLUDE_PATTERNS[@]}"; do
        rsync_cmd="$rsync_cmd --exclude='$pattern'"
    done
    
    # Executar sincronització
    eval $rsync_cmd "$origen/" "$desti/"
    
    return $?
}

# Cleanup al sortir
cleanup() {
    desmuntar_remot
}
trap cleanup EXIT

# Programa principal
main() {
    # Parsejar arguments
    # ...
    
    # Verificar connexió
    echo "[1/4] Verificant connexió..."
    # ...
    
    # Muntar
    muntar_remot "$servidor" "$directori_remot" || exit 1
    
    # Sincronitzar segons l'acció
    case "$accio" in
        pujar)
            sincronitzar "$directori_local" "$PUNT_MUNTATGE"
            ;;
        baixar)
            sincronitzar "$PUNT_MUNTATGE" "$directori_local"
            ;;
        sync)
            # Implementar sincronització bidireccional
            ;;
    esac
}

main "$@"

Exercici extra: Desplegament paral·lel

Crea un script que executi una comanda en diversos servidors simultàniament (en paral·lel).

Requisits

./desplegament_parallel.sh servidors.txt "sudo apt update && sudo apt upgrade -y"

=== Executant en 5 servidors ===

[web1    ] ⟳ Executant...
[web2    ] ⟳ Executant...
[db1     ] ⟳ Executant...
[db2     ] ⟳ Executant...
[cache   ] ⟳ Executant...

[cache   ] ✓ Completat (45s)
[web2    ] ✓ Completat (52s)
[db1     ] ✓ Completat (67s)
[web1    ] ✗ Error: connexió perduda (32s)
[db2     ] ✓ Completat (89s)

=== Resum ===
Èxit: 4/5
Errors: 1/5
Temps total: 89s

Pista

Usa & per executar en segon pla i wait per esperar que tots acabin:

for servidor in "${SERVIDORS[@]}"; do
    (
        ssh "$servidor" "$COMANDA"
        echo $? > "/tmp/resultat_$servidor"
    ) &
done

wait  # Esperar que tots acabin

Criteris d'avaluació