Autor: ciberkaos

  • R3.2 [Solución] Programación-Bucles

    R3.2 [Solución] Programación-Bucles

    Walter White y Jesse Pinkman han cocinado 1000 pastillas de «mentaanfetamienta» en su caravana.

    Cada pastilla tiene una calidad aleatoria entre 0 y 100.

    El “señor del pollo” (Gus Fring) solo acepta aquellas con calidad mayor o igual que 90.

    Base común: generar calidad 0–100

    Usaremos:

    
    
    
    
    
    Random r = new Random(); int calidad = r.nextInt(101); // 0..100 (incluye 100)

    RETO 1: “El recuento del lote”

    Calcular cuántas pastillas tienen una calidad superior a 90.

    Pistas:

    • Usa Random para generar números del 0 al 100.
    • Usa un for para simular las 1000 pastillas.
    • Usa un contador para las “buenas”.

    Ejemplo de salida:

    Pastillas totales: 1000
    De calidad superior: 128

    Objetivo: de 1000 pastillas, contar cuántas tienen calidad > 90 (ojo: tu historia dice “≥90”, pero el reto 1 pide “superior a 90” → >90).

    Idea

    • Bucle for de 1 a 1000
    • Generar calidad
    • Si calidad > 90, incrementamos contador

    Código

    
    
    
    
    
    import java.util.Random;
    
    public class Reto1RecuentoLote {
        public static void main(String[] args) {
            Random r = new Random();
    
            int total = 1000;
            int buenas = 0;
    
            for (int i = 1; i <= total; i++) {
                int calidad = r.nextInt(101); // 0..100
    
                if (calidad > 90) {           // superior a 90
                    buenas++;
                }
            }
    
            System.out.println("Pastillas totales: " + total);
            System.out.println("De calidad superior: " + buenas);
        }
    }
    

    RETO 2: “Hasta lograr la receta perfecta”

    Walter repite la cocción hasta que consiga una pastilla con calidad 100.

    Pistas:

    • Genera números aleatorios entre 0 y 100.
    • Detén el bucle cuando salga 100.
    • Muestra cuántos intentos necesitó.

    Ejemplo:

    ¡Perfecta! Calidad 100 obtenida tras 57 intentos.

    Objetivo: repetir intentos hasta que salga calidad 100, mostrar cuántos intentos.

    Idea

    • Bucle while o do-while
    • Contador de intentos
    • Se para cuando calidad == 100

    Código

    
    
    
    
    
    import java.util.Random;
    
    public class Reto2RecetaPerfecta {
        public static void main(String[] args) {
            Random r = new Random();
    
            int intentos = 0;
            int calidad;
    
            do {
                calidad = r.nextInt(101);
                intentos++;
            } while (calidad != 100);
    
            System.out.println("¡Perfecta! Calidad 100 obtenida tras " + intentos + " intentos.");
        }
    }
    

    Por qué do-while: garantiza al menos un intento (tiene sentido aquí).


    RETO 3: “La producción nocturna”

    Walter y Jesse producen pastillas hasta llegar a 1000 unidades buenas (≥90).

    Muestra cuántas totales han hecho (incluyendo las malas).

    Ejemplo:

    Para conseguir 1000 pastillas buenas, produjeron un total de 8732.
    
    

    Objetivo: producir hasta conseguir 1000 buenas (≥90), y mostrar cuántas totales se produjeron.

    Idea

    • buenas llega a 1000
    • totales cuenta todas, buenas y malas
    • Condición buena: calidad >= 90

    Código

    
    
    
    
    
    import java.util.Random;
    
    public class Reto3ProduccionNocturna {
        public static void main(String[] args) {
            Random r = new Random();
    
            int buenas = 0;
            int totales = 0;
    
            while (buenas < 1000) {
                int calidad = r.nextInt(101);
                totales++;
    
                if (calidad >= 90) {
                    buenas++;
                }
            }
    
            System.out.println("Para conseguir 1000 pastillas buenas, produjeron un total de " + totales + ".");
        }
    }
    

    RETO 4: “El análisis por lotes”

    Dividir la producción en 10 lotes de 100 pastillas y mostrar cuántas buenas hay en cada lote.

    Salida esperada:

    Lote 1 → 13 pastillas buenas
    Lote 2 → 8 pastillas buenas
    ...
    Lote 10 → 11 pastillas buenas
    
    

    Objetivo: 10 lotes de 100, contar buenas (≥90) por lote.

    Idea

    • Bucle externo: lotes 1..10
    • Bucle interno: 100 pastillas
    • Contador buenasLote reiniciado en cada lote

    Código

    
    
    
    
    
    import java.util.Random;
    
    public class Reto4AnalisisPorLotes {
        public static void main(String[] args) {
            Random r = new Random();
    
            int lotes = 10;
            int tamLote = 100;
    
            for (int lote = 1; lote <= lotes; lote++) {
                int buenasLote = 0;
    
                for (int i = 1; i <= tamLote; i++) {
                    int calidad = r.nextInt(101);
                    if (calidad >= 90) {
                        buenasLote++;
                    }
                }
    
                System.out.println("Lote " + lote + " \u2192 " + buenasLote + " pastillas buenas");
            }
        }
    }
    

    RETO 5: “Promedio de calidad”

    Calcular el promedio total de calidad de las 1000 pastillas.

    Salida:

    Promedio de calidad general: 72.38
    
    

    Objetivo: promedio de calidad de 1000 pastillas.

    Idea

    • Acumulador sumaCalidades
    • Tras el bucle: promedio = suma / total
    • Para mostrar con 2 decimales: System.out.printf

    Código

    
    
    
    
    
    import java.util.Random;
    
    public class Reto5PromedioCalidad {
        public static void main(String[] args) {
            Random r = new Random();
    
            int total = 1000;
            int sumaCalidades = 0;
    
            for (int i = 1; i <= total; i++) {
                int calidad = r.nextInt(101);
                sumaCalidades += calidad;
            }
    
            double promedio = (double) sumaCalidades / total;
    
            System.out.printf("Promedio de calidad general: %.2f%n", promedio);
        }
    }
    

    Detalle clave: el casteo a double evita división entera.

    RETO 6 (extra): “La inspección de Gus Fring”

    Genera pastillas hasta tener 500 buenas, pero cada vez que salgan 50 malas seguidas, muestra:

    🔥 Gus Fring sospecha del laboratorio...
    
    

    Objetivo: generar pastillas hasta tener 500 buenas (≥90), pero cada vez que haya 50 malas seguidas, imprimir:

    Gus Fring sospecha del laboratorio...

    Idea

    • Contador buenas hasta 500
    • Contador malasSeguidas que:
      • aumenta si sale mala (<90)
      • se reinicia a 0 si sale buena
    • Cuando malasSeguidas == 50, avisamos y reiniciamos (o seguimos contando, tú eliges; aquí reiniciamos para no spamear).

    Código

    import java.util.Random;
    
    public class Reto6InspeccionGusFring {
        public static void main(String[] args) {
            Random r = new Random();
    
            int buenas = 0;
            int totales = 0;
            int malasSeguidas = 0;
    
            while (buenas < 500) {
                int calidad = r.nextInt(101);
                totales++;
    
                if (calidad >= 90) {
                    buenas++;
                    malasSeguidas = 0; // racha de malas se rompe
                } else {
                    malasSeguidas++;
                }
    
                if (malasSeguidas == 50) {
                    System.out.println("🔥 Gus Fring sospecha del laboratorio...");
                    malasSeguidas = 0; // reiniciamos para volver a detectar otra racha de 50
                }
            }
    
            System.out.println("Buenas conseguidas: " + buenas);
            System.out.println("Pastillas producidas en total: " + totales);
        }
    }
    
    
  • R3.3 [Solución]- Arrays – Bienvenido al mundo de Mr. Robot

    R3.3 [Solución]- Arrays – Bienvenido al mundo de Mr. Robot

    Evil Corp —el gigante que controla todo lo que consumes, lo que piensas y hasta lo que olvidas— cree tenerlo todo bajo control.

    Pero no contaba contigo.

    En un sótano lleno de cables, pantallas parpadeantes y tazas de café frías, un grupo de hackers conocidos como Atriumsociety prepara su próximo golpe digital. Su misión: devolver el poder a la gente, línea de código a línea de código.

    Tu papel comienza aquí.

    Eres parte del equipo. Hoy no vienes a “hacer ejercicios”, vienes a infiltrarte en el sistema, Cada array que declares es una base de datos secreta, cada bucle un intento de intrusión, cada condicional una decisión que puede cambiarlo todo.

    Prepárate: el prompt está parpadeando.

    Atriumsociety te necesita.

    1. “Elliot vs Evil Corp”

    Enunciado:

    Elliot ha interceptado una lista con los balances de Evil Corp.

    Con el siguiente array:

    int[] balances = {12000, -50, 5000, 15000, 0, -300, 800, 22000, 9999, 100};
    
    

    Muestra:

    • Cuántas cuentas tienen saldo negativo.
    • Cuántas tienen saldo superior a 10 000 $.
    • El saldo medio.

    Qué se hace

    • Recorremos balances
    • Contamos negativos (<0)
    • Contamos los que superan 10.000 (>10000)
    • Sumamos todo para el promedio

    Código

    public class ElliotVsEvilCorp {
        public static void main(String[] args) {
    
            int[] balances = {12000, -50, 5000, 15000, 0, -300, 800, 22000, 9999, 100};
    
            int negativos = 0;
            int masDe10000 = 0;
            int suma = 0;
    
            for (int i = 0; i < balances.length; i++) {
                int b = balances[i];
    
                if (b < 0) negativos++;
                if (b > 10000) masDe10000++;
    
                suma += b;
            }
    
            double media = (double) suma / balances.length;
    
            System.out.println("Cuentas con saldo negativo: " + negativos);
            System.out.println("Cuentas con saldo superior a 10000$: " + masDe10000);
            System.out.printf("Saldo medio: %.2f%n", media);
        }
    }
    

    2. “Backdoor Scanner”

    Enunciado:

    Darlene analiza si los servidores de Evil Corp están vulnerables.

    Usa el siguiente array:

    boolean[] vulnerables = {false, true, false, false, true, false, true, false};
    
    

    Muestra:

    • Cuántos servidores son vulnerables (true).
    • En qué posiciones están.

    Qué se hace

    • Recorremos el array de boolean
    • Si es true, contamos y mostramos la posición

    Código

    
    
    
    
    
    public class BackdoorScanner {
        public static void main(String[] args) {
    
            boolean[] vulnerables = {false, true, false, false, true, false, true, false};
    
            int contador = 0;
    
            System.out.print("Servidores vulnerables en posiciones: ");
            for (int i = 0; i < vulnerables.length; i++) {
                if (vulnerables[i]) {
                    contador++;
                    System.out.print(i + " ");
                }
            }
    
            System.out.println();
            System.out.println("Total vulnerables: " + contador);
        }
    }
    


    3. “Password Audit”

    Enunciado:

    Elliot encuentra las siguientes contraseñas antiguas de Evil Corp:

    String[] passwords = {"admin123", "e@mpl3", "supersecure99", "pass", "root@2020"};
    
    

    Indica:

    • Cuántas contienen el carácter @.
    • Cuántas tienen más de 8 caracteres.
    • Cuántas terminan en un número.
    • Cuál es la más larga.

    Qué se hace

    Para cada contraseña:

    • contains("@") → cuenta las que tienen @
    • length() > 8 → largas
    • “termina en número” → miramos el último carácter con charAt y comprobamos si es dígito
    • “la más larga” → guardamos la que tenga mayor longitud

    Código

    
    
    
    
    
    public class PasswordAudit {
        public static void main(String[] args) {
    
            String[] passwords = {"admin123", "e@mpl3", "supersecure99", "pass", "root@2020"};
    
            int conArroba = 0;
            int masDe8 = 0;
            int terminanEnNumero = 0;
    
            String masLarga = passwords[0];
    
            for (int i = 0; i < passwords.length; i++) {
                String p = passwords[i];
    
                if (p.contains("@")) conArroba++;
                if (p.length() > 8) masDe8++;
    
                char ultimo = p.charAt(p.length() - 1);
                if (Character.isDigit(ultimo)) terminanEnNumero++;
    
                if (p.length() > masLarga.length()) {
                    masLarga = p;
                }
            }
    
            System.out.println("Contraseñas con @: " + conArroba);
            System.out.println("Contraseñas con más de 8 caracteres: " + masDe8);
            System.out.println("Contraseñas que terminan en número: " + terminanEnNumero);
            System.out.println("La más larga es: " + masLarga + " (" + masLarga.length() + " caracteres)");
        }
    }
    


    4. “Hack the Gibson”

    Enunciado:

    Simula los niveles de éxito de los ataques de Elliot con el siguiente array:

    int[] intentos = {82, 13, 45, 79, 90, 5, 33, 72, 18, 65, 40, 100, 29, 10, 67, 55, 88, 60, 14, 3};
    
    

    Muestra:

    • El valor máximo y el mínimo.
    • Cuántos intentos fueron “exitosos” (más de 70).
    • Si todos son menores de 30, muestra “Mr Robot sospecha que estás desconectado”.

    Qué se hace

    • Máximo y mínimo: inicializamos con el primer elemento y comparamos
    • Exitosos: >70
    • “si todos son menores de 30”: bandera todosMenor30 (true al inicio, se rompe si encontramos uno >= 30)

    Código

    
    
    
    
    
    public class HackTheGibson {
        public static void main(String[] args) {
    
            int[] intentos = {82, 13, 45, 79, 90, 5, 33, 72, 18, 65, 40, 100, 29, 10, 67, 55, 88, 60, 14, 3};
    
            int max = intentos[0];
            int min = intentos[0];
            int exitosos = 0;
    
            boolean todosMenor30 = true;
    
            for (int i = 0; i < intentos.length; i++) {
                int v = intentos[i];
    
                if (v > max) max = v;
                if (v < min) min = v;
    
                if (v > 70) exitosos++;
    
                if (v >= 30) {
                    todosMenor30 = false;
                }
            }
    
            System.out.println("Máximo: " + max);
            System.out.println("Mínimo: " + min);
            System.out.println("Intentos exitosos (>70): " + exitosos);
    
            if (todosMenor30) {
                System.out.println("Mr Robot sospecha que estás desconectado");
            }
        }
    }
    


    5. “Logs del Servidor”

    Enunciado:

    Angela revisa los registros de acceso de un servidor:

    String[] logs = {"OK", "ERROR", "OK", "OK", "ERROR", "OK", "ERROR", "ERROR", "OK", "OK"};
    
    

    Cuenta:

    • Cuántos accesos fueron "OK".
    • Cuántos "ERROR".
    • Si hay más errores que accesos correctos, muestra “Servidor en peligro”.

    Qué se hace

    • Contar "OK" y "ERROR" usando equals
    • Comparar: si errores > ok → aviso

    Código

    
    
    
    
    
    public class LogsDelServidor {
        public static void main(String[] args) {
    
            String[] logs = {"OK", "ERROR", "OK", "OK", "ERROR", "OK", "ERROR", "ERROR", "OK", "OK"};
    
            int ok = 0;
            int error = 0;
    
            for (int i = 0; i < logs.length; i++) {
                if (logs[i].equals("OK")) ok++;
                else if (logs[i].equals("ERROR")) error++;
            }
    
            System.out.println("OK: " + ok);
            System.out.println("ERROR: " + error);
    
            if (error > ok) {
                System.out.println("Servidor en peligro");
            }
        }
    }
    


    6. “Temperaturas del Servidor”

    Enunciado:

    Durante un ataque, Elliot monitoriza las temperaturas del servidor:

    int[] temperaturas = {45, 49, 52, 57, 60, 59, 55, 48, 46, 50};
    
    

    Calcula:

    • La temperatura media.
    • Cuántas mediciones superan los 55 °C.
    • Si todas las temperaturas están por debajo de 60 °C, muestra “Sistema estable”; si alguna es 60 o más, muestra “¡Sobrecalentamiento detectado!”.

    Qué se hace

    • Media: suma / total
    • Contar >55
    • Comprobar si alguna es >=60 (bandera sobrecalentamiento)

    Código

    
    
    
    
    
    public class TemperaturasServidor {
        public static void main(String[] args) {
    
            int[] temperaturas = {45, 49, 52, 57, 60, 59, 55, 48, 46, 50};
    
            int suma = 0;
            int superan55 = 0;
    
            boolean sobrecalentamiento = false;
    
            for (int i = 0; i < temperaturas.length; i++) {
                int t = temperaturas[i];
    
                suma += t;
    
                if (t > 55) superan55++;
                if (t >= 60) sobrecalentamiento = true;
            }
    
            double media = (double) suma / temperaturas.length;
    
            System.out.printf("Temperatura media: %.2f%n", media);
            System.out.println("Mediciones que superan 55°C: " + superan55);
    
            if (!sobrecalentamiento) {
                System.out.println("Sistema estable");
            } else {
                System.out.println("¡Sobrecalentamiento detectado!");
            }
        }
    }
    


    7. “DDoS Simulator”

    Enunciado:

    Durante un ataque DDoS, se registran los siguientes tiempos de respuesta (en ms):

    int[] tiempos = {200, 540, 720, 150, 950, 330, 480, 510, 870, 610};
    
    

    Muestra:

    • La media, el máximo y el mínimo.
    • Si más del 60 % supera los 500 ms, muestra “Servidor saturado”.
    • Si menos del 10 % supera los 200 ms, muestra “Ataque fallido”.

    Qué se hace

    • Media, máximo, mínimo (igual que antes)
    • Contar cuántos superan 500 → para porcentaje
    • Si (superan500 / total) > 0.60 → “Servidor saturado”
    • Si (superan200 / total) < 0.10 → “Ataque fallido”
      • Nota: “supera 200” significa >200, no >=200.

    Código

    
    
    
    
    
    public class DDoSSimulator {
        public static void main(String[] args) {
    
            int[] tiempos = {200, 540, 720, 150, 950, 330, 480, 510, 870, 610};
    
            int suma = 0;
            int max = tiempos[0];
            int min = tiempos[0];
    
            int superan500 = 0;
            int superan200 = 0;
    
            for (int i = 0; i < tiempos.length; i++) {
                int t = tiempos[i];
    
                suma += t;
                if (t > max) max = t;
                if (t < min) min = t;
    
                if (t > 500) superan500++;
                if (t > 200) superan200++;
            }
    
            double media = (double) suma / tiempos.length;
    
            double porcentaje500 = (double) superan500 / tiempos.length;
            double porcentaje200 = (double) superan200 / tiempos.length;
    
            System.out.printf("Media: %.2f ms%n", media);
            System.out.println("Máximo: " + max + " ms");
            System.out.println("Mínimo: " + min + " ms");
    
            if (porcentaje500 > 0.60) {
                System.out.println("Servidor saturado");
            }
    
            if (porcentaje200 < 0.10) {
                System.out.println("Ataque fallido");
            }
        }
    }
    
  • R8 [Solución]- El Escalafón Mágico de Hogwarts

    R8 [Solución]- El Escalafón Mágico de Hogwarts

    El Ministerio de Magia ha implantado un nuevo sistema de clasificación de magos para evaluar su progreso, capacidades y responsabilidades dentro del mundo mágico.

    1) Casa.java (enum)

    La enum sirve para tener un conjunto cerrado de valores (solo esas casas), evitando Strings sueltos.

    
    
    
    
    
    package modelo;
    
    public enum Casa {
        GRYFFINDOR,
        SLYTHERIN,
        RAVENCLAW,
        HUFFLEPUFF
    }
    

    2) Mago.java (clase base)

    Qué aporta esta clase

    • Define lo común a todos: nombre, nivel, vida, mana, casa.
    • Aplica un bonus inicial según la casa.
    • Tiene métodos base (entrenar, descansar, ficha, lanzarHechizo).
    • lanzarHechizo NO es abstracto: por defecto hace algo simple.
    
    
    
    
    
    package modelo;
    
    public class Mago {
    
        protected String nombre;
        protected int nivel; // 1..100
        protected int vida;  // 0..100
        protected int mana;  // 0..100
        protected Casa casa;
    
        public Mago(String nombre, Casa casa) {
            this.nombre = nombre;
            this.casa = casa;
    
            // Valores base
            this.nivel = 1;
            this.vida = 100;
            this.mana = 100;
    
            aplicarBonusCasa();
        }
    
        private void aplicarBonusCasa() {
            // Bonus simples y fáciles de ver en consola
            switch (casa) {
                case GRYFFINDOR:
                    vida += 10; // más resistencia
                    break;
                case SLYTHERIN:
                    mana += 10; // más “energía mágica”
                    break;
                case RAVENCLAW:
                    nivel += 1; // aprende más rápido (nivel inicial superior)
                    break;
                case HUFFLEPUFF:
                    vida += 5;
                    mana += 5; // equilibrio
                    break;
            }
            // Normalizamos límites
            vida = clamp(vida, 0, 100);
            mana = clamp(mana, 0, 100);
            nivel = clamp(nivel, 1, 100);
        }
    
        public void entrenar() {
            // Entrenar sube nivel, pero cansa
            nivel += 1;
            mana -= 5;
            vida -= 2;
    
            nivel = clamp(nivel, 1, 100);
            mana = clamp(mana, 0, 100);
            vida = clamp(vida, 0, 100);
        }
    
        public void descansar() {
            // Descansar recupera recursos
            mana += 10;
            vida += 10;
    
            mana = clamp(mana, 0, 100);
            vida = clamp(vida, 0, 100);
        }
    
        public String ficha() {
            return nombre + " | Casa: " + casa +
                   " | Nivel: " + nivel +
                   " | Vida: " + vida +
                   " | Mana: " + mana;
        }
    
        /**
         * Lanza un hechizo genérico. Las clases hijas lo mejoran.
         * Devuelve el "daño" (o 0 si no se puede).
         */
        public int lanzarHechizo(String hechizo) {
            int coste = 5;
            if (!gastarMana(coste)) return 0;
            return 3; // daño base genérico
        }
    
        protected boolean gastarMana(int cantidad) {
            if (mana < cantidad) {
                return false;
            }
            mana -= cantidad;
            mana = clamp(mana, 0, 100);
            return true;
        }
    
        public void recibirDaño(int daño) {
            vida -= daño;
            vida = clamp(vida, 0, 100);
        }
    
        protected int clamp(int valor, int min, int max) {
            if (valor < min) return min;
            if (valor > max) return max;
            return valor;
        }
    }
    

    3) Aprendiz.java

    Idea clave

    • Un Aprendiz tiene torpeza, así que puede fallar.
    • Aprende con practicarBasico().
    • Sobrescribe lanzarHechizo para permitir solo hechizos básicos.
    
    
    
    
    
    package modelo;
    
    import java.util.Random;
    
    public class Aprendiz extends Mago {
    
        protected int torpeza; // 0..100 (más torpeza = más fallos)
        protected Random rnd = new Random();
    
        public Aprendiz(String nombre, Casa casa) {
            super(nombre, casa);
    
            torpeza = 40;
    
            // Ajuste según casa (sencillo y visible)
            if (casa == Casa.RAVENCLAW) torpeza -= 10;   // más “cabeza”
            if (casa == Casa.HUFFLEPUFF) torpeza -= 5;   // constancia
            if (casa == Casa.SLYTHERIN) torpeza += 5;    // “se la juega más”
            torpeza = clamp(torpeza, 0, 100);
        }
    
        public void practicarBasico() {
            // Practicar reduce torpeza (mejora)
            if (!gastarMana(3)) return;
    
            torpeza -= 2;
            torpeza = clamp(torpeza, 0, 100);
    
            // Practicar también puede subir un poquito el nivel
            if (nivel < 100) nivel += 1;
        }
    
        @Override
        public int lanzarHechizo(String hechizo) {
            // Coste base
            if (!gastarMana(5)) return 0;
    
            // Probabilidad de fallo basada en torpeza
            int tirada = rnd.nextInt(100); // 0..99
            if (tirada < torpeza) {
                // falló
                return 0;
            }
    
            // Hechizos permitidos
            if (hechizo.equalsIgnoreCase("Lumos")) return 5;
            if (hechizo.equalsIgnoreCase("Alohomora")) return 7;
    
            // Si escribe otro, no lo conoce
            return 0;
        }
    
        public int getTorpeza() {
            return torpeza;
        }
    
        public void setTorpeza(int torpeza) {
            this.torpeza = clamp(torpeza, 0, 100);
        }
    }
    

    4) Hechicero.java

    Idea clave

    • Hereda de Aprendiz, pero ahora tiene controlVarita.
    • Puede hacer hechizos más potentes.
    • Los fallos deberían ser menos frecuentes: usamos torpeza pero “rebajada”.
    
    
    
    
    
    package modelo;
    
    import java.util.Random;
    
    public class Hechicero extends Aprendiz {
    
        protected int controlVarita; // 0..100
        protected Random rnd2 = new Random();
    
        public Hechicero(String nombre, Casa casa) {
            super(nombre, casa);
    
            controlVarita = 50;
    
            // Ravenclaw suele destacar en control
            if (casa == Casa.RAVENCLAW) controlVarita += 10;
            if (casa == Casa.GRYFFINDOR) controlVarita += 5;
    
            controlVarita = clamp(controlVarita, 0, 100);
        }
    
        public void estudiarEnBiblioteca() {
            if (!gastarMana(6)) return;
    
            controlVarita += 3;
            controlVarita = clamp(controlVarita, 0, 100);
    
            nivel += 1;
            nivel = clamp(nivel, 1, 100);
        }
    
        @Override
        public int lanzarHechizo(String hechizo) {
            if (!gastarMana(7)) return 0;
    
            // Los Hechiceros fallan menos: torpeza influye menos
            int torpezaEfectiva = clamp(torpeza - (controlVarita / 5), 0, 100);
            int tirada = rnd2.nextInt(100);
            if (tirada < torpezaEfectiva) return 0;
    
            // Hechizos
            if (hechizo.equalsIgnoreCase("Lumos")) return 6;
            if (hechizo.equalsIgnoreCase("Alohomora")) return 8;
            if (hechizo.equalsIgnoreCase("Expelliarmus")) return 12;
            if (hechizo.equalsIgnoreCase("Stupefy")) return 18;
    
            return 0;
        }
    
        public int getControlVarita() {
            return controlVarita;
        }
    }
    

    5) Auror.java

    Idea clave

    • Un Auror es “modo combate”: tiene experiencia y puede arrestar.
    • Añadimos métodos propios: patrullar() y arrestar(...).
    
    
    
    
    
    package modelo;
    
    public class Auror extends Hechicero {
    
        private int experienciaCombate; // 0..100
        private int arrestos;
    
        public Auror(String nombre, Casa casa) {
            super(nombre, casa);
    
            experienciaCombate = 40;
            arrestos = 0;
    
            if (casa == Casa.GRYFFINDOR) experienciaCombate += 10; // valentía
            if (casa == Casa.SLYTHERIN) experienciaCombate += 5;   // ambición táctica
            experienciaCombate = clamp(experienciaCombate, 0, 100);
        }
    
        public void patrullar() {
            if (!gastarMana(8)) return;
    
            experienciaCombate += 4;
            experienciaCombate = clamp(experienciaCombate, 0, 100);
    
            nivel += 1;
            nivel = clamp(nivel, 1, 100);
        }
    
        public boolean arrestar(Aprendiz objetivo) {
            // Regla: solo si está débil
            if (objetivo == null) return false;
    
            // Como vida es protected en Mago, podemos leerla aquí directamente:
            if (objetivo.vida <= 20) {
                arrestos++;
                return true;
            }
            return false;
        }
    
        @Override
        public int lanzarHechizo(String hechizo) {
            if (!gastarMana(9)) return 0;
    
            // Auror: daño mejorado por experienciaCombate
            if (hechizo.equalsIgnoreCase("Stupefy")) {
                return 20 + (experienciaCombate / 10);
            }
    
            // Protego: “defensa” simple -> recupera vida (no daño)
            if (hechizo.equalsIgnoreCase("Protego")) {
                vida += 10;
                vida = clamp(vida, 0, 100);
                return 0;
            }
    
            // Otros hechizos como en Hechicero (reutilizamos lógica)
            return super.lanzarHechizo(hechizo);
        }
    
        public int getArrestos() {
            return arrestos;
        }
    }
    

    6) Profesor.java

    Idea clave

    • Un Profesor enseña: puede reducir torpeza y subir nivel del alumno.
    • Sus hechizos son “eficientes”: consumen menos mana o fallan menos.
    
    
    
    
    
    package modelo;
    
    public class Profesor extends Hechicero {
    
        private String asignatura;
        private int prestigio; // 0..100
    
        public Profesor(String nombre, Casa casa, String asignatura) {
            super(nombre, casa);
            this.asignatura = asignatura;
    
            prestigio = 60;
            if (casa == Casa.SLYTHERIN) prestigio += 5;
            if (casa == Casa.RAVENCLAW) prestigio += 10;
            prestigio = clamp(prestigio, 0, 100);
        }
    
        public void enseñar(Aprendiz alumno) {
            if (alumno == null) return;
            if (!gastarMana(6)) return;
    
            // Enseñar reduce torpeza y sube nivel
            alumno.setTorpeza(alumno.getTorpeza() - 8);
            alumno.nivel = clamp(alumno.nivel + 1, 1, 100);
        }
    
        public void evaluar() {
            if (!gastarMana(4)) return;
            prestigio += 2;
            prestigio = clamp(prestigio, 0, 100);
        }
    
        @Override
        public int lanzarHechizo(String hechizo) {
            // Profesor: coste menor y resultados más estables
            int coste = 6;
            if (!gastarMana(coste)) return 0;
    
            // “Daño controlado”
            if (hechizo.equalsIgnoreCase("Expelliarmus")) return 14;
            if (hechizo.equalsIgnoreCase("Stupefy")) return 17;
            if (hechizo.equalsIgnoreCase("Lumos")) return 5;
            if (hechizo.equalsIgnoreCase("Alohomora")) return 7;
    
            return 0;
        }
    
        public String getAsignatura() {
            return asignatura;
        }
    }
    

    7) Main.java (sin listas de Mago, tipos concretos)

    package app;
    
    import modelo.*;
    
    public class Main {
    
        public static void main(String[] args) {
    
            Aprendiz harry = new Aprendiz("Harry", Casa.GRYFFINDOR);
            Aprendiz hermione = new Aprendiz("Hermione", Casa.RAVENCLAW);
    
            Hechicero draco = new Hechicero("Draco", Casa.SLYTHERIN);
            Hechicero luna = new Hechicero("Luna", Casa.HUFFLEPUFF);
    
            Auror kingsley = new Auror("Kingsley", Casa.HUFFLEPUFF);
            Profesor snape = new Profesor("Snape", Casa.SLYTHERIN, "Pociones");
    
            System.out.println("=== FICHAS INICIALES ===");
            System.out.println(harry.ficha());
            System.out.println(hermione.ficha());
            System.out.println(draco.ficha());
            System.out.println(luna.ficha());
            System.out.println(kingsley.ficha());
            System.out.println(snape.ficha());
    
            System.out.println("\n=== RONDA 1: PRACTICAR Y ESTUDIAR ===");
            harry.practicarBasico();
            hermione.practicarBasico();
            draco.estudiarEnBiblioteca();
            luna.estudiarEnBiblioteca();
            kingsley.patrullar();
            snape.evaluar();
    
            System.out.println(harry.ficha());
            System.out.println(hermione.ficha());
            System.out.println(draco.ficha());
            System.out.println(luna.ficha());
            System.out.println(kingsley.ficha());
            System.out.println(snape.ficha());
    
            System.out.println("\n=== RONDA 2: DUELO SIMPLE (daño a vida) ===");
            int d1 = draco.lanzarHechizo("Stupefy");
            harry.recibirDaño(d1);
            System.out.println("Draco lanza Stupefy a Harry. Daño: " + d1);
            System.out.println("Harry -> " + harry.ficha());
    
            int d2 = harry.lanzarHechizo("Lumos");
            draco.recibirDaño(d2);
            System.out.println("Harry lanza Lumos a Draco (sí, es cutre). Daño: " + d2);
            System.out.println("Draco -> " + draco.ficha());
    
            System.out.println("\n=== RONDA 3: PROFESOR EN ACCIÓN ===");
            snape.enseñar(harry);
            System.out.println("Snape enseña a Harry (baja torpeza y sube nivel).");
            System.out.println("Harry -> " + harry.ficha());
    
            System.out.println("\n=== RONDA 4: AUROR Y PROTEGO ===");
            int d3 = kingsley.lanzarHechizo("Stupefy");
            luna.recibirDaño(d3);
            System.out.println("Kingsley lanza Stupefy a Luna. Daño: " + d3);
            System.out.println("Luna -> " + luna.ficha());
    
            kingsley.lanzarHechizo("Protego");
            System.out.println("Kingsley usa Protego (se cura un poco).");
            System.out.println("Kingsley -> " + kingsley.ficha());
    
            System.out.println("\n=== RONDA 5: INTENTO DE ARRESTO ===");
            // Bajamos a propósito la vida de Hermione para probar arresto
            hermione.recibirDaño(85);
            System.out.println("Hermione queda débil: " + hermione.ficha());
    
            boolean arresto = kingsley.arrestar(hermione);
            System.out.println("¿Kingsley arresta a Hermione? " + arresto);
            System.out.println("Arrestos de Kingsley: " + kingsley.getArrestos());
        }
    }
    
    Aquí el alumnado ve claramente la herencia: cada clase tiene lo suyo.
    
    
    
    
    

    El conocimiento es poder… pero en Hogwarts, también lo es la herencia bien diseñada.

  • Obsidian para documentar proyectos en Markdown

    Obsidian para documentar proyectos en Markdown

    1. Introducción

    En este tema aprenderás a utilizar Obsidian para crear y organizar documentación en formato Markdown. Los documentos se guardarán en una carpeta local y, posteriormente, podrán incorporarse a un repositorio de GitHub.

    El objetivo no es utilizar Obsidian como una nube ni como sustituto de GitHub. Obsidian será el editor de documentación y GitHub será el lugar donde se almacenen y entreguen los proyectos.

    2. ¿Qué es Obsidian?

    Obsidian es una aplicación para escribir y organizar notas mediante archivos Markdown. Cada nota es un archivo de texto con extensión .md y puede abrirse también con Visual Studio Code, cualquier editor de texto o directamente desde GitHub.

    Una de sus características principales es que los archivos se guardan en una carpeta normal del ordenador. Obsidian denomina bóveda o vault a esa carpeta.

    Con Obsidian podemos:

    • Crear archivos Markdown sin memorizar inicialmente toda la sintaxis.
    • Organizar documentos mediante carpetas.
    • Insertar imágenes, enlaces, listas, tablas y bloques de código.
    • Relacionar documentos entre sí.
    • Ver el resultado mientras escribimos.
    • Buscar rápidamente en toda la documentación.
    • Mantener una colección de apuntes o proyectos en archivos locales.

    Importante: una bóveda no es un formato especial ni un archivo comprimido. Es una carpeta normal que contiene documentos y recursos.

    3. Obsidian, Git y GitHub no son lo mismo

    HerramientaFunción
    ObsidianCrear, editar y organizar los documentos Markdown.
    GitRegistrar el historial de cambios del proyecto.
    GitHubAlojar el repositorio y permitir su entrega o revisión.

    El flujo de trabajo que utilizaremos será:

    Escribir en Obsidian → Guardar en la carpeta local → Confirmar con Git → Subir a GitHub

    4. Descargar Obsidian

    La descarga debe realizarse desde la página oficial:

    Descargar Obsidian

    Obsidian está disponible para Windows, macOS, Linux, Android, iPhone y iPad. En este curso utilizaremos principalmente la versión de escritorio.

    5. Instalación en Windows

    1. Accede a la página oficial de descarga.
    2. Localiza el apartado Windows.
    3. Pulsa Universal.
    4. Espera a que termine la descarga.
    5. Abre el archivo de instalación descargado.
    6. Sigue los pasos mostrados por el instalador.
    7. Abre Obsidian desde el menú Inicio.

    Si Windows muestra una advertencia, comprueba que el instalador procede del dominio oficial obsidian.md.

    6. Instalación en macOS

    1. Accede a la página oficial de descarga.
    2. Localiza el apartado Mac.
    3. Pulsa Universal.
    4. Abre el archivo descargado.
    5. Arrastra el icono de Obsidian hasta la carpeta Aplicaciones.
    6. Abre la carpeta Aplicaciones y ejecuta Obsidian.

    La primera vez, macOS puede pedir confirmación para abrir una aplicación descargada de Internet.

    7. Instalación en Linux

    La web oficial ofrece diferentes formatos: AppImage, Snap y paquete DEB. También aparece una versión Flatpak mantenida por la comunidad.

    Opción A: paquete DEB

    Esta opción resulta adecuada para Ubuntu, Debian y distribuciones derivadas.

    1. Descarga el paquete Deb desde la web oficial.
    2. Abre una terminal en la carpeta de descargas.
    3. Ejecuta:
    sudo apt install ./obsidian_*.deb
    1. Abre Obsidian desde el menú de aplicaciones.

    Opción B: AppImage

    1. Descarga el archivo AppImage.
    2. Abre una terminal en la carpeta donde se encuentre.
    3. Concede permiso de ejecución:
    chmod u+x Obsidian-*.AppImage
    1. Ejecuta la aplicación:
    ./Obsidian-*.AppImage

    Opción C: Flatpak

    Si el sistema ya tiene Flatpak y Flathub configurados:

    flatpak install flathub md.obsidian.Obsidian

    Para abrirlo desde la terminal:

    flatpak run md.obsidian.Obsidian

    8. Crear una bóveda local

    Al abrir Obsidian por primera vez aparecerá la pantalla de gestión de bóvedas.

    1. Pulsa Create junto a Create new vault.
    2. En Vault name, escribe:
    Documentacion-ASIR
    1. Pulsa Browse.
    2. Selecciona una ubicación fácil de encontrar, por ejemplo Documentos.
    3. Pulsa Create.

    Obsidian creará una carpeta llamada Documentacion-ASIR. Todos los documentos de la bóveda se guardarán físicamente dentro de ella.

    Una ubicación posible en Windows sería:

    C:\Users\alumno\Documents\Documentacion-ASIR

    En macOS o Linux podría ser:

    ~/Documentos/Documentacion-ASIR

    No crees la bóveda en una carpeta temporal, en Descargas ni dentro de otra bóveda.

    9. Crear la estructura inicial

    Dentro de la bóveda crea estas carpetas desde el explorador lateral de Obsidian:

    Documentacion-ASIR/
    ├── 00-Plantillas/
    ├── 01-Actividades/
    ├── 02-Proyectos/
    ├── 03-Apuntes/
    └── img/

    Su finalidad es:

    • 00-Plantillas: modelos reutilizables de documentos.
    • 01-Actividades: actividades breves realizadas durante el curso.
    • 02-Proyectos: proyectos de mayor tamaño.
    • 03-Apuntes: notas personales del alumno.
    • img: imágenes y capturas utilizadas en la documentación.

    10. Crear el primer README

    1. Selecciona la carpeta 01-Actividades.
    2. Crea una carpeta denominada actividad-01-markdown.
    3. Dentro de ella, crea una nota nueva.
    4. Cambia su nombre a README.

    Obsidian añadirá automáticamente la extensión y guardará el archivo como:

    README.md

    Escribe este contenido:

    # Actividad 1: introducción a Markdown
    
    ## Descripción
    
    Esta es mi primera documentación escrita con **Obsidian**.
    
    ## Objetivos
    
    - Aprender a crear un README.
    - Organizar una actividad.
    - Insertar imágenes.
    - Preparar el documento para GitHub.
    
    ## Conclusión
    
    En esta actividad he aprendido a crear y visualizar un documento Markdown.

    11. Modos de edición y lectura

    Obsidian permite trabajar principalmente con dos vistas:

    • Vista de edición: permite modificar el documento.
    • Vista de lectura: muestra el documento renderizado.

    También dispone de Live Preview, que presenta gran parte del formato mientras se escribe.

    Utiliza la vista de lectura antes de entregar una actividad para comprobar:

    • Que los títulos tienen la jerarquía correcta.
    • Que las listas aparecen correctamente.
    • Que las imágenes se muestran.
    • Que no existen enlaces rotos.
    • Que los bloques de código son legibles.

    12. Configuración recomendada para trabajar con GitHub

    Obsidian incorpora funciones propias que no siempre funcionan igual fuera de la aplicación. Para mantener la compatibilidad con GitHub, realiza esta configuración.

    12.1 Utilizar enlaces Markdown

    1. Abre Settings.
    2. Entra en Files and links.
    3. Desactiva Use [[Wikilinks]].

    Obsidian utilizará enlaces estándar:

    [Nombre del documento](otro-documento.md)

    En lugar de:

    [[otro-documento]]

    Los dos formatos funcionan en Obsidian, pero el primero ofrece mejor compatibilidad con otros editores y repositorios.

    12.2 Actualizar enlaces automáticamente

    En Settings → Files and links, mantén activada la actualización automática de enlaces internos. De esta manera, si renombras un documento desde Obsidian, sus referencias se actualizarán.

    12.3 Elegir dónde se guardan las imágenes

    1. Abre Settings.
    2. Entra en Files and links.
    3. Busca Default location for new attachments.
    4. Selecciona In subfolder under current folder.
    5. Escribe:
    img

    Así, cada actividad podrá conservar sus capturas junto al README:

    actividad-01-markdown/
    ├── README.md
    └── img/
        ├── paso-01.png
        └── resultado-final.png

    13. Insertar imágenes

    Puedes arrastrar una imagen desde el explorador de archivos hasta el documento. Obsidian la copiará a la ubicación configurada y la insertará en la nota.

    Para GitHub es recomendable que el resultado utilice esta sintaxis:

    ![Descripción de la captura](img/paso-01.png)

    Buenas prácticas:

    • Usa nombres descriptivos.
    • Evita espacios, tildes y caracteres especiales en los nombres.
    • Recorta las capturas para mostrar solo lo necesario.
    • Añade una explicación antes o después de cada captura.
    • No muestres contraseñas, tokens, datos personales ni direcciones privadas sensibles.
    • Comprueba la imagen tanto en Obsidian como en GitHub.

    14. Enlaces internos y externos

    Enlace a otro documento

    [Consultar instalación](instalacion.md)

    Enlace a una sección del mismo documento

    [Ir a las conclusiones](#conclusiones)

    Enlace externo

    [Documentación oficial de Obsidian](https://help.obsidian.md)

    Evita depender de enlaces especiales exclusivos de Obsidian si el documento debe visualizarse en GitHub.

    15. Bloques de código y comandos

    Para escribir un comando dentro de una frase utiliza una comilla invertida:

    Ejecuta el comando `git status`.

    Para escribir varios comandos utiliza un bloque e indica el lenguaje:

    ```bash
    git add .
    git commit -m "Completa la documentación"
    git push
    ```

    Ejemplo con Java:

    ```java
    public class Principal {
        public static void main(String[] args) {
            System.out.println("Hola");
        }
    }
    ```

    16. Diagramas Mermaid

    Obsidian puede representar diagramas Mermaid escritos dentro del propio documento.

    ```mermaid
    flowchart TD
        A[Crear documentación] --> B[Revisar en Obsidian]
        B --> C[Guardar cambios con Git]
        C --> D[Subir a GitHub]
    ```

    Antes de entregar, comprueba que el diagrama también se representa correctamente en GitHub.

    17. Plantilla básica para las actividades

    Guarda en 00-Plantillas un archivo llamado plantilla-actividad.md:

    # Título de la actividad
    
    ## Información
    
    - **Alumno:**
    - **Asignatura:**
    - **Fecha:**
    
    ## Descripción
    
    Explicación breve de la actividad.
    
    ## Objetivos
    
    - Objetivo 1.
    - Objetivo 2.
    
    ## Desarrollo
    
    ### Paso 1
    
    Explicación del paso.
    
    ![Descripción de la captura](img/paso-01.png)
    
    ## Problemas encontrados
    
    Describe los problemas y las soluciones aplicadas.
    
    ## Resultado
    
    Explica cómo has comprobado el funcionamiento.
    
    ## Conclusiones
    
    Resume lo aprendido con tus propias palabras.
    
    ## Referencias
    
    - [Documentación consultada](https://ejemplo.com)

    18. Llevar una actividad a GitHub

    La carpeta que se abra como repositorio debe contener directamente el proyecto y su documentación:

    mi-proyecto/
    ├── README.md
    ├── img/
    ├── src/
    └── otros-archivos-del-proyecto

    Puedes abrir esa misma carpeta como bóveda de Obsidian mediante Open folder as vault. Así editas el README directamente dentro del repositorio y evitas mantener dos copias diferentes.

    Cuando termines de documentar:

    git status
    git add README.md img/
    git commit -m "Añade la documentación de la actividad"
    git push

    Después, abre el repositorio en GitHub y comprueba visualmente el README.

    19. ¿Subir la configuración de Obsidian al repositorio?

    Obsidian crea una carpeta oculta denominada .obsidian con la configuración de la bóveda.

    Para actividades individuales normalmente no es necesario subirla. Puedes añadirla a .gitignore:

    .obsidian/

    Esto mantiene el repositorio centrado en la documentación y en los archivos del proyecto. Si un equipo necesita compartir una configuración concreta, deberá decidirlo expresamente.

    20. Plugins y temas

    Obsidian permite instalar temas y plugins, pero no son necesarios para crear buenos README.

    Durante las primeras actividades se recomienda:

    • Utilizar el tema predeterminado.
    • No instalar plugins comunitarios.
    • Aprender primero Markdown estándar.
    • Introducir nuevas funciones únicamente cuando resuelvan una necesidad real.

    Los plugins añaden complejidad y algunos generan contenido que no funciona correctamente fuera de Obsidian.

    21. Copias de seguridad y sincronización

    Que los archivos estén en el ordenador no significa que tengan una copia de seguridad.

    Recomendaciones:

    • Utiliza Git y GitHub para los proyectos del curso.
    • Realiza commits frecuentes y con mensajes descriptivos.
    • No confundas sincronización con copia de seguridad.
    • No guardes contraseñas ni secretos en la bóveda.
    • Comprueba qué archivos vas a subir mediante git status.

    Obsidian ofrece servicios opcionales de sincronización y publicación, pero no son necesarios para seguir este tema ni para entregar las actividades en GitHub.

    22. Consejos de organización

    • Utiliza un solo # para el título principal.
    • Organiza los apartados con ## y ###.
    • Mantén nombres coherentes: actividad-01, actividad-02, etc.
    • Evita nombres como final, final-bueno o final-definitivo-2.
    • Escribe primero la explicación y añade después la evidencia.
    • No conviertas el README en una colección de capturas.
    • Incluye siempre una sección de comprobación o resultado.
    • Explica los errores relevantes y cómo los resolviste.
    • Cita las fuentes consultadas.
    • Revisa el documento en GitHub antes de entregar.

    23. Errores frecuentes

    La imagen se ve en Obsidian, pero no en GitHub

    Comprueba que la imagen se encuentre dentro del repositorio y que la ruta respete exactamente mayúsculas y minúsculas:

    ![Resultado](img/resultado.png)

    El enlace funciona en Obsidian, pero no en GitHub

    Es posible que se haya utilizado un Wikilink. Sustitúyelo por un enlace Markdown estándar.

    El README aparece como texto sin formato

    Comprueba que se llama exactamente README.md y no README.md.txt.

    Hay demasiadas imágenes en la raíz

    Configura la ubicación de adjuntos y almacénalos en una carpeta img.

    Obsidian no muestra una bóveda anterior

    Selecciona Open folder as vault y elige la carpeta que contiene los archivos Markdown.

    24. Lista de comprobación antes de entregar

    • El archivo principal se llama README.md.
    • El README está dentro del repositorio correcto.
    • Las imágenes están dentro del repositorio.
    • Las rutas de las imágenes son relativas.
    • Los enlaces funcionan en GitHub.
    • Los títulos tienen una jerarquía lógica.
    • Los comandos están dentro de bloques de código.
    • No aparecen contraseñas, tokens ni datos sensibles.
    • La carpeta .obsidian está excluida si no es necesaria.
    • Se ha realizado un commit antes de la entrega.
    • Se ha comprobado la presentación final en GitHub.

    25. Actividad propuesta

    1. Instala Obsidian.
    2. Crea una bóveda local denominada Documentacion-ASIR.
    3. Crea la estructura de carpetas indicada en este manual.
    4. Configura los enlaces Markdown y la carpeta de imágenes.
    5. Crea un archivo README.md utilizando la plantilla básica.
    6. Inserta una captura en la carpeta img.
    7. Añade una lista, un enlace y un bloque de código.
    8. Revisa el documento en vista de lectura.
    9. Abre la carpeta con Visual Studio Code y comprueba que el archivo continúa siendo editable.
    10. Sube el resultado al repositorio indicado por el profesor.

    26. Referencias oficiales

  • 2.1 – Usuarios, permisos y el impostor legal sudo

    2.1 – Usuarios, permisos y el impostor legal sudo

    Un sistema operativo multiusuario es como un edificio donde vive mucha gente. Cada persona tiene su habitación y sus cosas. Sin permisos, cualquiera podría:

    • Abrirse la nevera de otro.
    • Pagar las facturas del vecino (aunque le convenga).
    • Borrar carpetas del sistema “sin querer”.

    Linux nació para compartir la casa de forma civilizada.

    [La regla de oro]
    El usuario normal puede romper su habitación; el superusuario puede romper el edificio entero.

    ¿Qué es el superusuario (root)?

    Root es ese administrador que tiene todas las llaves, incluidas las que abren las puertas del sistema. Puede instalar programas, cambiar configuraciones, borrar sistemas de archivos y mirar cualquier carpeta.


    ¿Qué es sudo realmente?

    “Substitute User DO” (o “superuser do”).
    Traducción humana: Haz esto como si yo fuera el administrador.

    Sudo no da poderes mágicos. Solo te presta el disfraz de root por unos segundos, si el sistema confía en ti, según lo que aparezca en el archivo /etc/sudoers.

    Además:

    • Sudo pide contraseña porque necesita asegurarse de que eres tú.
    • Guarda un registro de lo que haces (auditoría)
    • Puede limitar qué comandos exactos puede usar cada usuario.

    Ese toque de control es lo que hace que sudo sea más seguro que loguearse directamente como root.


    Explicación práctica del archivo /etc/sudoers

    En el documento sudoers podemos dar permisos para utilizar todos los comando o algunos en concreto.

    usuario maquina=(usuario_objetivo) comandos

    Ejemplo clásico:

    antonio ALL=(ALL:ALL) ALL

    Traducción informal: Antonio puede usar sudo para hacer cualquier cosa, desde cualquier sitio, como cualquier usuario.

    Significado de ALL=(ALL:ALL) ALL

    Piensa en cada ALL como una variable diferente en una cadena de permisos.
    El archivo /etc/sudoers sigue esta estructura general:

    usuario hosts = (usuarios_objetivo : grupos_objetivo) comandos

    Primer ALL → Dónde puede usar sudo

    ALL =

    Esto significa:

    “Desde cualquier máquina o terminal donde este usuario inicie sesión”.

    En aulas, servidores, SSH, local… no importa.
    Significa sin restricciones por host.


    (ALL:ALL) → Quién puede llegar a ser

    Este es el trozo más interesante.

    (ALL:ALL) Se divide en dos partes:

    ==Primer ALL (antes de los dos puntos)==

    Es la lista de usuarios objetivo.

    Traducción:

    “Puede usar sudo para convertirse en cualquier usuario del sistema.”

    No solo root: también www-data, postgres, backup, etc.

    Por ejemplo:

    sudo -u postgres psql

    ==Segundo ALL (tras los dos puntos)==

    Es la lista de grupos objetivo.

    Significa:

    “Puede ejecutar comandos como miembro de cualquier grupo.”

    No siempre se usa, pero cuando está, implica libertad total en cómo sudo crea el entorno del comando.

    En resumen:

    Tiene permiso para ejecutar comandos como cualquier usuario y cualquier grupo.


    Último ALL → Qué comandos puede ejecutar

    ... ALL

    Es la lista de comandos permitidos con sudo.

    Este último ALL significa:

    “Puede ejecutar cualquier comando con sudo.”

    Incluyendo:

    • Administración del sistema
    • Manipulación de archivos críticos
    • Instalación de paquetes
    • Gestión de usuarios
    • Servicios
    • Montaje/desmontaje
    • Cambios en red
    • Etc.

    [!NOTA]
    Es la carta blanca total.—

    En distros como Ubuntu, pertenecer al grupo sudo ya te da superpoderes. Puedes inspeccionar el grupo así:

    
    
    
    
    
    getent group sudo

    O, de forma artesanal:

    
    
    
    
    
    cat /etc/group | grep sudo

    También puedes pedirle al sistema: “Oye, ¿quién puede ejecutar sudo?” con:

    
    
    
    
    
    sudo -l -U nombre_de_usuario

    Esto te dice exactamente qué puede hacer ese usuario con sudo.

    En resumen privilegiado:
    — Usuarios declarados en /etc/sudoers
    — Usuarios declarados en /etc/sudoers.d/*
    — Usuarios que pertenecen al grupo sudo (o wheel, según la distro)

    Crear usuarios sin poderes especiales

    Comandos básicos:

    Crear usuario

    sudo adduser juan

    El sistema pedirá contraseña y datos opcionales.
    Por defecto, juan no tiene poderes administrativos.

    Ver su grupo

    id juan

    Verán que no pertenece al grupo sudo.

    Cambiar a ese usuario

    su juan

    Ahora puedes intentar un comando de administrador:

    sudo apt update

    Te dirá que juan no está en el archivo sudoers.

    Esa frase es el equivalente a “no tienes la llave del edificio”.


    Crear un usuario con permisos de sudo

    Hay dos formas:

    A) Añadirlo al grupo sudo

    sudo usermod -aG sudo juan

    Ahora juan puede usar sudo después de cerrar sesión y volver a entrar.

    B) Darle permisos específicos (ideal para clase avanzada)

    Editar con el editor seguro:

    sudo visudo

    Y añadir algo como:

    juan ALL=(ALL) /usr/bin/apt, /usr/bin/systemctl restart apache2

    Ahora juan solo puede actualizar paquetes y reiniciar Apache.
    Esto crea un usuario “Hawkeye”: no tiene superpoderes totales, pero sí un par de flechas especiales.

    Comandos clave

    • Crear usuario: sudo adduser nombre
    • Cambiar su grupo: sudo usermod -aG sudo nombre
    • Cambiar de usuario: su - nombre
    • Editar permisos: sudo visudo
    • Ver grupos: id nombre

    Archivos importantes

    • /etc/passwd → lista de usuarios.
    • /etc/group → lista de grupos.
    • /etc/sudoers → permisos privilegiados.
    • /var/log/auth.log → historial de uso de sudo.

    Comandos para la creación de usuarios y grupos

    1. Crear usuario con adduser

    adduser es amigable, pregunta cosas, rellena la casa del usuario y pone alfombra.

    Ejemplos:

    Crear usuario normal

    sudo adduser mario

    Crear usuario y saltarse las preguntas (solo contraseña):

    sudo adduser --disabled-password mario

    Después puedes activar contraseña con:

    sudo passwd mario

    Crear usuario sin carpeta home. Esto es útil para cuentas de servicio.

    sudo adduser --no-create-home servidorweb

    Crear usuario en un grupo específico

    sudo adduser juana profesores


    2. Crear usuario con useradd (el técnico)

    useradd es seco, directo… y totalmente predecible, ideal para scripts y prácticas avanzadas.

    Crear usuario con home y shell

    sudo useradd -m -s /bin/bash ana

    Crear usuario sin home

    sudo useradd -M bot

    Crear usuario con grupo primario específico

    sudo useradd -g profesores laura

    Crear usuario con grupos adicionales

    sudo useradd -G sudo,devops carlos

    Crear usuario con fecha de caducidad

    Esto es genial para usuarios temporales.

    sudo useradd -m -e 2025-12-31 invitado

    Puedes ver la caducidad con:

    sudo chage -l invitado

    Crear usuario con comentario

    sudo useradd -m -c "Laura Martínez" laura


    GESTIÓN DE CONTRASEÑAS

    La herramienta clave aquí es passwd.

    Cambiar o poner contraseña a un usuario

    sudo passwd juan

    Desactivar la contraseña (no puede iniciar sesión)

    sudo passwd -l juan

    Activar contraseña bloqueada

    sudo passwd -u juan

    Forzar cambio de contraseña al siguiente inicio

    Esto es ideal para alumnos nuevos:

    sudo passwd -e juan

    Establecer políticas de contraseñas

    Con chage puedes ajustar tiempos.

    Ejemplos:

    Caducidad de contraseña a 90 días

    sudo chage -M 90 juan

    Periodo mínimo entre cambios: 1 día

    sudo chage -m 1 juan

    Avisar 7 días antes de caducar

    sudo chage -W 7 juan

    Bloquear cuenta si no usa su cuenta en X días

    sudo chage -I 30 juan


    GESTIÓN DE GRUPOS

    Crear grupo

    sudo groupadd profesores

    Añadir usuario a grupo

    sudo usermod -aG profesores juan

    Sacar usuario de un grupo

    Para ver grupos primero:

    groups juan

    Eliminarlo del grupo:

    sudo gpasswd -d juan profesores


    MODIFICAR USUARIOS YA EXISTENTES

    Cambiar su shell

    sudo usermod -s /bin/bash mario

    Cambiar su home (se mueve manualmente)

    sudo usermod -d /home/nuevo_mario mario

    Cambiar nombre del usuario

    sudo usermod -l nuevo_nombre viejo_nombre

    Cambiar el UID o GID

    (para nivel pro)

    sudo usermod -u 1500 mario sudo usermod -g staff mario


    Ver en qué grupos está un usuario

    El método rápido, casi intuitivo:

    
    
    
    
    
    groups nombreusuario

    Te devuelve todos los grupos a los que pertenece, con una lista directa, estilo:

    
    
    
    
    
    nombreusuario : grupo1 grupo2 grupo3

    Si quieres la versión más formal:

    
    
    
    
    
    id nombreusuario

    Te muestra UID, GID y todos los grupos extra.

    Y si estás logueado como ese usuario, basta con:

    
    
    
    
    
    groups

    Ver qué usuarios pertenecen a un grupo

    Esta es la operación inversa: mirar dentro del grupo para ver la lista de miembros.

    Forma clara:

    
    
    
    
    
    getent group nombredelgrupo
    

    Salida típica:

    
    
    
    
    
    profesores:x:1003:antonio,juan,marta
    

    También puedes mirar el archivo clásico:

    
    
    
    
    
    cat /etc/group | grep nombredelgrupo

    Y si el grupo tiene muchos miembros, puedes hacerlo más legible:

    
    
    
    
    
    getent group nombredelgrupo | tr ':' '\n'

    El detalle curioso: grupos primarios vs secundarios

    Cada usuario tiene:

    • un grupo primario (su GID principal)
    • varios grupos secundarios

    id te los marca con claridad:

    
    
    
    
    
    id alumna1
    

    Salida:

    
    
    
    
    
    uid=1001(alumna1) gid=1001(alumna1) groups=1001(alumna1),1002(sudo),1003(profesores)

    Cómo ver si un usuario tiene permisos indirectos en un grupo

    Linux no tiene una orden directa tipo “¿quién tiene permisos en esta carpeta vía grupo?”, pero con la trilogía:

    1. ver el grupo dueño de la carpeta
    2. ver los permisos
    3. listar los usuarios del grupo

    Ya puedes reconstruir la escena del crimen digital.

    Ejemplo:

    
    
    
    
    
    ls -ld carpeta

    Resultado:

    
    
    
    
    
    drwxrwx--- 2 root profesores 4096 ...

    Luego:

    
    
    
    
    
    getent group profesores

    Obtienes la lista real de personas con acceso.

  • 2.2 – Por qué root no es tu amigo (pero lo necesitas a veces)

    2.2 – Por qué root no es tu amigo (pero lo necesitas a veces)

    ¿Qué es el superusuario (root)?

    Root es ese administrador que tiene todas las llaves, incluidas las que abren las puertas del sistema. Puede instalar programas, cambiar configuraciones, borrar sistemas de archivos y mirar cualquier carpeta.

    Hay varias formas de obtener una sesión como superusuario. Cada una tiene su sabor.

    Entrar como root con su -

    Este es el método clásico.

    su -

    Te pedirá la contraseña del usuario root.
    Si root está deshabilitado (como en Ubuntu), no funcionará.

    El - significa “cargar el entorno completo de root” (ruta, variables, etc.), no solo cambiar el usuario.


    Entrar como root usando sudo

    Esto solo funciona si tu usuario pertenece al grupo sudo.

    sudo su -

    Aquí la contraseña que pide es la tuya, no la del root.
    Es una forma de entrar en modo administrador sin conocer la clave maestra.


    Abrir directamente una shell como root

    sudo -i

    Es prácticamente equivalente a su -, pero usando el poder de sudo.

    ¿Por qué es mala idea usar root todo el tiempo?

    Root no tiene frenos

    Un usuario normal puede romper su sesión.
    Root puede romper el sistema entero, el arranque, o borrar discos completos sin pestañear.

    [!NOTE]
    ==Ejemplo peligroso: ==
    rm -rf /
    ESTO BOORARA TODO

    Un usuario normal no puede ejecutarlo sobre el sistema.
    Root sí. No pregunta. No duda. No se arrepiente.


    Root no te protege de tus despistes

    Un error tipográfico en root es como enviar un misil por escribir mal una coma.

    Esto pasa más de lo que parece:

    ==**Ejemplo peligroso: **==
    ==mv /home/alumno /home/alumno_backup mv /home/alumno_backup /==
    ESTO DAÑARA EL SISTEMA

    y adiós estructura de carpetas.


    Root no queda registrado igual que sudo

    Cuando usas root directamente:

    • No queda claro qué usuario real hizo qué.
    • No hay auditoría detallada
    • En una clase o empresa, dificulta saber quién tocó qué.

    Cuando usas sudo:

    /var/log/auth.log

    registra cada comando ejecutado.


    Root abre puertas a ataques

    Si un script, un archivo o un comando malicioso se ejecuta como root, ya está dentro de la fortaleza con una llave maestra.
    Malo para servidores. Malo para usuarios.


    5. Root ignora restricciones útiles

    No hay:

    • cuotas
    • límites de procesos
    • límites de memoria
    • restricciones de permisos

    Root puede saturar el sistema sin querer.


    Root fomenta malos hábitos

    Cosas que acaban pasando cuando se usa root “porque es más rápido”:

    • Instalar paquetes sin pensar.
    • Editar archivos del sistema sin copia de seguridad.
    • Romper autenticación, red o fstab
    • Crear permisos demasiado amplios.

    [!NOTA]
    En una frase, se traduce en:
    “Profe, mi VM no arranca y no sé por qué…”

  • 2.3 – Tipos de permisos en Linux

    2.3 – Tipos de permisos en Linux

    Los permisos en Linux son el sistema nervioso de la seguridad.
    Sin ellos, cualquiera podría abrir, leer o destruir cualquier archivo.

    Esta lección explica:

    • qué permisos existen
    • cómo se representan
    • qué significan
    • cómo afectan a la ejecución de programas
    • cómo se relacionan con usuarios y grupos
    • y los permisos especiales que muchos desconocen (SUID, SGID, sticky bit)

    Los tres actores del sistema de permisos

    Cada archivo y carpeta tiene tres “capas” de permisos:

    1. Usuario (u) → el dueño del archivo
    2. Grupo (g) → usuarios que comparten un grupo
    3. Otros (o) → todos los demás

    Ejemplo del comando ls -l:

    Desglose:

    • - → tipo de archivo
    • rwx → permisos del usuario
    • r-x → permisos del grupo
    • --- → permisos de otros

    Tipos de permisos básicos

    Permiso de lectura — r

    • En archivos → permite leer su contenido
    • En directorios → permite listar los nombres de los archivos

    Símbolo: r
    Valor numérico: 4


    Permiso de escritura — w

    • En archivos → permite modificar el contenido
    • En directorios → permite crear, borrar o renombrar archivos dentro

    Símbolo: w
    Valor numérico: 2


    Permiso de ejecución — x

    • En archivos → permite ejecutarlo como un programa o script
    • En directorios → permite entrar (cd) dentro del directorio

    Símbolo: x
    Valor numérico: 1


    Cómo funcionan los permisos numéricos (modo octal)

    Cada permiso suma:

    • r = 4
    • w = 2
    • x = 1

    Por lo que si lo combinamos.

    OctalBinarioPermiso
    0000
    1001–x
    2010-w-
    3011-wx
    4100r–
    5101r-x
    6110rw-
    7111rwx

    De tal modo que:

    Ejemplo clásico: chmod 755 archivo

    TipoOctalBinarioPermiso
    Usuario7111rwx
    Grupo5101r-x
    Otros5101r-x

    Desglose:

    • Usuario → 7 → rwx
    • Grupo → 5 → r-x
    • Otros → 5 → r-x

    Ejemplos útiles:

    chmod 777 archivo # todos pueden todo
    chmod 644 archivo # dueño rw, grupo r, otros r
    chmod 700 clave.txt # solo el dueño puede acceder

    Permisos simbólicos (modo con letras)

    Muy útil para cambiar permisos parcialmente.

    Dar ejecución al usuario:

    chmod u+x script.sh

    Quitar escritura al grupo:

    chmod g-w notas.txt

    Dar permisos a todos:

    chmod a+rx carpeta

    Añadir permisos al dueño y quitarlos al resto:

    chmod u+rw,go-rwx secreto.txt

    Cómo funcionan los permisos en directorios

    Aquí tienes la regla simple:

    Lectura (r)

    Te deja ver la lista de archivos dentro del directorio.

    Escritura (w)

    Te deja crear, borrar o renombrar archivos dentro del directorio.

    Ejecución (x)

    Te deja entrar al directorio (cd) y acceder a archivos cuyo nombre conozcas.

    Frase clave:

    Sin “x”, no puedes entrar; sin “r”, no puedes ver lo que hay; sin “w”, no puedes cambiar nada.

    mkdir carpeta
    chmod 000 carpeta

    Resultado: ni root salvo usando sudo puede entrar.

  • 2.4 – CHOWN, CHMOD, CHGRP — LAS TRES LLAVES DEL REINO

    2.4 – CHOWN, CHMOD, CHGRP — LAS TRES LLAVES DEL REINO

    En Linux, cada archivo tiene un dueño (usuario), un grupo, y un conjunto de permisos.
    Modificar todo eso es fácil… demasiado fácil si usas root sin cabeza.

    Vamos a verlos uno por uno.


    1. chown → Cambiar el dueño del archivo

    La sintaxis es:

    chown usuario archivo

    Ejemplo simple:

    sudo chown juan /var/www/html/index.html

    Ahora Juan es el dueño de ese archivo.

    Si quieres cambiar usuario y grupo:

    sudo chown juan:profesores documento.txt

    Cambiar solo el grupo:

    sudo chown :profesores documento.txt

    Cambiar de forma recursiva (carpeta entera):

    sudo chown -R juan:juangroup /home/juan

    chown es “Change Owner”: cambia quién manda sobre el archivo.

    2. chgrp → Cambiar solo el grupo

    Es más específico que chown:

    sudo chgrp alumnos proyecto.txt

    La idea es sencilla:
    Cuando tienes un archivo, pueden mandar sobre él:

    • tú como usuario
    • o cualquiera de tu grupo asociado

    chgrp te deja decidir ese segundo nivel.


    3. chmod → Cambiar los permisos

    Aquí empieza el festival de números y letras. Tus alumnos suelen entenderlo mejor si usas una metáfora de puertas.

    Cada archivo tiene permisos divididos en tres bloques:

    u g o
    user group others

    Y cada uno tiene:

    • r → read (leer)
    • w → write (escribir)
    • x → execute (ejecutar)

    Dos formas de usar chmod:

    A) Modo numérico (octal)

    Es el clásico:

    chmod 755 archivo

    Por qué 7, 5 y 5?
    Porque cada permiso suma:

    • r = 4
    • w = 2
    • x = 1

    Ejemplos:

    • 7 = rwx (4+2+1)
    • 6 = rw- (4+2)
    • 5 = r-x (4+1)
    • 4 = r– (4)

    Ejemplos prácticos:

    Permiso para que usuario pueda todo, grupo y otros solo leer:

    chmod 744 informe.txt

    Permiso de ejecución para usuario y grupo:

    chmod 770 script.sh

    Modo más típico para scripts:

    chmod 755 script.sh

    B) Modo simbólico (con letras)

    Más legible:

    Dar ejecución al usuario:

    chmod u+x script.sh

    Quitar escritura a otros:

    chmod o-w archivo.txt

    Dar permisos de lectura y escritura al grupo:

    chmod g+rw proyecto

    Ejemplo 1: carpeta compartida para un grupo

    sudo mkdir /compartido
    sudo chgrp alumnos /compartido
    sudo chmod 770 /compartido

    Todo el grupo “alumnos” puede usarla.


    Ejemplo 2: permitir que un usuario edite su web

    sudo chown -R juan:www-data /var/www/juan
    sudo chmod -R 750 /var/www/juan

    Explicación para los estudiantes:

    • Juan puede leer/escribir.
    • El servidor (www-data) puede leer.
    • Nadie más puede entrar.

    Ejemplo 3: archivo ejecutable para todos

    chmod a+x programa.sh

    a significa all (todos los usuarios).


    Ejemplo 4: bloquear totalmente un archivo

    chmod 000 documento.txt

    Solo root podrá tocarlo.

    ¿Cómo enlazar esto con la lección de root?

    Un usuario normal solo puede cambiar permisos y dueños de lo que le pertenece.
    Root puede cambiar todo, lo que lo convierte en una herramienta poderosa… o en un desastre en manos torpes.

    sudo chown root:root /home/alumno1
    sudo chmod 700 /home/alumno1

    Acabas de expulsar a alumno1 de su propia casa.
    Es un experimento divertido para enseñar responsabilidad… o para que entiendan por qué root no es una buena costumbre.

    Resumen

    • chown → cambia el dueño del archivo y su grupo
    • chgrp → cambia solo el grupo
    • chmod → cambia los permisos (r, w, x) en user/group/others
    • root puede cambiarlo todo
    • usuarios normales solo pueden cambiar sus propios archivos
  • 2.5 – Práctica guiada: “La estación orbital Andrómeda”

    2.5 – Práctica guiada: “La estación orbital Andrómeda”

    La estación espacial Andrómeda necesita organizar a su tripulación.
    Hay tres equipos principales:

    • pilotos
    • ingenieros
    • cientificos

    Cada miembro de la tripulación tendrá acceso solo a determinadas carpetas según su grupo.
    Además, el comandante de la estación deberá poder reorganizar la tripulación, cambiar usuarios de grupo y ajustar propietarios y permisos de archivos.

    Tu misión será convertirte en el administrador del sistema de la estación.


    1. Objetivos de la práctica

    Al finalizar esta práctica, el alumno será capaz de:

    • crear usuarios en Ubuntu,
    • crear grupos de usuarios,
    • añadir usuarios a grupos,
    • cambiar un usuario de grupo,
    • comprobar a qué grupos pertenece un usuario,
    • crear carpetas para distintos equipos,
    • asignar propietario y grupo a carpetas y archivos,
    • modificar permisos con chmod,
    • utilizar chown para cambiar propietario y grupo,
    • verificar que los permisos funcionan correctamente.

    2. Qué vas a aprender

    En Linux, cada archivo y carpeta tiene asociado:

    • un propietario,
    • un grupo,
    • unos permisos.

    Los permisos se pueden definir para:

    • u → usuario propietario,
    • g → grupo,
    • o → otros usuarios.

    Y los permisos básicos son:

    • r → lectura,
    • w → escritura,
    • x → ejecución o acceso.

    3. Preparación inicial

    Antes de empezar, abre una terminal y asegúrate de trabajar con un usuario con permisos de administración.

    Puedes comprobarlo con:

    whoami

    Y probar que tienes permisos de sudo con:

    sudo -v

    4. Crear los grupos de la estación

    Vamos a crear los tres grupos principales de la tripulación.

    sudo groupadd pilotos
    sudo groupadd ingenieros
    sudo groupadd cientificos

    Comprobar que los grupos existen

    getent group pilotos
    getent group ingenieros
    getent group cientificos

    Esto mostrará información del grupo si se ha creado correctamente.


    5. Crear los usuarios de la tripulación

    Ahora vamos a crear varios usuarios.

    Equipo de pilotos

    sudo useradd -m -s /bin/bash luke
    sudo useradd -m -s /bin/bash leia

    Equipo de ingenieros

    sudo useradd -m -s /bin/bash data
    sudo useradd -m -s /bin/bash scotty

    Equipo de científicos

    sudo useradd -m -s /bin/bash ripley
    sudo useradd -m -s /bin/bash spock

    Explicación

    • useradd crea el usuario.
    • -m crea su carpeta personal en /home.
    • -s /bin/bash asigna Bash como shell.

    6. Asignar contraseña a los usuarios

    Para que estos usuarios puedan iniciar sesión, asígnales una contraseña.

    sudo passwd luke
    sudo passwd leia
    sudo passwd data
    sudo passwd scotty
    sudo passwd ripley
    sudo passwd spock

    Puedes usar una contraseña sencilla solo para la práctica, por ejemplo:

    Clave123*

    7. Añadir usuarios a sus grupos

    Ahora asignamos cada usuario a su equipo.

    sudo usermod -aG pilotos luke
    sudo usermod -aG pilotos leia
    
    sudo usermod -aG ingenieros data
    sudo usermod -aG ingenieros scotty
    
    sudo usermod -aG cientificos ripley
    sudo usermod -aG cientificos spock

    Explicación importante

    • usermod modifica un usuario.
    • -aG añade el usuario a uno o varios grupos sin borrar los grupos anteriores.

    8. Comprobar a qué grupos pertenece cada usuario

    Usa alguno de estos comandos:

    groups luke
    groups leia
    groups data
    groups scotty
    groups ripley
    groups spock

    O también:

    id luke
    id data
    id spock

    Esto permite ver:

    • el UID del usuario,
    • el GID principal,
    • los grupos a los que pertenece.

    9. Crear la estructura de carpetas de la estación

    Vamos a crear una zona común de trabajo para la estación.

    sudo mkdir -p /srv/andromeda/pilotos
    sudo mkdir -p /srv/andromeda/ingenieros
    sudo mkdir -p /srv/andromeda/cientificos
    sudo mkdir -p /srv/andromeda/comun

    Verificar la estructura creada

    ls -l /srv
    ls -l /srv/andromeda

    10. Asignar propietario y grupo a las carpetas

    Ahora vamos a asociar cada carpeta con su grupo correspondiente.

    sudo chown root:pilotos /srv/andromeda/pilotos
    sudo chown root:ingenieros /srv/andromeda/ingenieros
    sudo chown root:cientificos /srv/andromeda/cientificos
    sudo chown root:root /srv/andromeda/comun

    Explicación

    Con chown puedes cambiar:

    • el propietario,
    • el grupo,
    • o ambos.

    En este caso:

    • el propietario será root,
    • el grupo será el del equipo correspondiente.

    La sintaxis es:

    sudo chown propietario:grupo ruta

    NOTA: El Comando chgrp

    El comando chgrp se utiliza en Linux para cambiar el grupo asociado a un archivo o carpeta.

    Mientras que chown puede cambiar el propietario y también el grupo, chgrp está pensado específicamente para modificar solo el grupo.

    chgrp grupo archivo_o_carpeta

    sudo chgrp pilotos /srv/andromeda/ruta_estelar.txt

    Con este comando, el archivo ruta_estelar.txt pasará a pertenecer al grupo pilotos.


    ¿Para qué sirve?

    chgrp es útil cuando:

    • queremos que varios usuarios de un mismo grupo puedan acceder a un archivo,
    • no necesitamos cambiar el propietario,
    • queremos reorganizar permisos por grupos de trabajo.

    En una práctica como la de la estación orbital, puede servir para decidir qué equipo debe compartir un documento sin cambiar quién es su dueño.


    Diferencia entre chown y chgrp

    • chown cambia el propietario y, si se quiere, también el grupo.
    • chgrp cambia solo el grupo.


    Por ejemplo:

    sudo chown luke:pilotos archivo.txt

    cambia propietario y grupo.


    En cambio:

    sudo chgrp pilotos archivo.txt

    solo cambia el grupo, manteniendo el mismo propietario.

    11. Asignar permisos a las carpetas

    Queremos que cada grupo pueda entrar en su carpeta, leer y escribir en ella, pero que otros no puedan acceder.

    sudo chmod 770 /srv/andromeda/pilotos
    sudo chmod 770 /srv/andromeda/ingenieros
    sudo chmod 770 /srv/andromeda/cientificos
    sudo chmod 777 /srv/andromeda/comun

    Explicación de los permisos

    770

    • propietario: rwx
    • grupo: rwx
    • otros: ---

    777

    • propietario: rwx
    • grupo: rwx
    • otros: rwx

    La carpeta comun será accesible para todos, mientras que las otras estarán restringidas.


    12. Comprobar los permisos

    ls -ld /srv/andromeda/pilotos
    ls -ld /srv/andromeda/ingenieros
    ls -ld /srv/andromeda/cientificos
    ls -ld /srv/andromeda/comun

    Fíjate en algo como esto:

    drwxrwx--- 2 root pilotos ...

    Eso significa:

    • d → es una carpeta,
    • rwx → permisos del propietario,
    • rwx → permisos del grupo,
    • --- → permisos del resto.

    13. Probar acceso con distintos usuarios

    Ahora toca comprobar si realmente funciona.

    Entrar como un usuario concreto

    Puedes cambiar de usuario con:

    su - luke

    O, si prefieres, ejecutar comandos como otro usuario:

    sudo -u luke ls /srv/andromeda/pilotos
    sudo -u luke ls /srv/andromeda/ingenieros

    Qué debería ocurrir

    • luke sí debería poder entrar en /srv/andromeda/pilotos
    • luke no debería poder entrar en /srv/andromeda/ingenieros

    Prueba varios casos:

    sudo -u luke ls /srv/andromeda/pilotos
    sudo -u luke ls /srv/andromeda/ingenieros
    sudo -u data ls /srv/andromeda/ingenieros
    sudo -u ripley ls /srv/andromeda/cientificos
    sudo -u spock ls /srv/andromeda/pilotos
    ¿Que hace? sudo -u luke ls
    Ejecuta el comando ls como si lo estuviera lanzando el usuario luke. 
    -u luke Le dice a sudo que el comando no se ejecute como tu usuario actual, sino como el usuario luke.

    14. Crear archivos dentro de las carpetas

    Vamos a crear documentos de misión dentro de cada zona.

    sudo touch /srv/andromeda/pilotos/ruta_estelar.txt
    sudo touch /srv/andromeda/ingenieros/reactor.txt
    sudo touch /srv/andromeda/cientificos/informe_biologico.txt
    sudo touch /srv/andromeda/comun/avisos_generales.txt

    Añadimos contenido:


    
    echo "Ruta secreta al sector Omega" | sudo tee /srv/andromeda/pilotos/ruta_estelar.txt
    
    echo "Estado del reactor principal" | sudo tee /srv/andromeda/ingenieros/reactor.txt
    
    echo "Análisis de muestras alienígenas" | sudo tee /srv/andromeda/cientificos/informe_biologico.txt
    
    echo "Reunión general a las 18:00" | sudo tee /srv/andromeda/comun/avisos_generales.txt
    ¿Que hace tee?

    sirve para escribir un texto dentro de un archivo con permisos de administrador.
    El comando tee recoge lo que le llega por la entrada estándar y lo:

    • muestra por pantalla,
    • y además lo guarda en un archivo.

    Como va precedido de sudo, tee se ejecuta con permisos de administrador, por lo que puede escribir en una ruta protegida.

    Saber más

    15. Cambiar propietario de un archivo con chown

    Ahora vamos a usar chown de forma más clara sobre archivos.

    Por ejemplo, el archivo del reactor lo va a gestionar el ingeniero data.

    sudo chown data:ingenieros /srv/andromeda/ingenieros/reactor.txt

    Y el informe biológico será gestionado por spock.

    sudo chown spock:cientificos /srv/andromeda/cientificos/informe_biologico.txt

    Verificar el cambio

    ls -l /srv/andromeda/ingenieros/reactor.txt
    ls -l /srv/andromeda/cientificos/informe_biologico.txt

    16. Cambiar solo el grupo de un archivo

    También puedes cambiar únicamente el grupo.

    Por ejemplo:

    sudo chown :pilotos /srv/andromeda/comun/avisos_generales.txt

    Eso cambia solo el grupo, manteniendo el propietario actual.

    Compruébalo:

    ls -l /srv/andromeda/comun/avisos_generales.txt

    17. Dar permisos concretos a los archivos

    Vamos a ajustar permisos para que:

    • el propietario pueda leer y escribir,
    • el grupo pueda leer,
    • otros no puedan acceder.
    sudo chmod 640 /srv/andromeda/ingenieros/reactor.txt
    sudo chmod 640 /srv/andromeda/cientificos/informe_biologico.txt
    sudo chmod 664 /srv/andromeda/comun/avisos_generales.txt

    Interpretación

    640

    • propietario: lectura y escritura
    • grupo: lectura
    • otros: sin permisos

    664

    • propietario: lectura y escritura
    • grupo: lectura y escritura
    • otros: lectura

    18. Cambiar un usuario de grupo

    Ahora viene una situación de la historia.

    La comandante decide que leia deja el equipo de pilotos y pasa al equipo de ingenieros.

    Primero la añadimos al nuevo grupo:

    sudo usermod -aG ingenieros leia

    Comprobamos sus grupos:

    groups leia

    Ahora leia pertenece a dos grupos: pilotos e ingenieros.

    Quitarla del grupo de pilotos

    Para hacerlo de forma clara en Ubuntu:

    sudo gpasswd -d leia pilotos

    Volvemos a comprobar:

    groups leia

    Ahora debería quedar solo en ingenieros además de su grupo principal.


    19. Crear un nuevo usuario y asignarlo a un grupo

    La estación recibe a un nuevo tripulante: neo.

    sudo useradd -m -s /bin/bash neo
    sudo passwd neo
    sudo usermod -aG cientificos neo

    Comprobar:

    groups neo

    20. Probar qué puede hacer cada usuario

    Haz pruebas reales con comandos como estos:

    sudo -u data cat /srv/andromeda/ingenieros/reactor.txt
    sudo -u luke cat /srv/andromeda/ingenieros/reactor.txt
    sudo -u spock cat /srv/andromeda/cientificos/informe_biologico.txt
    sudo -u leia touch /srv/andromeda/ingenieros/prueba_leia.txt
    sudo -u neo touch /srv/andromeda/cientificos/muestra_01.txt

    Qué observar

    • Un usuario del grupo correcto debería poder trabajar dentro de su carpeta.
    • Un usuario de otro grupo debería recibir un error de permisos.
    • Los archivos deben respetar los permisos establecidos.

    21. Ver propietarios y permisos de toda la estación

    Para revisar toda la estructura:

    ls -lR /srv/andromeda

    Esto te mostrará:

    • carpetas,
    • archivos,
    • propietarios,
    • grupos,
    • permisos.

    22. Recuerda

    Diferencia entre propietario y grupo

    • El propietario es normalmente el usuario dueño del archivo.
    • El grupo permite que varios usuarios compartan acceso a archivos y carpetas.

    Diferencia entre chown y chmod

    • chown cambia el propietario o grupo.
    • chmod cambia los permisos.

    Comandos clave

    Crear grupo

    sudo groupadd nombre_grupo

    Crear usuario

    sudo useradd -m -s /bin/bash nombre_usuario

    Asignar contraseña

    sudo passwd nombre_usuario

    Añadir usuario a grupo

    sudo usermod -aG grupo usuario

    Ver grupos de un usuario

    groups usuario

    Quitar usuario de un grupo

    sudo gpasswd -d usuario grupo

    Cambiar propietario y grupo

    sudo chown propietario:grupo archivo_o_carpeta

    Cambiar permisos

    sudo chmod permisos archivo_o_carpeta

    23. Actividad

    Ahora que ya sabes manejar usuarios y permisos, realiza estas tareas:

    Tarea 1

    Crea un nuevo grupo llamado:

    seguridad

    Tarea 2

    Crea dos usuarios nuevos:

    • trinity
    • morpheo

    Tarea 3

    Añade ambos al grupo seguridad.

    Tarea 4

    Crea la carpeta:

    /srv/andromeda/seguridad

    Tarea 5

    Haz que:

    • el propietario sea root,
    • el grupo sea seguridad,
    • los permisos sean 770.

    Tarea 6

    Crea dentro un archivo llamado:

    protocolo_defensa.txt

    Tarea 7

    Haz que el archivo pertenezca a trinity:seguridad.

    Tarea 8

    Pon permisos 640 al archivo.

    Tarea 9

    Comprueba que:

    • trinity puede leerlo,
    • morpheo puede leerlo,
    • luke no puede acceder.

    25. Planteate las siguientes preguntas.

    1. ¿Qué diferencia hay entre un usuario y un grupo?
    2. ¿Qué hace el comando chown?
    3. ¿Qué hace el comando chmod?
    4. ¿Qué significa el permiso 770?
    5. ¿Qué significa el permiso 640?
    6. ¿Cómo se comprueba a qué grupos pertenece un usuario?
    7. ¿Qué comando se usa para eliminar a un usuario de un grupo?
    8. ¿Por qué es útil trabajar con grupos en lugar de dar permisos usuario por usuario?

    La estación orbital Andrómeda ya está organizada.
    Cada tripulante pertenece a su equipo, cada carpeta está protegida y los documentos sensibles solo son accesibles por el personal autorizado.
    Has completado con éxito tu primera misión como administrador de sistemas espaciales.


    Tabla de comandos y opciones principales

    ComandoOpción / sintaxisExplicación
    groupaddgroupadd nombre_grupoCrea un grupo nuevo en el sistema.
    useradduseradd nombre_usuarioCrea un usuario.
    useradd-mCrea automáticamente la carpeta personal del usuario en /home.
    useradd-s /bin/bashAsigna la shell Bash al usuario.
    passwdpasswd nombre_usuarioEstablece o cambia la contraseña de un usuario.
    usermodusermod usuarioModifica la configuración de un usuario existente.
    usermod-aG grupo usuarioAñade el usuario a un grupo secundario sin quitarlo de los demás.
    groupsgroups usuarioMuestra los grupos a los que pertenece un usuario.
    idid usuarioMuestra UID, GID y grupos del usuario.
    mkdirmkdir carpetaCrea una carpeta.
    mkdir-pCrea la ruta completa aunque haya varios niveles de carpetas.
    touchtouch archivoCrea un archivo vacío si no existe.
    lslsLista archivos y carpetas.
    ls-lMuestra la lista en formato largo, con permisos, propietario, grupo, tamaño, etc.
    ls-dMuestra información de la carpeta en sí, no de su contenido.
    ls-RLista el contenido de forma recursiva, incluyendo subcarpetas.
    chownchown propietario archivoCambia el propietario de un archivo o carpeta.
    chownchown propietario:grupo archivoCambia propietario y grupo a la vez.
    chownchown :grupo archivoCambia solo el grupo del archivo o carpeta.
    chown-RAplica el cambio de propietario/grupo de forma recursiva.
    chmodchmod permisos archivoCambia los permisos de un archivo o carpeta.
    chmod770Propietario y grupo con todos los permisos; otros sin acceso.
    chmod750Propietario con todos los permisos; grupo puede leer y entrar; otros sin acceso.
    chmod640Propietario puede leer y escribir; grupo solo leer; otros sin acceso.
    chmod664Propietario y grupo pueden leer y escribir; otros solo leer.
    chmod777Todos pueden leer, escribir y ejecutar/entrar.
    chmod-RCambia permisos de forma recursiva.
    gpasswdgpasswd -d usuario grupoElimina un usuario de un grupo.
    susu - usuarioCambia a otro usuario cargando su entorno.
    sudosudo comandoEjecuta un comando con privilegios de administrador.
    sudosudo -u usuario comandoEjecuta un comando como otro usuario.
    getentgetent group nombre_grupoConsulta información de un grupo en la base de datos del sistema.
    whoamiwhoamiMuestra el usuario actual.
    teetee archivoEscribe en un archivo a partir de la entrada estándar. Muy útil junto con echo.
    catcat archivoMuestra el contenido de un archivo.

    Tabla permisos numéricos

    ValorSignificado
    7rwx = lectura, escritura y ejecución
    6rw- = lectura y escritura
    5r-x = lectura y ejecución
    4r-- = solo lectura
    3-wx = escritura y ejecución
    2-w- = solo escritura
    1--x = solo ejecución
    0--- = sin permisos

    Cómo leer un permiso como 770

    PosiciónValorSignificado
    Propietario7rwx
    Grupo7rwx
    Otros0---

    Ejemplos rápidos

    ObjetivoComando
    Crear gruposudo groupadd pilotos
    Crear usuario con home y bashsudo useradd -m -s /bin/bash luke
    Añadir usuario a gruposudo usermod -aG pilotos luke
    Ver grupos de un usuariogroups luke
    Cambiar propietario y gruposudo chown data:ingenieros archivo.txt
    Cambiar solo gruposudo chown :cientificos archivo.txt
    Dar permisos al propietario y gruposudo chmod 770 carpeta
    Quitar a un usuario de un gruposudo gpasswd -d leia pilotos

  • 2.6 – Usuarios y Huellas Digitales en Linux

    2.6 – Usuarios y Huellas Digitales en Linux

    whoami

    El equivalente digital de mirarse al espejo.
    Muestra el usuario efectivo que está ejecutando el comando.
    Perfecto para explicar la diferencia entre:

    • usuario real (el que inicia sesión),
    • usuario efectivo (el que el sistema usa para permisos, especialmente tras un sudo).

    id

    Un pequeño radiotelescopio hacia tu identidad numérica.
    Muestra:

    • UID (identificador del usuario)
    • GID (grupo principal)
    • grupos secundarios
      Es una forma directa de ver permisos y roles dentro del sistema. Ideal para ejercicios de administración y forense.

    who / w / users

    El “quién está ahora mismo en la nave”.
    Sirve para ver sesiones activas y cómo han entrado:

    • tty
    • pts (sesiones remotas)
    • SSH
    • tiempo conectado

    • En ciberseguridad es una herramienta rápida para detectar conexiones sospechosas.

    env

    El baúl entero de variables de entorno.
    Aquí viven cosas como:

    • $USER
    • $HOME
    • $SHELL
    • $PATH

      Además permite explicar a los alumnos por qué una aplicación “sabe” dónde buscar binarios o dónde está su carpeta de configuración.

    echo $USER

    Una forma simple de leer la variable que indica el nombre del usuario que ha iniciado sesión.
    Comparar whoami vs $USER es didáctico:
    $USER → quien inició sesión
    whoami → usuario efectivo (útil para mostrar cómo sudo cambia el contexto)


    echo $HOME

    Viene genial para scripts o explicaciones sobre la organización del sistema.
    Muestra la ruta al directorio personal, que siempre es sagrado en Linux.


    echo $SHELL

    Permite enseñar la diferencia entre bash, zsh, fish…
    Ideal para que entiendan por qué su terminal “se comporta raro” tras instalar algo.


    hostname

    La identidad pública del sistema en la red.
    Junto con hostname -I, sirve para explicar la distinción entre:

    • identidad del equipo,
    • interfaces,
    • direcciones IP que usa para comunicarse.

    logname

    La versión más purista de “quién inició esta sesión”, incluso si has hecho un su o un sudo.
    Muy útil en prácticas de forense porque te permite reconstruir acciones de usuarios.


    tty

    Muestra el dispositivo de terminal actual.
    En remoto se verá algo como /dev/pts/1.
    Perfecto para entender:

    • sesiones locales,
    • sesiones remotas,
    • multiplexación de terminales.

    ps aux | grep $USER

    Una puerta a ver “qué está ejecutando realmente tu identidad”.
    A los alumnos les ayuda a comprender procesos, permisos, señales y contextos.


    finger (si lo instalas)

    Pinta un pequeño perfil del usuario:

    • shell
    • home
    • nombre real

      Antiguo pero didáctico como pocas cosas.

    Actividad: “¿Quién eres en esta máquina?” – Identidad y sesiones en Linux

    Imagina que el sistema es una estación espacial. Cada alumno entra por una compuerta distinta, a veces cambia de traje (sudo), y el objetivo es reconstruir quién hizo qué.


    Todo ocurre en un Ubuntu normal.


    FASE 1 — Identidad básica

    Ejecuta:

    
    
    
    
    
    whoami
    echo $USER
    id
    logname
    

    Descubrir que el sistema te reconoce por varias “capas”.

    Explicación:

    • whoami → usuario efectivo.
    • $USER → usuario que inició sesión.
    • id → UID, GID, grupos.
    • logname → el user original aunque hayan hecho su.

    Pequeño reto:
    Pídeles que intenten entender por qué sudo whoami devuelve root,
    pero echo $USER sigue mostrando su usuario normal.


    FASE 2 — Dónde están realmente

    Ejecutar

    
    
    
    
    
    pwd
    echo $HOME
    echo $SHELL
    tty
    

    Esto muestra:

    • dónde están,
    • cuál es su shell,
    • qué terminal están usando (local, SSH, pts…).

    Ejercicio: Compartir un terminal local (tty1) con una sesión SSH


    FASE 3 — Quién más está en la nave

    Ahora miramos el estado de la estación:

    
    
    
    
    
    who
    w
    users
    hostname
    hostname -I
    

    Objetivo: identificar todas las sesiones activas.
    Puedes entrar desde otra máquina para ver “un intruso”.

    Mini-misión:
    Que usen who para averiguar:

    • quién está conectado,
    • desde qué terminal,
    • desde qué IP si es SSH,
    • desde cuándo.

    Esto introduce sin ruido en análisis forense real.


    FASE 4 — Cambio de identidad

    
    
    
    
    
    sudo -i
    whoami
    echo $USER
    id
    logname
    tty
    

    Aquí ocurre la magia:

    • whoami → root
    • $USER → su usuario original
    • logname → quien realmente abrió la sesión
    • tty → la misma porque no abren una nueva


    FASE 5 — Ver qué hace cada identidad

    En otra terminal, que ejecuten:

    
    
    
    
    
    ps aux | grep $USER
    ps aux | grep root
    

    Fijate que root suele llevar servicios, demonios, etc.

    FASE 6 — Prueba forense

    Prueba a ejecutar con un usuario un comando secreto en su sesión, por ejemplo:

    
    
    
    
    
    mkdir /tmp/estacion-alpha
    echo "Hola profe" > /tmp/mensaje.txt
    touch ~/algo_raro
    

    Luego cambia de usuario :

    “Reconstruid qué usuarios han hecho qué”

    Utilizando:

    
    
    
    
    
    ls -l /tmp
    ls -l /home/*
    who
    logname
    id username
    

    La identidad del sistema queda impregnada en permisos, UID, GID, sesiones y ficheros creados.


    Hackeo benévolo

    Se hace SSH desde otro equipo con:

    
    
    
    
    
    ssh usuario@IP
    

    Luego ejecuta:

    
    
    
    
    
    who
    w
    tty
    hostname -I
    

    Los demás deben encontrar:

    • quién ha entrado
    • desde qué IP
    • en qué terminal
    • cuánto tiempo lleva conectado
      Esta parte siempre les encanta porque parece CSI, pero sin dramatismos digitales.