En el Módulo 1 dibujaste el mapa: sabes qué es /etc, qué distingue /opt de /srv y por qué /var contiene lo que crece. Pero conocer un mapa y recorrer el terreno son cosas distintas. Esta lección es el recorrido.
Moverse por el sistema de archivos parece trivial —cd para ir, ls para mirar— y sin embargo es donde se pierde más tiempo a lo largo de una carrera. La diferencia entre alguien que navega con fluidez y alguien que no está en detalles concretos: saber volver al directorio anterior con dos teclas, leer la salida de ls -l de un vistazo, entender qué te dice exactamente cada marca de tiempo de un archivo, y no confundir «esto ocupa 4 KB» con «esto declara 18 bytes».
Un aviso antes de empezar: hasta el final de esta lección no vas a modificar nada. Todos los comandos que verás son de solo lectura. Es deliberado: primero se aprende a mirar, y en la lección siguiente se aprende a tocar.
Contenido
pwdy el directorio de trabajocden todas sus formas- Rutas absolutas y relativas en la práctica
.y..: entradas reales del directoriolsa fondo- Leer
ls -lcolumna a columna tree: ver la estructura de un vistazostaty las tres marcas de tiempofile: qué es un archivo de verdadduydf: cuánto ocupa y cuánto queda- No perderse nunca: hábitos de orientación
- Práctica guiada: recorrido por el árbol de Tramontana
pwd y el directorio de trabajo
pwd y el directorio de trabajoCada proceso del sistema tiene un directorio de trabajo actual (current working directory, cwd): el punto del árbol desde el que interpreta las rutas relativas. Tu shell es un proceso y también tiene el suyo.
pwd (print working directory) responde siempre con una ruta absoluta, desde /.
Al iniciar sesión, tu directorio de trabajo es tu directorio personal, que en srv-tramontana es /home/operador. Por eso el prompt muestra ~: es la abreviatura del home.
pwd tiene dos opciones que solo cobran sentido cuando hay enlaces simbólicos por medio (lección 02-06):
| Opción | Comportamiento |
|---|---|
-L (por defecto) |
Muestra la ruta lógica, tal como llegaste, con los enlaces sin resolver |
-P |
Muestra la ruta física real, resolviendo todos los enlaces |
operador@srv-tramontana:/opt/tramontana/app$ pwd
/opt/tramontana/app
operador@srv-tramontana:/opt/tramontana/app$ pwd -P
/opt/tramontana/releases/2026-08-18Esa diferencia será importante cuando Tramontana adopte el patrón de despliegue con enlaces. De momento, quédate con que pwd -P te dice dónde estás de verdad.
cd en todas sus formas
cd en todas sus formascd (change directory) cambia el directorio de trabajo. Es un builtin, y en la lección 02-01 viste por qué tiene que serlo.
| Forma | Qué hace |
|---|---|
cd /ruta/absoluta |
Va a esa ruta, independientemente de dónde estés |
cd subdirectorio |
Baja a un hijo del directorio actual |
cd .. |
Sube al directorio padre |
cd ../.. |
Sube dos niveles |
cd (sin argumentos) |
Va a tu home |
cd ~ |
Lo mismo, explícito |
cd ~operador |
Al home de ese usuario |
cd - |
Vuelve al directorio anterior |
cd / |
A la raíz |
Recorrido completo:
operador@srv-tramontana:~$ pwd
/home/operador
operador@srv-tramontana:~$ cd /var/log/tramontana
operador@srv-tramontana:/var/log/tramontana$ pwd
/var/log/tramontana
operador@srv-tramontana:/var/log/tramontana$ cd ..
operador@srv-tramontana:/var/log$ pwd
/var/log
operador@srv-tramontana:/var/log$ cd
operador@srv-tramontana:~$ pwd
/home/operadorFíjate en cómo el prompt refleja el directorio actual. Es tu instrumento de orientación permanente y no cuesta nada mirarlo.
Las dos formas que más tiempo ahorran, y que mucha gente no conoce:
cd - alterna entre los dos últimos directorios, como el botón «atrás». Al usarlo, Bash imprime a dónde ha ido:
operador@srv-tramontana:~$ cd /etc/tramontana
operador@srv-tramontana:/etc/tramontana$ cd /var/log/tramontana
operador@srv-tramontana:/var/log/tramontana$ cd -
/etc/tramontana
operador@srv-tramontana:/etc/tramontana$ cd -
/var/log/tramontanaEs perfecto cuando estás comparando la configuración con los logs: dos teclas para saltar de un lado a otro.
~usuario es la ruta del home de otro usuario, resuelta por el shell:
operador@srv-tramontana:~$ echo ~
/home/operador
operador@srv-tramontana:~$ echo ~alumno
/home/alumno
operador@srv-tramontana:~$ echo ~root
/rootOjo con ~root: es /root, no /home/root. La cuenta de administración tiene su home fuera de /home precisamente para que siga siendo accesible aunque /home esté en una partición que no se ha montado, algo que importa en la recuperación del sistema (lección 07-01).
Un comportamiento a tener en cuenta: si cd falla, no te mueves.
operador@srv-tramontana:~$ cd /etc/tramontanas
-bash: cd: /etc/tramontanas: No existe el fichero o el directorio
operador@srv-tramontana:~$ pwd
/home/operadorEl prompt no cambió y pwd lo confirma. Este es el detalle que hacía peligroso el ; de la lección anterior: cd falla, pero el comando siguiente se ejecuta igual, en el sitio equivocado.
- Rutas absolutas y relativas en la práctica
La definición la viste en el Módulo 1. Aquí la vas a usar.
- Absoluta: empieza por
/. Significa lo mismo desde cualquier sitio. - Relativa: no empieza por
/. Se interpreta desde el directorio actual.
El árbol de Tramontana que vas a usar como referencia:
/
├── etc/
│ └── tramontana/
│ └── app.conf
├── opt/
│ └── tramontana/
│ └── app/
│ ├── ejecutable
│ ├── plantillas/
│ └── version.txt
├── srv/
│ └── tramontana/
│ └── backups/
├── var/
│ └── log/
│ └── tramontana/
│ ├── acceso.log
│ └── errores.log
└── home/
└── operador/
├── scripts/
└── datos/
├── reservas.csv
└── casas.txtEjercicios de traducción. Estás en /var/log/tramontana. ¿Cómo llegas a cada destino de las dos maneras?
| Destino | Ruta absoluta | Ruta relativa |
|---|---|---|
errores.log (mismo dir.) |
/var/log/tramontana/errores.log |
errores.log o ./errores.log |
El directorio /var/log |
/var/log |
.. |
/etc/tramontana/app.conf |
/etc/tramontana/app.conf |
../../../etc/tramontana/app.conf |
/opt/tramontana/app |
/opt/tramontana/app |
../../../opt/tramontana/app |
| Tu home | /home/operador |
~ o ../../../home/operador |
Comprobación práctica de la tercera fila:
Tres .. porque hay que subir de tramontana a log, de log a var, y de var a /. Cuenta los niveles del prompt y te salen solos.
Cuándo usar cada una:
| Contexto | Usa | Por qué |
|---|---|---|
| Trabajo interactivo, cerca de donde estás | Relativa | Más corta, menos que teclear |
| Scripts (Módulo 4) | Absoluta, siempre | El script puede ejecutarse desde cualquier directorio |
| Tareas de cron (03-07) | Absoluta, siempre | Cron arranca en un directorio que no controlas |
| Configuración de servicios | Absoluta | El servicio no comparte tu directorio de trabajo |
| Documentar un procedimiento | Absoluta | Quien lo lea no sabe dónde estabas |
Regla mnemotécnica: relativa para tus dedos, absoluta para las máquinas.
. y ..: entradas reales del directorio
. y ..: entradas reales del directorio. es el directorio actual y .. es el padre. Pero no son un truco del shell: son entradas reales dentro de cada directorio, escritas en disco.
operador@srv-tramontana:~$ ls -la /home/operador/datos
total 16
drwxr-xr-x 2 operador operador 4096 ago 18 08:11 .
drwxr-x--- 5 operador operador 4096 ago 18 08:11 ..
-rw-r--r-- 1 operador operador 418 ago 17 19:40 casas.txt
-rw-r--r-- 1 operador operador 1204 ago 18 07:55 reservas.csvLas dos primeras líneas son entradas de verdad, con sus permisos, su propietario y su fecha. Comprobación definitiva:
operador@srv-tramontana:~$ ls -ldi /home/operador/datos /home/operador/datos/.
262148 drwxr-xr-x 2 operador operador 4096 ago 18 08:11 /home/operador/datos
262148 drwxr-xr-x 2 operador operador 4096 ago 18 08:11 /home/operador/datos/.El mismo número, 262148. Ese número es el inodo, y que coincida demuestra que . y el directorio son literalmente el mismo objeto. Los inodos son el tema de la lección 02-06; guarda este dato.
Dos consecuencias prácticas:
./ es obligatorio para ejecutar un programa del directorio actual. Como viste en 02-01, el directorio actual no está en el PATH:
operador@srv-tramontana:~/scripts$ informe.sh
-bash: informe.sh: orden no encontrada
operador@srv-tramontana:~/scripts$ ./informe.sh
Generando informe de reservas..../ protege frente a nombres que empiezan por guion, como viste con el separador --. rm ./-informe.txt funciona siempre.
Un detalle sobre el directorio raíz: en /, la entrada .. apunta a sí misma. cd /.. te deja en /. El árbol termina ahí.
ls a fondo
ls a fondols es el comando que más veces ejecutarás en tu vida. Merece la pena conocerlo bien.
| Opción | Qué hace |
|---|---|
-l |
Formato largo: permisos, propietario, tamaño, fecha |
-a |
Muestra todo, incluidos los ocultos, . y .. |
-A |
Como -a pero sin . ni .. (casi siempre más útil) |
-h |
Tamaños legibles (K, M, G). Requiere -l |
-t |
Ordena por fecha de modificación, más reciente primero |
-S |
Ordena por tamaño, mayor primero |
-r |
Invierte el orden |
-R |
Recursivo: entra en los subdirectorios |
-d |
Muestra el directorio en sí, no su contenido |
-i |
Muestra el número de inodo |
-1 |
Un elemento por línea (útil con tuberías) |
-F |
Añade un símbolo según el tipo: / dir., * ejecutable, @ enlace |
--color=auto |
Colorea por tipo (ya viene como alias en Ubuntu) |
Sin opciones, ls es escueto porque el shell antiguo lo era:
Combinaciones que se usan de verdad:
# La más común: todo, largo, tamaños legibles
operador@srv-tramontana:~$ ls -lah /var/log/tramontana
total 32K
drwxr-x--- 2 root adm 4,0K ago 18 09:00 .
drwxrwxr-x 12 root syslog 4,0K ago 18 00:00 ..
-rw-r----- 1 root adm 18K ago 18 09:14 acceso.log
-rw-r----- 1 root adm 6,2K ago 18 09:02 errores.log
# Lo último que ha cambiado, arriba del todo: para diagnosticar
operador@srv-tramontana:~$ ls -lt /etc/tramontana
total 4
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
# Lo último abajo: mejor cuando hay muchos archivos, porque queda junto al prompt
operador@srv-tramontana:~$ ls -ltr /var/log
...
-rw-r----- 1 syslog adm 124832 ago 18 09:15 syslog
# Los más grandes primero: para encontrar qué llena un disco
operador@srv-tramontana:~$ ls -lhS /var/log/tramontana
-rw-r----- 1 root adm 18K ago 18 09:14 acceso.log
-rw-r----- 1 root adm 6,2K ago 18 09:02 errores.logls -ltr merece un comentario: al ordenar de más antiguo a más reciente, lo último modificado queda justo encima del prompt, donde tienes la vista. En un directorio con doscientos archivos, eso es la diferencia entre ver la respuesta y tener que buscarla.
-d es la opción menos intuitiva y más necesaria. Sin ella, ls -l sobre un directorio lista su contenido; con ella, describe el directorio mismo:
operador@srv-tramontana:~$ ls -l /etc/tramontana
total 4
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
operador@srv-tramontana:~$ ls -ld /etc/tramontana
drwxr-x--- 2 root tramontana 4096 ago 18 08:30 /etc/tramontanaLa primera te dice qué hay dentro; la segunda te dice quién puede entrar. Cuando llegues a los permisos en la lección 02-07, ls -ld será tu herramienta principal.
-R recorre el árbol entero. Úsalo con cuidado: ls -R / produce cientos de miles de líneas.
operador@srv-tramontana:~$ ls -R /opt/tramontana
/opt/tramontana:
app
/opt/tramontana/app:
ejecutable plantillas version.txt
/opt/tramontana/app/plantillas:
confirmacion.html factura.html
- Leer
ls -l columna a columna
ls -l columna a columnaEsta salida hay que saber leerla de un vistazo, porque contiene casi toda la información relevante de un archivo:
operador@srv-tramontana:~$ ls -l /var/log/tramontana/acceso.log
-rw-r----- 1 root adm 18432 ago 18 09:14 /var/log/tramontana/acceso.logDesmontada:
| Columna | Valor | Significado |
|---|---|---|
| 1 (1er carácter) | - |
Tipo: archivo regular. d directorio, l enlace, c/b dispositivo, s socket, p tubería |
| 1 (resto) | rw-r----- |
Permisos: tres grupos de tres. Lección 02-07 |
| 2 | 1 |
Número de enlaces duros. Lección 02-06 |
| 3 | root |
Propietario |
| 4 | adm |
Grupo propietario |
| 5 | 18432 |
Tamaño en bytes (con -h, en unidades legibles) |
| 6 | ago 18 09:14 |
Fecha de última modificación (mtime) |
| 7 | acceso.log |
Nombre |
Un detalle de la sexta columna: ls muestra la hora si el archivo se modificó en los últimos seis meses, y el año si es más antiguo. Esa asimetría desconcierta la primera vez:
operador@srv-tramontana:~$ ls -l /etc/hostname /var/log/tramontana/acceso.log
-rw-r--r-- 1 root root 16 jun 12 2025 /etc/hostname
-rw-r----- 1 root adm 18432 ago 18 09:14 /var/log/tramontana/acceso.logSi quieres fechas completas y sin ambigüedad:
operador@srv-tramontana:~$ ls -l --time-style=full-iso /var/log/tramontana/acceso.log
-rw-r----- 1 root adm 18432 2026-08-18 09:14:37.482910233 +0200 /var/log/tramontana/acceso.logLa segunda columna, el número de enlaces, tiene un comportamiento que sorprende: en los directorios nunca vale 1.
operador@srv-tramontana:~$ ls -ld /opt/tramontana/app
drwxr-xr-x 4 root root 4096 ago 18 08:30 /opt/tramontana/appVale 4 porque cuentan: la entrada app en /opt/tramontana, la entrada . dentro de app, y las entradas .. de sus dos subdirectorios. El número de enlaces de un directorio es 2 + el número de subdirectorios que contiene. Es un truco para contar subdirectorios sin entrar, y quedará completamente claro en la lección 02-06.
Y el tamaño de un directorio (4096) no es lo que contiene: es lo que ocupa la propia lista de nombres. Para saber lo que contiene está du, en el apartado 10.
tree: ver la estructura de un vistazo
tree: ver la estructura de un vistazotree muestra la jerarquía dibujada. No viene instalado por defecto en Ubuntu Server:
operador@srv-tramontana:~$ tree
Orden «tree» no encontrada, pero se puede instalar con:
sudo apt install tree
operador@srv-tramontana:~$ sudo apt install -y tree(La gestión de paquetes se estudia en la lección 05-03; aquí lo instalamos y seguimos.)
operador@srv-tramontana:~$ tree /opt/tramontana
/opt/tramontana
└── app
├── ejecutable
├── plantillas
│ ├── confirmacion.html
│ └── factura.html
└── version.txt
3 directories, 4 filesOpciones imprescindibles:
| Opción | Qué hace |
|---|---|
-L n |
Limita la profundidad a n niveles |
-d |
Solo directorios |
-a |
Incluye ocultos |
-h |
Muestra tamaños legibles |
-F |
Añade / a los directorios |
--du |
Suma el tamaño de cada rama |
-L es prácticamente obligatoria en directorios grandes:
operador@srv-tramontana:~$ tree -L 1 /
/
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── varAhí ves algo interesante: bin, lib y sbin aparecen con una flecha. Son enlaces simbólicos a directorios dentro de /usr, resultado de la reorganización /usr-merge que hicieron las distribuciones modernas. La lección 02-06 explica exactamente qué significa esa flecha.
Combinación muy útil para documentar la estructura de un proyecto:
operador@srv-tramontana:~$ tree -d -L 2 /var
/var
├── backups
├── cache
├── lib
├── log
│ ├── apt
│ └── tramontana
├── spool
└── tmp
stat y las tres marcas de tiempo
stat y las tres marcas de tiempols -l da un resumen. stat da todo:
operador@srv-tramontana:~$ stat /home/operador/datos/reservas.csv
Fichero: /home/operador/datos/reservas.csv
Tamaño: 1204 Bloques: 8 Bloque E/S: 4096 fichero regular
Dispositivo: 8,2 Nodo-i: 262151 Enlaces: 1
Acceso: (0644/-rw-r--r--) Uid: ( 1001/operador) Gid: ( 1001/operador)
Acceso: 2026-08-18 09:20:11.104283761 +0200
Modificación: 2026-08-18 07:55:02.882910233 +0200
Cambio: 2026-08-18 07:55:02.882910233 +0200
Creación: 2026-08-10 12:03:44.000000000 +0200Lo que aporta sobre ls -l:
- El número de inodo (262151) y el dispositivo donde vive.
- Los permisos en octal y simbólico a la vez (
0644/-rw-r--r--), muy útil para la lección 02-07. - Los UID y GID numéricos además de los nombres.
- Los bloques realmente ocupados.
- Y las marcas de tiempo con precisión de nanosegundos.
Las tres marcas clásicas se confunden constantemente. Esta tabla resuelve la confusión:
| Marca | Nombre | Se actualiza cuando... | No se actualiza cuando... |
|---|---|---|---|
| atime | Acceso | Se lee el contenido (cat, less) |
Solo miras sus metadatos con ls |
| mtime | Modificación | Cambia el contenido | Cambian los permisos o el propietario |
| ctime | Cambio de inodo | Cambia el contenido o los metadatos | Nunca lo puedes fijar tú a mano |
El error más extendido es creer que ctime significa creation time. No es así: es change time, el momento en que cambió el inodo. Cambiar los permisos de un archivo actualiza su ctime pero no su mtime.
Demostración:
operador@srv-tramontana:~$ stat -c '%y %z' datos/casas.txt
2026-08-17 19:40:10.000000000 +0200 2026-08-17 19:40:10.000000000 +0200
operador@srv-tramontana:~$ chmod 640 datos/casas.txt
operador@srv-tramontana:~$ stat -c '%y %z' datos/casas.txt
2026-08-17 19:40:10.000000000 +0200 2026-08-18 09:31:55.771820102 +0200El mtime (%y) no se movió: el contenido no cambió. El ctime (%z) sí: el inodo se modificó al cambiar los permisos. Esta distinción es la base de la detección de intrusiones (lección 06-04): un atacante puede falsificar el mtime, pero no el ctime.
La cuarta línea, Creación (birth time), es relativamente moderna. Existe en ext4 y otros sistemas de archivos actuales, pero no todas las herramientas la exponen y no se puede consultar de forma portable.
Un detalle sobre atime que conviene conocer: actualizarlo cada vez que se lee un archivo implica una escritura en disco por cada lectura, lo que sería un desastre de rendimiento. Por eso Linux monta los sistemas de archivos con la opción relatime, que solo actualiza atime si es más antiguo que mtime o si han pasado más de 24 horas. Consecuencia: el atime que ves es aproximado. No lo uses para auditoría precisa.
stat acepta formatos personalizados con -c:
operador@srv-tramontana:~$ stat -c '%n: %s bytes, permisos %a, dueño %U:%G' datos/*
datos/casas.txt: 418 bytes, permisos 640, dueño operador:operador
datos/reservas.csv: 1204 bytes, permisos 644, dueño operador:operadorEsa forma es la que usarás en los scripts del Módulo 4 para generar informes.
file: qué es un archivo de verdad
file: qué es un archivo de verdadEn Windows, la extensión determina el tipo. En Linux la extensión es solo parte del nombre: no significa nada para el sistema. Lo que determina el tipo es el contenido, y quien lo interpreta es el programa que lo abre.
file examina los primeros bytes de un archivo y los compara con una base de datos de firmas conocidas (los números mágicos):
operador@srv-tramontana:~$ file /home/operador/datos/*
/home/operador/datos/casas.txt: UTF-8 Unicode text
/home/operador/datos/reservas.csv: CSV text
operador@srv-tramontana:~$ file /opt/tramontana/app/ejecutable
/opt/tramontana/app/ejecutable: ELF 64-bit LSB pie executable, x86-64,
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, ...
operador@srv-tramontana:~$ file /etc/tramontana /dev/null /dev/sda
/etc/tramontana: directory
/dev/null: character special (1/3)
/dev/sda: block special (8/0)Prueba definitiva de que la extensión no manda:
operador@srv-tramontana:~$ cp datos/casas.txt /tmp/casas.jpg
operador@srv-tramontana:~$ file /tmp/casas.jpg
/tmp/casas.jpg: UTF-8 Unicode textSe llama .jpg y sigue siendo texto. file no se deja engañar por el nombre.
Casos en los que file te salva de un problema:
# ¿Con qué está comprimido este archivo que me han pasado?
operador@srv-tramontana:~$ file /srv/tramontana/backups/copia-2026-08-17
/srv/tramontana/backups/copia-2026-08-17: gzip compressed data, from Unix
# ¿Por qué el script falla con un error raro?
operador@srv-tramontana:~$ file scripts/informe.sh
scripts/informe.sh: Bourne-Again shell script, ASCII text executable,
with CRLF line terminatorsEse último ejemplo es un clásico: with CRLF line terminators significa que el archivo tiene finales de línea de Windows. Bash intenta ejecutar /bin/bash\r y falla con un mensaje incomprensible. file da el diagnóstico en un segundo.
Opciones útiles:
| Opción | Qué hace |
|---|---|
-b |
Solo el tipo, sin el nombre del archivo |
-i |
Devuelve el tipo MIME (text/plain, application/gzip) |
-L |
Sigue los enlaces simbólicos |
Hábito profesional: pasa file a todo archivo desconocido antes de abrirlo. En la lección 02-05 verás por qué hacer cat de un binario destroza tu terminal; file es la comprobación que lo evita.
du y df: cuánto ocupa y cuánto queda
du y df: cuánto ocupa y cuánto quedaDos comandos que se confunden y responden a preguntas distintas:
df(disk free): cuánto espacio queda en los sistemas de archivos montados. Pregunta al sistema de archivos.du(disk usage): cuánto ocupa un directorio concreto. Recorre y suma.
operador@srv-tramontana:~$ df -h
S.ficheros Tamaño Usados Disp Uso% Montado en
tmpfs 389M 1,4M 388M 1% /run
/dev/sda2 23G 6,7G 15G 30% /
tmpfs 1,9G 0 1,9G 0% /dev/shm
tmpfs 5,0M 0 5,0M 0% /run/lock
/dev/sda1 1,1G 6,4M 1,1G 1% /boot/efiAhí ves el disco de 23 GB al 30 % que conoces de la instalación. Las líneas tmpfs son sistemas de archivos en memoria RAM, no en disco: por eso /run y /dev/shm desaparecen al reiniciar.
Opción imprescindible que casi nadie usa:
operador@srv-tramontana:~$ df -hi /
S.ficheros Nodos NUsados NLibres NUso% Montado en
/dev/sda2 1,5M 112K 1,4M 8% /-i muestra los inodos, no los bytes. Un disco puede tener espacio libre y aun así dar «No queda espacio en el dispositivo» si se han agotado los inodos, típicamente por millones de archivos diminutos. Es una incidencia que desconcierta a quien no sabe que existe, y df -hi es el diagnóstico en un segundo.
du responde a la pregunta contraria:
| Opción | Qué hace |
|---|---|
-s |
Resumen: solo el total, sin desglosar |
-h |
Legible |
-c |
Añade una línea de total al final |
-d n |
Baja n niveles en el desglose |
--apparent-size |
Tamaño declarado, no el ocupado en disco |
-x |
No cruza a otros sistemas de archivos |
Sin -s, du desglosa cada subdirectorio, lo que en / produce una avalancha. Con -d 1 obtienes el desglose de un nivel, que es lo que quieres para buscar culpables:
operador@srv-tramontana:~$ sudo du -h -d 1 /var/log
4,0K /var/log/apt
26K /var/log/tramontana
8,0K /var/log/private
1,3M /var/logLa última línea es el total de /var/log, incluidos los archivos sueltos que no están en ningún subdirectorio.
La diferencia entre tamaño declarado y espacio ocupado explica una discrepancia que confunde:
operador@srv-tramontana:~$ echo "hola" > /tmp/prueba.txt
operador@srv-tramontana:~$ ls -l /tmp/prueba.txt
-rw-rw-r-- 1 operador operador 5 ago 18 09:45 /tmp/prueba.txt
operador@srv-tramontana:~$ du -h /tmp/prueba.txt
4,0K /tmp/prueba.txt
operador@srv-tramontana:~$ du -h --apparent-size /tmp/prueba.txt
5 /tmp/prueba.txtEl archivo declara 5 bytes, pero ocupa 4 KB porque el sistema de archivos asigna espacio en bloques y el bloque mínimo de ext4 es de 4 KB. Un directorio con cien mil archivos de 5 bytes ocupa 400 MB reales.
Por eso du (que mide lo ocupado) y df (que mide lo libre en el dispositivo) pueden no cuadrar. Otra causa clásica de descuadre: un archivo borrado que sigue abierto por un proceso. Desaparece del árbol, así que du no lo ve, pero el espacio no se libera hasta que el proceso lo cierra, así que df sí lo cuenta. Es el motivo por el que borrar un log enorme sin reiniciar el servicio no libera espacio, y lo retomarás en la lección 05-07.
- No perderse nunca: hábitos de orientación
Tres costumbres que evitan el 90 % de los sustos:
1. Lee el prompt antes de cada comando destructivo. El prompt de Ubuntu ya muestra el directorio actual. No cuesta nada mirarlo, y en el instante anterior a un rm es lo que separa borrar lo correcto de borrar lo otro.
2. pwd como reflejo. Tras cualquier cd encadenado, tras volver de una pausa, tras conectarte por SSH a otra máquina. Es gratis.
3. Antes de actuar, mira. El patrón que ya viste en 02-01 y que se repetirá todo el curso:
operador@srv-tramontana:~$ ls -la /srv/tramontana/backups/temporales # 1. mirar
operador@srv-tramontana:~$ pwd # 2. confirmar dónde estoy
operador@srv-tramontana:~$ cd /srv/tramontana/backups/temporales && ... # 3. actuar con &&Un cuarto hábito, para más adelante: cuando trabajes en varios servidores a la vez, personaliza el prompt para que muestre el nombre de la máquina en color distinto. Es la forma de no ejecutar en producción lo que ibas a ejecutar en pruebas. Se hace con la variable PS1 (lección 03-01).
- Práctica guiada: recorrido por el árbol de Tramontana
Vamos a recorrer entero el despliegue de Tramontana Reservas, describiendo cada pieza. Este recorrido es el que harías al recibir un servidor que no conoces.
Punto de partida y visión general:
operador@srv-tramontana:~$ pwd
/home/operador
operador@srv-tramontana:~$ df -h /
S.ficheros Tamaño Usados Disp Uso% Montado en
/dev/sda2 23G 6,7G 15G 30% /Un solo sistema de archivos para todo el árbol, al 30 %. Bien de espacio, y también significa que cualquier cosa que crezca sin control afecta a todo el sistema.
La aplicación:
operador@srv-tramontana:~$ tree -L 2 /opt/tramontana
/opt/tramontana
└── app
├── ejecutable
├── plantillas
└── version.txt
operador@srv-tramontana:~$ ls -ld /opt/tramontana/app
drwxr-xr-x 4 root root 4096 ago 18 08:30 /opt/tramontana/app
operador@srv-tramontana:~$ cat /opt/tramontana/app/version.txt
Tramontana Reservas 3.2.1
operador@srv-tramontana:~$ file /opt/tramontana/app/ejecutable
/opt/tramontana/app/ejecutable: ELF 64-bit LSB pie executable, x86-64
operador@srv-tramontana:~$ du -sh /opt/tramontana/app
48M /opt/tramontana/appDiagnóstico: software de terceros en /opt según el FHS, propiedad de root (los usuarios no pueden modificar el código: correcto), 48 MB, un binario compilado y sus plantillas. Datos estáticos: no cambian salvo en un despliegue.
La configuración:
operador@srv-tramontana:~$ ls -l /etc/tramontana/
total 4
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
operador@srv-tramontana:~$ stat -c 'permisos %a, dueño %U:%G, modificado %y' /etc/tramontana/app.conf
permisos 640, dueño root:tramontana, modificado 2026-08-18 08:47:12.338291044 +0200Dos cosas relevantes. La primera: permisos 640, es decir, nadie que no sea root o del grupo tramontana puede leerla, lo cual es correcto porque contiene credenciales. La segunda: el grupo tramontana aparece aquí, y todavía no lo hemos creado formalmente; eso se hará en la lección 05-01. El significado exacto del 640 es la lección 02-07.
Fíjate también en el mtime: se modificó esta mañana a las 8:47. En un servidor que no debería cambiar, una configuración modificada recientemente es lo primero que se investiga ante una incidencia.
Los logs:
operador@srv-tramontana:~$ sudo ls -lh /var/log/tramontana/
total 25K
-rw-r----- 1 root adm 18K ago 18 09:14 acceso.log
-rw-r----- 1 root adm 6,2K ago 18 09:02 errores.log
operador@srv-tramontana:~$ sudo du -sh /var/log/tramontana
26K /var/log/tramontana
operador@srv-tramontana:~$ sudo file /var/log/tramontana/acceso.log
/var/log/tramontana/acceso.log: ASCII textDatos variables: crecen con el uso. 26 KB hoy no es nada, pero un log de acceso en producción crece de forma lineal con el tráfico, y ese es exactamente el escenario que justificaba ponerlo en /var. Que sea ASCII text importa: significa que todas las herramientas de procesamiento de texto del Módulo 3 funcionarán sobre él.
Las copias y los datos de trabajo:
operador@srv-tramontana:~$ ls -ld /srv/tramontana/backups
drwxr-x--- 2 root root 4096 ago 18 08:30 /srv/tramontana/backups
operador@srv-tramontana:~$ ls -lh ~/datos/
total 8,0K
-rw-r----- 1 operador operador 418 ago 17 19:40 casas.txt
-rw-r--r-- 1 operador operador 1,2K ago 18 07:55 reservas.csv
operador@srv-tramontana:~$ head -n 3 ~/datos/reservas.csv
id;fecha;casa;huesped;noches;importe
1001;2026-07-03;mas-figueres;Nuria Prat;4;620.00
1002;2026-07-05;can-ventos;Oriol Sala;2;280.00Los datos de trabajo están en tu home, separados de la aplicación. reservas.csv usa punto y coma como separador, un detalle que será importante al procesarlo en la lección 03-05.
Resumen del recorrido, en el formato de informe que Marta espera:
| Ruta | Contenido | Naturaleza | Tamaño | Propietario |
|---|---|---|---|---|
/opt/tramontana/app |
Binario y plantillas | Estático | 48 M | root:root |
/etc/tramontana/app.conf |
Configuración con credenciales | Estático, sensible | 512 B | root:tramontana |
/var/log/tramontana/ |
Registros de acceso y error | Variable, crece | 26 K | root:adm |
/srv/tramontana/backups |
Copias de seguridad | Variable, crece a saltos | 0 | root:root |
/home/operador/datos |
Datos de trabajo | Variable | 8 K | operador:operador |
Con cinco comandos —df, tree, ls -l, stat, du— has caracterizado un servidor completo sin tocar nada. Ese es el reconocimiento inicial que se hace al heredar un sistema.
Errores Comunes y Consejos
Confundir .. con .. cd . no hace nada, cd .. sube. Un carácter, mucha diferencia.
Usar rutas relativas en scripts. Funciona mientras lo ejecutas a mano desde el directorio adecuado, y falla el día que lo lanza cron desde /. Absolutas siempre en scripts.
Creer que el tamaño de un directorio en ls -l es lo que contiene. No: son 4096 bytes de índice. Usa du -sh.
Confundir du con df. Si preguntas «cuánto queda en el disco», es df. Si preguntas «qué está ocupando tanto», es du.
Creer que ctime es la fecha de creación. Es change time. La creación real, cuando está disponible, la muestra stat como «Creación».
Fiarse de la extensión. Un .txt puede ser un binario y un archivo sin extensión puede ser un ejecutable. file es la respuesta.
Consejo: cd - y pushd/popd. cd - alterna entre dos. Si necesitas una pila de directorios, pushd y popd la implementan; son builtins y su documentación está en help pushd.
Consejo: ls -ltr en directorios con muchos archivos. Lo más reciente queda pegado al prompt.
Consejo: ls -ld es la opción que más se olvida. Cada vez que quieras saber algo del directorio y no de su contenido, es -d.
Consejo: df -hi cuando «no queda espacio» pero df -h dice que sí. Se han agotado los inodos.
Ejercicios
Ejercicio 1: traducción de rutas
Sin ejecutar nada, partiendo del árbol de Tramontana del apartado 3 y estando en /opt/tramontana/app/plantillas:
- Ruta relativa a
/opt/tramontana/app/version.txt. - Ruta relativa a
/etc/tramontana/app.conf. - ¿Qué directorio es
../../../../var/log? - ¿Qué hace
cd ../..desde ahí, y cuál es elpwdresultante?
Después comprueba tus respuestas en el servidor.
Ejercicio 2: caracterizar un directorio desconocido
Marta te pide que revises el directorio /var/log de srv-tramontana porque «el disco parece que va llenándose». Sin borrar nada, averigua y presenta:
- Cuánto espacio libre queda en la partición raíz y qué porcentaje se usa.
- Cuánto ocupa
/var/logen total. - Qué tres subdirectorios de
/var/logocupan más. - Cuál es el archivo modificado más recientemente dentro de
/var/log/tramontanay a qué hora. - Si ese archivo es texto o binario.
Ejercicio 3: las marcas de tiempo
En tu home, con un archivo de prueba:
- Crea
/tmp/marcas.txtcon algo de contenido y anota sus tres marcas de tiempo. - Léelo con
cat. ¿Cuál cambió? - Cambia sus permisos con
chmod 600. ¿Cuál cambió ahora? - Añádele contenido. ¿Cuáles cambiaron?
- Explica por qué un atacante que quiere ocultar que ha modificado un archivo del sistema puede falsificar el mtime pero le resulta mucho más difícil falsificar el ctime.
Soluciones
Solución 1
1. ../version.txt — subes de plantillas a app y ahí está el archivo.
operador@srv-tramontana:/opt/tramontana/app/plantillas$ cat ../version.txt
Tramontana Reservas 3.2.12. ../../../etc/tramontana/app.conf. Cuenta los niveles: de plantillas a app (uno), a tramontana (dos), a opt (tres)... y desde opt hay que subir uno más hasta /. Son cuatro: ../../../../etc/tramontana/app.conf.
Comprobémoslo, que es justo el tipo de error que se comete:
operador@srv-tramontana:/opt/tramontana/app/plantillas$ ls ../../../etc/tramontana/
ls: no se puede acceder a '../../../etc/tramontana/': No existe el fichero o el directorio
operador@srv-tramontana:/opt/tramontana/app/plantillas$ ls ../../../../etc/tramontana/
app.confLa ruta absoluta actual tiene cuatro componentes (opt, tramontana, app, plantillas), así que hacen falta cuatro .. para llegar a la raíz. Esta es exactamente la razón por la que las rutas absolutas son mejores en cuanto la distancia pasa de un par de niveles: /etc/tramontana/app.conf no admite este error.
3. ../../../../var/log es /var/log, por el mismo cálculo.
4. cd ../.. sube dos niveles: de plantillas a app, y de app a tramontana.
operador@srv-tramontana:/opt/tramontana/app/plantillas$ cd ../..
operador@srv-tramontana:/opt/tramontana$ pwd
/opt/tramontanaSolución 2
# 1. Espacio en la raíz
operador@srv-tramontana:~$ df -h /
S.ficheros Tamaño Usados Disp Uso% Montado en
/dev/sda2 23G 6,7G 15G 30% /15 GB libres, 30 % usado. Sin problema por ahora.
1,3 MB sobre 23 GB: /var/log no es la causa de que el disco se llene. Este es el dato que cierra la pregunta de Marta.
# 3. Los tres subdirectorios más grandes
operador@srv-tramontana:~$ sudo du -h -d 1 /var/log | sort -h | tail -n 4
8,0K /var/log/private
26K /var/log/tramontana
912K /var/log/journal
1,3M /var/log(El | sort -h | tail es una tubería; se explica a fondo en el Módulo 3. Puedes obtener lo mismo leyendo la salida de du -h -d 1 /var/log a ojo.)
El mayor consumidor es journal, el registro de systemd, con 912 KB. Es normal y tiene límite de tamaño configurable (lección 05-06).
# 4. El más reciente en /var/log/tramontana
operador@srv-tramontana:~$ sudo ls -lt --time-style=long-iso /var/log/tramontana
total 25
-rw-r----- 1 root adm 18432 2026-08-18 09:14 acceso.log
-rw-r----- 1 root adm 6348 2026-08-18 09:02 errores.logacceso.log, modificado a las 09:14. -t ordena por fecha descendente, así que el primero es el más reciente.
# 5. Tipo de archivo
operador@srv-tramontana:~$ sudo file /var/log/tramontana/acceso.log
/var/log/tramontana/acceso.log: ASCII textInforme para Marta: el disco raíz está al 30 % con 15 GB libres. /var/log ocupa 1,3 MB en total, así que no es lo que está llenando el disco; conviene mirar en otro sitio. Dentro de los registros, el mayor consumidor es el diario del sistema (912 KB) y los logs de la aplicación suman 26 KB. El registro de acceso se actualizó por última vez a las 09:14 de hoy, lo que confirma que la aplicación está funcionando y escribiendo con normalidad.
Solución 3
operador@srv-tramontana:~$ echo "linea inicial" > /tmp/marcas.txt
operador@srv-tramontana:~$ stat -c 'atime=%x%nmtime=%y%nctime=%z' /tmp/marcas.txt
atime=2026-08-18 10:02:14.118293011 +0200
mtime=2026-08-18 10:02:14.118293011 +0200
ctime=2026-08-18 10:02:14.118293011 +0200Al crearlo, las tres coinciden.
operador@srv-tramontana:~$ cat /tmp/marcas.txt
linea inicial
operador@srv-tramontana:~$ stat -c 'atime=%x%nmtime=%y%nctime=%z' /tmp/marcas.txt
atime=2026-08-18 10:03:41.554820119 +0200
mtime=2026-08-18 10:02:14.118293011 +0200
ctime=2026-08-18 10:02:14.118293011 +0200Solo cambió atime: has leído el contenido, no lo has modificado. (Si no ves el cambio, es por relatime: si atime ya era más reciente que mtime y no han pasado 24 horas, el kernel no lo actualiza. Es el comportamiento normal y esperado.)
operador@srv-tramontana:~$ chmod 600 /tmp/marcas.txt
operador@srv-tramontana:~$ stat -c 'atime=%x%nmtime=%y%nctime=%z' /tmp/marcas.txt
atime=2026-08-18 10:03:41.554820119 +0200
mtime=2026-08-18 10:02:14.118293011 +0200
ctime=2026-08-18 10:05:02.771820102 +0200Solo cambió ctime: has modificado el inodo (los permisos viven ahí), no el contenido ni lo has leído. Esta es la demostración de que ctime no es creation time.
operador@srv-tramontana:~$ echo "segunda linea" >> /tmp/marcas.txt
operador@srv-tramontana:~$ stat -c 'atime=%x%nmtime=%y%nctime=%z' /tmp/marcas.txt
atime=2026-08-18 10:03:41.554820119 +0200
mtime=2026-08-18 10:06:33.201938477 +0200
ctime=2026-08-18 10:06:33.201938477 +0200Cambiaron mtime y ctime. El contenido cambió (mtime) y, al cambiar el contenido, también cambió el tamaño registrado en el inodo (ctime). No cambió atime porque escribir no es leer.
Punto 5: por qué el ctime es difícil de falsificar. El comando touch permite fijar atime y mtime al valor que quieras (touch -t, lección 02-04). Un atacante que modifica /etc/tramontana/app.conf puede dejar el mtime exactamente como estaba y el archivo parecerá intacto en ls -l.
Pero el ctime no se puede fijar. No hay ninguna llamada al sistema que permita escribir un valor arbitrario en él: el kernel lo actualiza automáticamente cada vez que el inodo cambia, incluido el cambio que provoca el propio touch al falsificar el mtime. Falsificar el ctime exige acceso directo al dispositivo de bloques por debajo del sistema de archivos, o cambiar el reloj del sistema, y ambas cosas dejan otros rastros.
De ahí la práctica forense: ante la sospecha de una intrusión, se comparan mtime y ctime. Un archivo cuyo ctime es muy posterior a su mtime ha sido tocado de una forma que merece explicación. Es uno de los indicadores que usan las herramientas de la lección 06-04.
Conclusión
Ya no navegas a tientas por el árbol del Módulo 1: lo recorres con instrumentos.
pwdte dice dónde estás, ypwd -Pdónde estás de verdad cuando hay enlaces por medio.cdtiene más formas de las que parecía:cd -para alternar,cda secas para volver a casa,~usuariopara el home ajeno. Y si falla, no te mueves, que es justo lo que hacía peligroso el;.- Sabes traducir entre rutas absolutas y relativas contando niveles, y tienes el criterio: relativas para tus dedos, absolutas para scripts y cron.
.y..son entradas reales con su propio inodo, y por eso./programaes la forma de ejecutar algo del directorio actual.lslo lees columna a columna, y conoces las combinaciones que se usan a diario:-lah,-ltr,-lhSy el imprescindible-ld.tree -Lte da la estructura de un vistazo sin ahogarte en profundidad.statte da los metadatos completos, y entiendes con precisión atime, mtime y ctime, incluida la razón por la que ctime es relevante en seguridad.filete dice qué es realmente un archivo, porque en Linux la extensión no manda.dumide lo que ocupa algo,dfmide lo que queda, y sabes por qué a veces no cuadran y qué hacer cuando el disco «está lleno» sin estarlo.- Y has caracterizado el despliegue completo de Tramontana Reservas con cinco comandos, sin modificar nada.
Se acabó mirar. En la próxima lección, Operaciones con Archivos y Directorios, empiezas a escribir en el disco: touch y mkdir para crear, cp y mv con todas sus trampas —incluida la barra final del destino, que muerde a todo el mundo—, rm y la conversación seria sobre rm -rf que hay que tener una vez en la vida, rsync para copiar directorios grandes como es debido, y tar con gzip, bzip2 y xz para empaquetar. Terminarás preparando un paquete de /opt/tramontana/app para pasárselo a Luis. Asegúrate de tener el snapshot de la VM al día antes de empezar: a partir de aquí, los comandos ya no se limitan a mirar.
Curso de Linux: De Principiante a Administrador de Sistemas
Módulo 1: Introducción a Linux
- ¿Qué es Linux?
- Historia de Linux
- Distribuciones de Linux
- Instalando Linux
- Primer Contacto con el Sistema
- Estructura del Sistema de Archivos de Linux
Módulo 2: Comandos Básicos de Linux
- Introducción a la Línea de Comandos
- Obtener Ayuda y Documentación del Sistema
- Navegando el Sistema de Archivos
- Operaciones con Archivos y Directorios
- Visualización y Edición de Archivos
- Enlaces Duros y Simbólicos
- Permisos y Propiedad de Archivos
Módulo 3: Habilidades Avanzadas en la Línea de Comandos
- El Entorno del Shell: Variables, Alias e Historial
- Uso de Comodines y Expresiones Regulares
- Búsqueda de Archivos y Contenido: find, locate y grep
- Tuberías y Redirección
- Procesamiento de Texto: cut, sort, uniq, sed y awk
- Gestión de Procesos
- Programación de Tareas con Cron
- Comandos de Redes
Módulo 4: Scripting en Shell
- Introducción al Scripting en Shell
- Variables y Tipos de Datos
- Entrada, Salida y Argumentos de un Script
- Estructuras de Control
- Funciones y Librerías
- Depuración y Manejo de Errores
- Scripts de Producción: Buenas Prácticas
Módulo 5: Administración del Sistema
- Gestión de Usuarios y Grupos
- sudo y Permisos Especiales
- Gestión de Paquetes
- Gestión de Discos
- systemd y la Gestión de Servicios
- Registros del Sistema: journald y syslog
- Monitoreo del Sistema y Optimización del Rendimiento
- Respaldo y Restauración
Módulo 6: Redes y Seguridad
- Configuración de Redes
- SSH y Acceso Remoto
- Firewall y Seguridad Perimetral
- Sistemas de Detección de Intrusos
- Gestión de Secretos y Certificados TLS
- Asegurando Sistemas Linux
Módulo 7: Temas Avanzados
- El Proceso de Arranque y la Recuperación del Sistema
- Diagnóstico Avanzado: strace, perf y eBPF
- Optimización del Kernel de Linux
- Virtualización con Linux
- Contenedores de Linux y Docker
- Automatización con Ansible
- Alta Disponibilidad y Balanceo de Carga
