Un servidor Linux se administra editando archivos de texto. La configuración de un servicio es texto, los registros que produce son texto, el inventario de reservas de Tramontana es texto separado por punto y coma, y hasta la información que el kernel expone en /proc es texto. La filosofía Unix que viste en el Módulo 1 —«texto plano como interfaz universal»— tiene esta consecuencia muy concreta: la mitad del trabajo de administración consiste en leer y modificar ficheros de texto.

Esta lección te da las dos mitades de esa habilidad. La primera, ver contenido sin abrir nada: qué comando usar para un archivo de tres líneas, cuál para uno de dos millones, y cuál para un log que está creciendo ahora mismo mientras Marta te pregunta qué está pasando. La segunda, editar: nano completo, porque es lo que usarás a diario, y el vim mínimo imprescindible, porque el día que entres en un servidor recién instalado o en un contenedor puede ser lo único que haya.

Y en medio, una convención que el curso adoptará a partir de aquí y no abandonará: antes de editar un fichero de configuración, se hace una copia.

Contenido

  1. cat y tac: el archivo entero de golpe
  2. less: el visor de verdad
  3. head y tail: los extremos
  4. Seguir un archivo en vivo: tail -f y tail -F
  5. nl y wc: numerar y contar
  6. Panorama de editores en terminal
  7. nano completo
  8. vim de supervivencia
  9. La lección de oro: copia antes de editar
  10. Archivos que no son texto: file, strings, xxd y reset
  11. Comparar versiones: diff y sdiff

  1. cat y tac: el archivo entero de golpe

cat (concatenate) vuelca uno o más archivos a la pantalla:

operador@srv-tramontana:~$ cat datos/casas.txt
mas-figueres;Mas Figueres;Girona;6
can-ventos;Can Ventós;Empordà;4
la-solana;La Solana;Pallars;8
cal-ferrer;Cal Ferrer;Berguedà;10

Su nombre viene de su propósito original, que no era mostrar sino concatenar:

operador@srv-tramontana:~$ cat datos/casas.txt datos/reservas.csv > /tmp/todo.txt

Opciones útiles:

Opción Qué hace
-n Numera todas las líneas
-b Numera solo las no vacías
-A Muestra los caracteres invisibles ($ fin de línea, ^I tabulador)
-s Comprime varias líneas en blanco seguidas en una

-A es una herramienta de diagnóstico infravalorada:

operador@srv-tramontana:~$ cat -A /tmp/config-luis.conf
puerto=8080^M$
timeout=30^M$

Esos ^M son retornos de carro de Windows. El $ marca el fin de línea real. Es la misma patología que detectaba file con «CRLF line terminators» en la lección 02-03, vista ahora carácter a carácter. Un servicio que lee puerto=8080\r intentará abrir un puerto llamado 8080\r y fallará con un mensaje que no ayuda en nada.

El «uso inútil de cat»

Existe una expresión consagrada en la cultura Unix, Useless Use of Cat (UUOC), para esto:

# Uso inútil de cat
cat /var/log/tramontana/errores.log | grep "ERROR"

# Correcto
grep "ERROR" /var/log/tramontana/errores.log

grep sabe abrir archivos. Meter un cat delante crea un proceso extra y una tubería para nada. Con un archivo pequeño da igual; con uno de varios gigabytes, el cat fuerza a leer y transferir todo el contenido por la tubería en lugar de dejar que grep lo lea directamente.

No es purismo: la razón práctica es que muchas herramientas pierden funcionalidad cuando reciben la entrada por tubería en vez de un nombre de archivo. grep con un archivo puede decirte el número de línea y el nombre del fichero; a través de una tubería solo ve un flujo anónimo. Y wc -l archivo imprime el nombre, mientras que cat archivo | wc -l no.

Dicho esto, hay un uso legítimo: cuando de verdad concatenas varios archivos, o cuando construyes una cadena de forma exploratoria y la claridad te importa más que el rendimiento.

La regla honesta: cat es para archivos que caben en pantalla. Para un archivo grande, cat te lanza miles de líneas y solo ves las últimas veinticinco. Para eso está less.

tac es cat al revés: muestra el archivo empezando por la última línea.

operador@srv-tramontana:~$ tac datos/casas.txt
cal-ferrer;Cal Ferrer;Berguedà;10
la-solana;La Solana;Pallars;8
can-ventos;Can Ventós;Empordà;4
mas-figueres;Mas Figueres;Girona;6

Suena anecdótico y es muy útil con logs, porque lo más reciente está al final y tac lo pone arriba.

  1. less: el visor de verdad

less muestra un archivo página a página, sin cargarlo entero en memoria. Eso último es lo importante: abre un archivo de 10 GB instantáneamente, porque solo lee lo que va mostrando.

operador@srv-tramontana:~$ sudo less /var/log/tramontana/acceso.log

Los atajos ya los conoces de la lección 02-02, porque man usa less por debajo. Aquí van completos, con los que solo tienen sentido sobre archivos:

Tecla Acción
Espacio / f Avanzar una pantalla
b Retroceder una pantalla
d / u Media pantalla adelante / atrás
Flechas, j / k Línea a línea
g / G Principio / final del archivo
50g Ir a la línea 50
/texto Buscar hacia delante
?texto Buscar hacia atrás
n / N Siguiente / anterior coincidencia
&texto Filtrar: mostrar solo las líneas que coinciden
-N (dentro) Activar o desactivar los números de línea
-S (dentro) Activar o desactivar el corte de líneas largas
m + letra Marcar esta posición
' + letra Volver a la marca
F Pasar a modo seguimiento en vivo
v Abrir el archivo en el editor
h Ayuda
q Salir

Opciones de la línea de órdenes que merecen conocerse:

# Con números de línea
operador@srv-tramontana:~$ sudo less -N /var/log/tramontana/errores.log

# Sin cortar las líneas largas: se desplazan lateralmente con las flechas
operador@srv-tramontana:~$ sudo less -S /var/log/tramontana/acceso.log

# Abrir directamente al final (lo más nuevo de un log)
operador@srv-tramontana:~$ sudo less +G /var/log/tramontana/errores.log

# Abrir en modo seguimiento en vivo
operador@srv-tramontana:~$ sudo less +F /var/log/tramontana/errores.log

-S merece explicación. Por defecto, less parte las líneas largas para que quepan, y una sola línea puede ocupar cinco filas de pantalla. En un log con líneas largas eso hace la lectura imposible. Con -S cada línea ocupa una fila y el resto queda fuera; se ve desplazándose con las flechas izquierda y derecha. Para un acceso.log con líneas de doscientos caracteres, -S es la diferencia entre poder leerlo y no poder.

& es la joya escondida. Dentro de less, escribe &ERROR y Enter: la pantalla muestra solo las líneas que contienen «ERROR», ocultando las demás. Es un filtro instantáneo sin salir del visor. Se quita con & y Enter en blanco.

+F convierte less en un tail -f con superpoderes: sigue el archivo en vivo, y con Ctrl+C sales del modo seguimiento y puedes buscar y navegar por lo que ya se ha escrito, sin cerrar nada. Con F vuelves a seguir. Es la mejor herramienta que hay para observar un log durante una incidencia.

more y por qué less lo sustituyó

more es el paginador original de Unix. Sigue instalado por compatibilidad:

more less
Avanzar Sí Sí
Retroceder No (en la versión original) Sí
Buscar hacia atrás No Sí
Abrir archivos enormes Los lee entero Solo lo que muestra
Salir antes del final Sí, con q Sí
Al terminar Sale y deja el texto en pantalla Limpia y vuelve al prompt

La limitación de more era brutal: si te pasabas una línea, no había vuelta atrás. Había que volver a abrir el archivo desde el principio. less nació precisamente para arreglar eso, y de ahí su nombre, un juego con el refrán inglés «less is more».

Hoy no hay razón para usar more, salvo una: en un sistema mínimo o en modo rescate puede que less no esté instalado y more sí. Que sepas que existe.

Un comportamiento de less que conviene conocer y a veces desactivar: al salir, limpia la pantalla y no queda rastro de lo que viste. Si prefieres que el contenido se quede, existe la opción -X. Y si quieres que no pagine cuando el contenido cabe en una pantalla, -F (mayúscula distinta de la tecla F de dentro). La combinación less -FX es la que muchos administradores dejan configurada por defecto.

  1. head y tail: los extremos

Casi nunca necesitas el archivo entero: necesitas el principio o el final.

operador@srv-tramontana:~$ head 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.00
1003;2026-07-08;la-solana;Marc Aliaga;7;1190.00
1004;2026-07-11;cal-ferrer;Berta Mir;3;540.00
1005;2026-07-14;mas-figueres;Jordi Camps;5;775.00
1006;2026-07-18;can-ventos;Aina Roca;2;280.00
1007;2026-07-21;la-solana;Pau Serra;6;1020.00
1008;2026-07-25;cal-ferrer;Elena Vila;4;720.00
1009;2026-07-29;mas-figueres;Sergi Bosch;3;465.00

Diez líneas por defecto en ambos comandos.

Opción head tail
-n N Primeras N líneas Últimas N líneas
-n +N — Desde la línea N hasta el final
-n -N Todo menos las últimas N —
-c N Primeros N bytes Últimos N bytes
-q No muestra cabeceras con varios archivos Igual
-f — Seguir el archivo en vivo
operador@srv-tramontana:~$ head -n 1 datos/reservas.csv
id;fecha;casa;huesped;noches;importe

operador@srv-tramontana:~$ tail -n 3 datos/reservas.csv
1023;2026-08-14;can-ventos;Ivan Puig;3;420.00
1024;2026-08-16;la-solana;Clara Font;5;850.00
1025;2026-08-17;cal-ferrer;Roger Mas;2;360.00

La forma -n +N de tail es la que se usa para saltarse la cabecera de un CSV:

operador@srv-tramontana:~$ tail -n +2 datos/reservas.csv | head -n 3
1001;2026-07-03;mas-figueres;Nuria Prat;4;620.00
1002;2026-07-05;can-ventos;Oriol Sala;2;280.00
1003;2026-07-08;la-solana;Marc Aliaga;7;1190.00

«Desde la línea 2 hasta el final» descarta el encabezado. Es un patrón que usarás constantemente al procesar datos en la lección 03-05.

-c trabaja con bytes y es útil para asomarse a un archivo desconocido sin volcarlo entero:

operador@srv-tramontana:~$ head -c 100 /opt/tramontana/app/ejecutable | xxd | head -n 3
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 6013 0000 0000 0000  ..>.....`.......
00000020: 4000 0000 0000 0000 e8ad 4c00 0000 0000  @.........@L....

Con varios archivos, ambos añaden una cabecera con el nombre:

operador@srv-tramontana:~$ head -n 2 datos/casas.txt datos/reservas.csv
==> datos/casas.txt <==
mas-figueres;Mas Figueres;Girona;6
can-ventos;Can Ventós;Empordà;4

==> datos/reservas.csv <==
id;fecha;casa;huesped;noches;importe
1001;2026-07-03;mas-figueres;Nuria Prat;4;620.00

  1. Seguir un archivo en vivo: tail -f y tail -F

Este es el apartado que más vas a usar en tu vida profesional. Cuando algo falla en producción, lo primero que se hace es abrir el log y mirarlo mientras se reproduce el problema.

operador@srv-tramontana:~$ sudo tail -f /var/log/tramontana/errores.log
2026-08-18 11:52:03 WARN  conexión lenta a la base de datos (1240 ms)
2026-08-18 11:52:44 ERROR fallo al enviar correo de confirmación reserva=1024
2026-08-18 11:53:01 INFO  reintento programado en 60 s

El comando no termina: se queda esperando y va mostrando cada línea nueva conforme la aplicación la escribe. Se sale con Ctrl+C.

La diferencia crítica entre -f y -F

Ya la anticipaste resolviendo la duda de Luis en la lección 02-02. Ahora en detalle, porque es una de esas cosas que se aprenden con una incidencia si no se aprenden antes.

flowchart TD
    A["tail -f errores.log"] --> B["Sigue el DESCRIPTOR<br/>del archivo abierto"]
    C["tail -F errores.log"] --> D["Sigue el NOMBRE<br/>y reabre si cambia"]
    B --> E["logrotate a medianoche:<br/>errores.log -> errores.log.1<br/>se crea errores.log nuevo"]
    D --> E
    E --> F["-f sigue mirando el archivo<br/>renombrado: NO MUESTRA NADA<br/>y no avisa"]
    E --> G["-F detecta el cambio,<br/>reabre y sigue mostrando"]

logrotate es el mecanismo que evita que los logs crezcan sin fin: cada noche renombra errores.log a errores.log.1, lo comprime y crea un errores.log vacío. La lección 05-06 lo cubre.

Si dejaste un tail -f corriendo, después de la rotación sigue leyendo un archivo que ya nadie escribe. La pantalla se queda quieta y no hay ningún mensaje que te avise. Puedes pasarte veinte minutos convencido de que la aplicación no está registrando errores cuando en realidad los está escribiendo en otro sitio.

operador@srv-tramontana:~$ sudo tail -F /var/log/tramontana/errores.log
tail: '/var/log/tramontana/errores.log' ha sido reemplazado; siguiendo el final del nuevo fichero
2026-08-19 00:00:12 INFO  arranque del ciclo diario

-F avisa y reengancha. Para logs de producción, -F siempre.

Opciones que acompañan bien:

# Empezar mostrando las últimas 50 y seguir
operador@srv-tramontana:~$ sudo tail -F -n 50 /var/log/tramontana/errores.log

# Seguir dos archivos a la vez: tail marca de cuál viene cada bloque
operador@srv-tramontana:~$ sudo tail -F /var/log/tramontana/acceso.log /var/log/tramontana/errores.log
==> /var/log/tramontana/errores.log <==
2026-08-18 11:52:44 ERROR fallo al enviar correo de confirmación reserva=1024

==> /var/log/tramontana/acceso.log <==
2026-08-18 11:52:45 POST /reservas 500 casa=la-solana

# Terminar automáticamente si el proceso 4127 muere
operador@srv-tramontana:~$ sudo tail -F --pid=4127 /var/log/tramontana/errores.log

Ese segundo ejemplo, seguir el log de acceso y el de errores a la vez, es exactamente cómo se diagnostica: ves el error y, justo al lado, la petición HTTP que lo provocó.

Alternativas para cuando less +F es mejor que tail -F: si mientras miras el log necesitas buscar hacia atrás algo que ya pasó, tail no te deja y less +F sí (Ctrl+C, buscas con /, y F para volver a seguir). Regla: tail -F para vigilar, less +F para investigar.

  1. nl y wc: numerar y contar

nl numera las líneas de forma configurable, con más control que cat -n:

operador@srv-tramontana:~$ nl datos/casas.txt
     1	mas-figueres;Mas Figueres;Girona;6
     2	can-ventos;Can Ventós;Empordà;4
     3	la-solana;La Solana;Pallars;8
     4	cal-ferrer;Cal Ferrer;Berguedà;10

operador@srv-tramontana:~$ nl -ba -w 3 -s ': ' datos/casas.txt
  1: mas-figueres;Mas Figueres;Girona;6
  2: can-ventos;Can Ventós;Empordà;4

-ba numera todas las líneas (por defecto salta las vacías), -w fija el ancho y -s el separador. Es útil cuando quieres pasarle a alguien un fragmento de configuración con números de línea para poder referirte a ellos por teléfono.

wc (word count) cuenta:

operador@srv-tramontana:~$ wc datos/reservas.csv
  26  26 1204 datos/reservas.csv

Tres números: líneas, palabras, bytes. Las opciones eligen cuál:

Opción Cuenta
-l Líneas
-w Palabras
-c Bytes
-m Caracteres (distinto de bytes con UTF-8)
-L Longitud de la línea más larga
operador@srv-tramontana:~$ wc -l datos/reservas.csv
26 datos/reservas.csv

operador@srv-tramontana:~$ sudo wc -l /var/log/tramontana/*.log
  412 /var/log/tramontana/acceso.log
   87 /var/log/tramontana/errores.log
  499 total

Un matiz de -c frente a -m que importa con nombres en catalán y castellano:

operador@srv-tramontana:~$ echo -n "Can Ventós" | wc -c
11
operador@srv-tramontana:~$ echo -n "Can Ventós" | wc -m
10

Diez caracteres, once bytes: la ó ocupa dos bytes en UTF-8. Cuando cuentes longitudes de campos de datos, -m es lo que quieres.

Y un truco práctico: wc -l sobre un CSV cuenta también la cabecera. Las reservas reales son 25, no 26.

  1. Panorama de editores en terminal

Editor Curva Presente por defecto Potencia Cuándo usarlo
nano Muy suave Ubuntu, Debian sí Media Tu editor diario. Edición rápida de configuración
vim Pronunciada Casi universal (vi en POSIX) Muy alta Servidores ajenos, contenedores, modo rescate
emacs Muy pronunciada Rara vez Máxima Si ya lo usas; no se aprende para administrar
VS Code por SSH Suave No Alta Desarrollo, proyectos con muchos archivos
ed Extrema Siempre Baja Solo si el terminal está tan roto que nada más funciona

La decisión razonable para un administrador de sistemas es aprender nano bien y vim lo justo:

  • nano para tu día a día. Está en Ubuntu, en Debian y en la mayoría de las distribuciones de servidor. Muestra los atajos en pantalla. No tiene modos. Nadie ha perdido tiempo aprendiéndolo.
  • vim porque algún día no habrá nano. Contenedores Docker minimalistas, imágenes de RHEL sin paquetes opcionales, sistemas en modo rescate, servidores de clientes con políticas restrictivas. En todos ellos hay vi o vim, porque POSIX lo exige. Entrar en un servidor caído y no saber salir de vim es una situación real y evitable.

Sobre VS Code o editores gráficos por SSH: la extensión Remote-SSH permite editar archivos remotos con una interfaz gráfica cómoda. Es excelente para desarrollo. Para administración tiene tres inconvenientes serios: instala un agente en el servidor (que consume memoria y puede no estar permitido), no funciona en modo rescate ni antes de que el sistema arranque del todo, y no está disponible cuando accedes desde la consola física o desde el móvil durante una guardia. Úsalo para trabajar en el código de la aplicación; no dependas de él para administrar.

emacs es un entorno extraordinario, pero aprenderlo desde cero para editar cuatro ficheros de configuración no compensa. Si ya lo usas, sigue.

  1. nano completo

operador@srv-tramontana:~$ nano /home/operador/datos/casas.txt

La pantalla tiene tres zonas: el título arriba, el texto en medio y dos filas de atajos abajo. Esas dos filas son la razón por la que nano no se olvida.

Leer la barra de atajos

^G Ayuda      ^O Guardar    ^W Buscar     ^K Cortar     M-U Deshacer
^X Salir      ^R Leer fich. ^\ Reemplazar ^U Pegar      M-E Rehacer

La notación es fija y hay que interiorizarla:

  • ^ significa Ctrl. ^O es Ctrl+O.
  • M- significa Meta, que en un teclado actual es Alt (o Esc pulsado y soltado antes). M-U es Alt+U.

Con eso, la barra inferior es la documentación completa y siempre visible.

Atajos por categorías

Movimiento (además de las flechas, que funcionan siempre):

Atajo Acción
Ctrl+A / Ctrl+E Principio / final de línea
Ctrl+Y / Ctrl+V Página arriba / abajo
Alt+\ / Alt+/ Principio / final del archivo
Ctrl+_ Ir a un número de línea concreto
Alt+G Lo mismo, en versiones recientes

Fíjate en que Ctrl+A y Ctrl+E son los mismos que en la línea de órdenes de Bash. No es casualidad: ambos siguen la convención de readline.

Edición:

Atajo Acción
Ctrl+K Cortar la línea actual (o la selección)
Ctrl+U Pegar lo cortado
Alt+6 Copiar sin cortar
Ctrl+6 o Alt+A Marcar el inicio de una selección
Alt+U Deshacer
Alt+E Rehacer
Ctrl+D Borrar el carácter bajo el cursor

Para cortar varias líneas, Ctrl+K repetido: se van acumulando en el portapapeles y Ctrl+U las pega todas juntas.

Búsqueda y reemplazo:

Atajo Acción
Ctrl+W Buscar
Alt+W Repetir la última búsqueda
Ctrl+\ Buscar y reemplazar
Ctrl+C Mostrar la posición actual (línea y columna)

El reemplazo con Ctrl+\ pide el texto a buscar, luego el de sustitución, y por cada coincidencia pregunta: S para sustituir esta, N para saltarla, T para todas de golpe.

Archivo:

Atajo Acción
Ctrl+O Guardar (pide confirmar el nombre; Enter para el mismo)
Ctrl+R Insertar otro archivo en la posición del cursor
Ctrl+X Salir (pregunta si hay cambios sin guardar)
Ctrl+T Explorador de archivos al guardar

El flujo básico completo: abres, editas, Ctrl+O, Enter, Ctrl+X. Cinco pulsaciones.

Si intentas salir con cambios sin guardar, nano pregunta:

Guardar el búfer modificado?
 S Sí
 N No           ^C Cancelar

Configuración mínima en ~/.nanorc

Cuatro líneas que mejoran mucho la experiencia:

operador@srv-tramontana:~$ nano ~/.nanorc
# Mostrar números de línea
set linenumbers

# Resaltado de sintaxis
include "/usr/share/nano/*.nanorc"

# No cortar las líneas largas automáticamente: CRÍTICO en ficheros de configuración
set nowrap

# Convertir los tabuladores en espacios y usar 4
set tabstospaces
set tabsize 4

# Mostrar la posición del cursor permanentemente
set constantshow

# Hacer copia de seguridad al guardar
set backup
set backupdir "/home/operador/.nano-backups"

Las dos importantes de verdad:

set nowrap evita que nano parta automáticamente las líneas largas al guardar. Sin esto, editar un fichero de configuración con una directiva larga puede romperlo silenciosamente: la línea se parte en dos, el servicio lee media directiva y falla. Es la causa de más de un rato perdido.

set backup guarda una copia del archivo original cada vez que guardas. No sustituye a la convención del apartado 9, pero es una red adicional gratis.

operador@srv-tramontana:~$ mkdir -p ~/.nano-backups

  1. vim de supervivencia

El objetivo aquí no es que domines vim. Es que puedas editar un fichero y salir sin destrozar nada en una máquina donde no hay otra cosa. Eso son unos quince comandos.

El concepto que lo explica todo: los modos

vim no es un editor donde escribes; es un editor donde das órdenes, y uno de esos modos consiste en escribir texto.

flowchart LR
    N["MODO NORMAL<br/>(al abrir)<br/>Las teclas son órdenes"]
    I["MODO INSERCIÓN<br/>Las teclas escriben texto"]
    C["MODO COMANDO<br/>Órdenes con :"]
    N -->|"i, a, o, I, A, O"| I
    I -->|"Esc"| N
    N -->|":"| C
    C -->|"Enter o Esc"| N

De aquí salen las dos reglas que resuelven el 90 % de los apuros:

  1. Al abrir vim estás en modo NORMAL. Si escribes, no aparece texto: se ejecutan órdenes.
  2. Esc siempre te devuelve al modo normal. Si estás perdido, pulsa Esc dos veces y estás en terreno conocido.

Entrar y salir

operador@srv-tramontana:~$ vim /etc/tramontana/app.conf
Orden Qué hace
:w Guardar
:q Salir (falla si hay cambios sin guardar)
:wq o :x Guardar y salir
ZZ Guardar y salir (en modo normal, sin :)
:q! Salir descartando los cambios
:w nombre Guardar con otro nombre
:w !sudo tee % Guardar como root un archivo que abriste sin permisos

:q! es el comando más importante de este apartado. Si has entrado en vim por accidente, si has tecleado algo sin querer, si no sabes qué has hecho: Esc, luego :q!, luego Enter. Sales sin guardar y el archivo queda como estaba.

Ese :w !sudo tee % resuelve una situación muy frecuente: abriste /etc/tramontana/app.conf sin sudo, hiciste todos los cambios y al guardar te dice que el archivo es de solo lectura. En lugar de perder el trabajo, esa orden lo escribe pasando por sudo.

Escribir texto

Tecla Entra en inserción...
i antes del cursor
a después del cursor
I al principio de la línea
A al final de la línea
o en una línea nueva debajo
O en una línea nueva encima

A y o son las que más se usan editando configuración: añadir al final de una línea o abrir una línea nueva.

Moverse

Tecla Movimiento
h j k l Izquierda, abajo, arriba, derecha (las flechas también funcionan)
w / b Palabra siguiente / anterior
0 / $ Principio / final de línea
gg Principio del archivo
G Final del archivo
42G o :42 Ir a la línea 42
Ctrl+F / Ctrl+B Página adelante / atrás

Editar

Orden Qué hace
x Borrar el carácter bajo el cursor
dd Cortar la línea entera
3dd Cortar tres líneas
dw Borrar hasta el final de la palabra
yy Copiar la línea (yank)
p Pegar debajo
P Pegar encima
u Deshacer
Ctrl+R Rehacer
. Repetir la última orden

La lógica de vim es que las órdenes se componen: d (borrar) + w (palabra) = dw. 3 + dd = tres líneas. Entender esa composición es lo que hace a la gente adicta a vim, y también lo que hace su curva empinada. Para supervivencia, memoriza dd, yy, p y u.

u es tu paracaídas. Pulsándolo repetidamente deshaces todo hasta el estado inicial.

Buscar y sustituir

Orden Qué hace
/texto Buscar hacia delante
?texto Buscar hacia atrás
n / N Siguiente / anterior
:%s/viejo/nuevo/g Sustituir en todo el archivo
:%s/viejo/nuevo/gc Igual, preguntando en cada caso
:s/viejo/nuevo/g Solo en la línea actual

Desglose de :%s/viejo/nuevo/g, porque cada parte cuenta:

  • % — en todas las líneas del archivo
  • s — sustituir
  • /viejo/nuevo/ — qué por qué
  • g — global: todas las apariciones de cada línea, no solo la primera

La variante con c al final pregunta antes de cada sustitución. Úsala siempre en un fichero de producción.

vimtutor

vim trae un tutorial interactivo de unos treinta minutos:

operador@srv-tramontana:~$ vimtutor

Es, sin exageración, la mejor inversión de media hora que puedes hacer en este módulo. No te convertirá en experto, pero después de hacerlo una vez ya nunca te quedarás atrapado en un servidor.

Una nota sobre vi frente a vim: vi es el editor original de Unix y vim (Vi IMproved) es su versión moderna. En Ubuntu, vi suele ser un enlace a vim. En sistemas minimalistas puedes encontrarte vi de verdad, con menos funciones (sin colores, sin u múltiple), pero todo lo de este apartado funciona igual.

  1. La lección de oro: copia antes de editar

Esto no es un truco: es una convención de trabajo que el curso adopta a partir de aquí y no abandona.

Antes de modificar cualquier fichero de configuración, se hace una copia fechada.

operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf /etc/tramontana/app.conf.bak-$(date +%F)
operador@srv-tramontana:~$ ls -l /etc/tramontana/
total 8
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
-rw-r----- 1 root tramontana 512 ago 18 12:15 app.conf.bak-2026-08-18

$(date +%F) es sustitución de comandos: el shell ejecuta date +%F, que devuelve 2026-08-18, y pone el resultado en la línea. El mecanismo completo se explica en la lección 03-01; adóptalo ya como fórmula.

Por qué exactamente así:

Elemento Razón
En el mismo directorio La encuentras al instante, sin recordar dónde la dejaste
Sufijo .bak-FECHA Sabes de cuándo es sin abrir nada
cp y no mv El original sigue en su sitio y el servicio no se entera
La fecha en formato ISO Ordena cronológicamente al listar con ls
Antes, no después Después ya no tienes el original

Si vas a hacer varios cambios el mismo día, añade la hora:

operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf /etc/tramontana/app.conf.bak-$(date +%F-%H%M)

El procedimiento completo de una edición de configuración, que es lo que se hace en producción:

# 1. Copia de seguridad
operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf /etc/tramontana/app.conf.bak-$(date +%F)

# 2. Editar
operador@srv-tramontana:~$ sudo nano /etc/tramontana/app.conf

# 3. Ver EXACTAMENTE qué has cambiado
operador@srv-tramontana:~$ sudo diff -u /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf

# 4. (Si el servicio tiene validador, usarlo antes de recargar)
# 5. Recargar el servicio y comprobar que arranca

# 6. Si algo va mal: volver atrás en un segundo
operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf

El paso 3 es el que convierte la copia en algo más que un seguro: te permite verificar tu propio cambio antes de aplicarlo. Es donde entra diff, en el apartado 11.

Una advertencia sobre dónde dejar las copias: en algunos directorios, dejar archivos sueltos tiene efectos secundarios. Un .bak en /etc/sudoers.d/ o en /etc/apt/sources.list.d/ puede ser leído por el sistema como si fuera configuración válida. En esos casos, la copia va fuera del directorio, por ejemplo en /home/operador/backups-config/. Lo veremos cuando toquemos esos directorios en el Módulo 5.

  1. Archivos que no son texto: file, strings, xxd y reset

Por qué no debes hacer cat de un binario

operador@srv-tramontana:~$ cat /opt/tramontana/app/ejecutable

Lo que pasa: aparece un chorro de basura en pantalla, suena un pitido varias veces, y el terminal deja de funcionar bien. Las letras que escribes salen como símbolos raros, el Enter no baja de línea, el prompt es ilegible.

La explicación es concreta y tiene sentido. Un terminal interpreta ciertas secuencias de bytes como órdenes de control, no como texto: cambiar de color, mover el cursor, y —esta es la que causa el problema— cambiar el juego de caracteres a modo gráfico. Un archivo binario contiene bytes arbitrarios, y entre millones de bytes aleatorios aparecerá tarde o temprano la secuencia que activa ese modo. A partir de ahí, el terminal dibuja símbolos de líneas en lugar de letras.

No se ha roto nada. Solo hay que restablecer el estado:

operador@srv-tramontana:~$ reset

Escríbelo aunque no veas lo que escribes y pulsa Enter. Si reset no está disponible:

operador@srv-tramontana:~$ stty sane
operador@srv-tramontana:~$ tput reset

Y si nada funciona, cerrar la sesión SSH y volver a entrar siempre lo arregla, porque el terminal se reinicia.

Prevención: pasa file antes de abrir un archivo desconocido. Es un segundo y evita el problema entero.

operador@srv-tramontana:~$ file /opt/tramontana/app/ejecutable
/opt/tramontana/app/ejecutable: ELF 64-bit LSB pie executable, x86-64

less también protege: al detectar que un archivo es binario avisa con "fichero" puede ser un fichero binario. ¿Verlo de todos modos?.

strings: extraer el texto de un binario

operador@srv-tramontana:~$ strings /opt/tramontana/app/ejecutable | head -n 20
/lib64/ld-linux-x86-64.so.2
libc.so.6
Tramontana Reservas
3.2.1
ERROR: no se puede leer la configuración en %s
db_host
db_port
db_name
Reserva creada correctamente
...

strings busca secuencias de caracteres imprimibles de al menos cuatro bytes. Usos reales:

  • Averiguar la versión de un binario sin documentación.
  • Encontrar las rutas que un programa tiene compiladas dentro (aquí ves que lee una configuración).
  • Ver los mensajes de error que puede emitir, lo que ayuda a interpretar uno que no entiendes.
  • En análisis de seguridad, detectar cadenas sospechosas dentro de un binario desconocido.
Opción Qué hace
-n N Longitud mínima (por defecto 4)
-t x Muestra el desplazamiento en hexadecimal
-a Recorre el archivo entero, no solo las secciones de datos

xxd: ver los bytes

operador@srv-tramontana:~$ xxd /opt/tramontana/app/ejecutable | head -n 4
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 6013 0000 0000 0000  ..>.....`.......
00000020: 4000 0000 0000 0000 e8ad 4c00 0000 0000  @.........@L....
00000030: 0000 0000 4000 3800 0d00 4000 2100 2000  [email protected]...@.!. .

Tres columnas: desplazamiento en hexadecimal, los bytes en hexadecimal, y su representación como texto (los no imprimibles salen como punto).

Los primeros cuatro bytes, 7f 45 4c 46, son \x7fELF: el número mágico que identifica un ejecutable de Linux. Es exactamente lo que lee file para hacer su diagnóstico.

Dónde es útil de verdad xxd: para ver caracteres invisibles en un fichero de texto que da problemas.

operador@srv-tramontana:~$ xxd /tmp/config-luis.conf | head -n 2
00000000: efbb bf70 7565 7274 6f3d 3830 3830 0d0a  ...puerto=8080..
00000010: 7469 6d65 6f75 743d 3330 0d0a            timeout=30..

Dos patologías a la vista:

  • ef bb bf al principio es el BOM de UTF-8, una marca invisible que añaden algunos editores de Windows. El programa que lee el archivo ve la primera clave como \xef\xbb\xbfpuerto en lugar de puerto, no la reconoce, y usa el valor por defecto. Es un fallo que puede costar horas si no sabes que existe.
  • 0d 0a al final de cada línea es CRLF, los finales de línea de Windows.

Ninguna de las dos cosas se ve con cat, y ambas son evidentes con xxd. Por eso es una herramienta de diagnóstico, no de curiosidad.

Ver útiles complementarios: hexdump -C produce una salida casi idéntica y está disponible en más sistemas; od -c es el clásico POSIX.

  1. Comparar versiones: diff y sdiff

La pregunta más frecuente después de que algo deje de funcionar es «¿qué cambió?». diff la responde.

operador@srv-tramontana:~$ sudo diff /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf
7c7
< max_conexiones=50
---
> max_conexiones=200

Ese formato clásico es compacto pero críptico. El formato unificado, -u, es el que se usa hoy y el que entienden Git y todas las herramientas modernas:

operador@srv-tramontana:~$ sudo diff -u /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf
--- /etc/tramontana/app.conf.bak-2026-08-18	2026-08-18 12:15:03.000000000 +0200
+++ /etc/tramontana/app.conf	2026-08-18 12:31:47.000000000 +0200
@@ -4,7 +4,8 @@
 db_port=5432
 db_name=reservas

-max_conexiones=50
+max_conexiones=200
+timeout_consulta=30

 log_nivel=info

Cómo se lee:

Elemento Significado
--- El archivo original, con su fecha
+++ El archivo nuevo, con su fecha
@@ -4,7 +4,8 @@ Trozo: desde la línea 4, 7 líneas en el original; desde la 4, 8 en el nuevo
Línea con espacio Contexto: no ha cambiado
Línea con - Eliminada del original
Línea con + Añadida en el nuevo

En este ejemplo: se subió max_conexiones de 50 a 200 y se añadió timeout_consulta. Dos cambios, identificados en tres segundos.

Opciones útiles:

Opción Qué hace
-u Formato unificado. El que debes usar
-r Recursivo, para comparar directorios
-q Solo dice si difieren, no en qué
-i Ignora mayúsculas y minúsculas
-w Ignora todos los espacios en blanco
-B Ignora las líneas en blanco
--color=always Colorea las diferencias
-y Salida en dos columnas

-r con -q es lo que usaste para verificar el paquete de Luis en la lección anterior:

operador@srv-tramontana:~$ diff -rq /opt/tramontana/app /tmp/verificacion/app
operador@srv-tramontana:~$ echo $?
0

Sin salida y código 0: idénticos. Con diferencias sería:

operador@srv-tramontana:~$ diff -rq /opt/tramontana/app /tmp/verificacion/app
Los ficheros /opt/tramontana/app/version.txt y /tmp/verificacion/app/version.txt son distintos
Sólo en /opt/tramontana/app: nuevo.html

Los códigos de salida de diff son de los que hay que consultar en el manual, como aprendiste en la lección 02-02:

Código Significado
0 Los archivos son idénticos
1 Son distintos (no es un error)
2 Ha ocurrido un error real

sdiff: comparación en dos columnas

operador@srv-tramontana:~$ sudo sdiff -w 100 /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf
# Configuración Tramontana Reservas    # Configuración Tramontana Reservas
db_host=127.0.0.1                      db_host=127.0.0.1
db_port=5432                           db_port=5432
db_name=reservas                       db_name=reservas

max_conexiones=50                    | max_conexiones=200
                                     > timeout_consulta=30

log_nivel=info                         log_nivel=info

Los marcadores del centro:

  • | — la línea es distinta en ambos
  • < — solo está en el izquierdo
  • > — solo está en el derecho
  • (vacío) — idéntica

sdiff es más legible para revisar visualmente y peor para pegar en un informe o aplicar como parche. -w fija el ancho total; ajústalo a tu terminal.

sdiff -o salida entra además en un modo interactivo de fusión, línea a línea, útil para reconciliar dos versiones de una configuración a mano.

Herramientas relacionadas que conviene conocer: vimdiff (o vim -d) muestra las diferencias con color dentro de vim y permite mover cambios de un lado a otro; comm compara dos archivos ordenados línea a línea; y cmp compara byte a byte y sirve para binarios, donde diff no aporta nada legible.

Errores Comunes y Consejos

Hacer cat de un archivo enorme. Miles de líneas pasando y solo ves las últimas. less o tail.

Hacer cat de un binario. Terminal roto. file primero, y reset si ya es tarde.

Usar tail -f en un log que rota. Se queda mudo sin avisar. -F siempre en producción.

No saber salir de vim. Esc, :q!, Enter. Y haz vimtutor una vez.

Editar configuración sin copia previa. El error más caro de la lección, y el más fácil de evitar.

Dejar que nano corte líneas largas. set nowrap en ~/.nanorc, o una directiva partida en dos romperá el servicio.

Editar con sudo nano un archivo y olvidar el sudo. Haces todo el trabajo y al guardar descubres que es de solo lectura. En vim hay rescate (:w !sudo tee %); en nano puedes guardar en /tmp con Ctrl+O y moverlo después.

Consejo: less +F en vez de tail -F cuando estés investigando. Puedes parar y buscar hacia atrás sin cerrar nada.

Consejo: less -S para logs con líneas largas. Cambia por completo la legibilidad.

Consejo: diff -u justo después de editar, siempre. Antes de recargar el servicio, mira lo que has hecho. Muchas veces descubrirás un cambio accidental.

Consejo: aprende a usar & dentro de less. Filtrar sin salir del visor es más rápido que cualquier tubería.

Ejercicios

Ejercicio 1: análisis de un log

Sobre /var/log/tramontana/acceso.log en srv-tramontana, y sin usar grep (que es del Módulo 3):

  1. ¿Cuántas líneas tiene?
  2. Muestra la primera y la última.
  3. Muestra las líneas de la 100 a la 105.
  4. Abre el archivo con less, ve al final, busca hacia atrás la primera aparición de 500 y anota la línea. Sal sin cerrar la sesión.
  5. Deja el archivo en seguimiento en vivo de forma que sobreviva a una rotación.

Ejercicio 2: edición segura de la configuración

Marta ha aprobado subir el límite de conexiones de la aplicación. Tienes que cambiar max_conexiones de 50 a 200 en /etc/tramontana/app.conf y añadir una línea timeout_consulta=30.

Ejecuta el procedimiento completo de edición segura, incluyendo la verificación del cambio, y prepara un resumen de dos líneas para Marta con exactamente lo que has modificado. Hazlo primero con nano y repítelo con vim para practicar.

Ejercicio 3: el fichero que no funciona

Luis te pasa un /tmp/config-luis.conf que «tiene la misma configuración pero la aplicación no lo lee bien». La aplicación devuelve valores por defecto en vez de los del archivo.

operador@srv-tramontana:~$ cat /tmp/config-luis.conf
puerto=8080
timeout=30
log_nivel=debug

A simple vista parece correcto. Diagnostica el problema con las herramientas de esta lección y explica a Luis por qué ocurre y cómo evitarlo en el futuro.

Soluciones

Solución 1

# 1. Número de líneas
operador@srv-tramontana:~$ sudo wc -l /var/log/tramontana/acceso.log
412 /var/log/tramontana/acceso.log

# 2. Primera y última
operador@srv-tramontana:~$ sudo head -n 1 /var/log/tramontana/acceso.log
2026-08-18 00:00:14 GET /casas 200 usuario=anon
operador@srv-tramontana:~$ sudo tail -n 1 /var/log/tramontana/acceso.log
2026-08-18 09:14:11 GET /casas 200 usuario=anon

# 3. Líneas 100 a 105
operador@srv-tramontana:~$ sudo head -n 105 /var/log/tramontana/acceso.log | tail -n 6
2026-08-18 03:41:02 GET /reservas 200 usuario=mvidal
2026-08-18 03:41:19 POST /reservas 201 casa=can-ventos
...

La combinación head -n 105 | tail -n 6 es el modismo clásico para extraer un rango: coge las primeras 105 y de esas quédate con las 6 últimas. Cuidado con el cálculo: para las líneas 100 a 105 son seis líneas, no cinco.

Alternativa más limpia con sed, que verás en la lección 03-05:

operador@srv-tramontana:~$ sudo sed -n '100,105p' /var/log/tramontana/acceso.log

4. Dentro de less:

operador@srv-tramontana:~$ sudo less -N /var/log/tramontana/acceso.log
  • G para ir al final.
  • ?500 y Enter para buscar hacia atrás (? es la búsqueda inversa; con / buscarías hacia delante y desde el final no encontrarías nada).
  • N para seguir hacia atrás si quieres ver más coincidencias, n para volver hacia delante.
  • El número de línea lo ves gracias a -N.
  • q para salir.
   287 2026-08-18 07:22:41 POST /reservas 500 casa=la-solana

5. Seguimiento resistente a la rotación:

operador@srv-tramontana:~$ sudo tail -F /var/log/tramontana/acceso.log

-F, no -f. Con -f, cuando logrotate renombre el archivo esta noche, el comando seguirá mirando el fichero antiguo y no mostrará nada más, sin ningún aviso. Con -F detecta el reemplazo, lo anuncia y reengancha con el archivo nuevo.

Si además quieres poder investigar mientras vigilas:

operador@srv-tramontana:~$ sudo less +F /var/log/tramontana/acceso.log

Ctrl+C para pausar y buscar, F para volver a seguir.

Solución 2

Versión con nano:

# 1. Copia de seguridad ANTES de nada
operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf /etc/tramontana/app.conf.bak-$(date +%F)

operador@srv-tramontana:~$ ls -l /etc/tramontana/
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
-rw-r----- 1 root tramontana 512 ago 18 12:15 app.conf.bak-2026-08-18

# 2. Editar
operador@srv-tramontana:~$ sudo nano /etc/tramontana/app.conf

Dentro de nano: Ctrl+W, escribes max_conexiones, Enter. El cursor va a la línea. Ctrl+K la corta y escribes la nueva, o mejor: te sitúas con End, borras el 50 y escribes 200. Luego Ctrl+E (final de línea), Enter para una línea nueva, y escribes timeout_consulta=30. Guardas con Ctrl+O, Enter, y sales con Ctrl+X.

# 3. Verificar exactamente qué ha cambiado
operador@srv-tramontana:~$ sudo diff -u /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf
--- /etc/tramontana/app.conf.bak-2026-08-18	2026-08-18 12:15:03.000000000 +0200
+++ /etc/tramontana/app.conf	2026-08-18 12:31:47.000000000 +0200
@@ -4,7 +4,8 @@
 db_port=5432
 db_name=reservas

-max_conexiones=50
+max_conexiones=200
+timeout_consulta=30

 log_nivel=info

# 4. Comprobar que no se ha roto el formato del archivo
operador@srv-tramontana:~$ sudo cat -A /etc/tramontana/app.conf | tail -n 5
max_conexiones=200$
timeout_consulta=30$
$
log_nivel=info$

Ese cat -A confirma que no hay ^M ni líneas partidas: cada línea acaba limpiamente en $.

Versión con vim, partiendo de la copia restaurada:

operador@srv-tramontana:~$ sudo cp /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf
operador@srv-tramontana:~$ sudo vim /etc/tramontana/app.conf

Secuencia de teclas:

  1. /max_conexiones y Enter — busca y sitúa el cursor.
  2. A — inserción al final de la línea.
  3. Borras 50 con retroceso y escribes 200.
  4. Esc — vuelves a modo normal.
  5. o — abre una línea nueva debajo y entra en inserción.
  6. Escribes timeout_consulta=30.
  7. Esc, luego :wq y Enter.

Alternativa aún más rápida para el primer cambio, con sustitución y confirmación:

:%s/max_conexiones=50/max_conexiones=200/gc

La c final hace que pregunte antes de sustituir. En un fichero de producción, siempre con c.

# 3 y 4 igual que antes
operador@srv-tramontana:~$ sudo diff -u /etc/tramontana/app.conf.bak-2026-08-18 /etc/tramontana/app.conf

Resumen para Marta:

Cambio aplicado en la configuración de Tramontana Reservas (/etc/tramontana/app.conf) el 18/08/2026 a las 12:31: el límite de conexiones simultáneas sube de 50 a 200 y se añade un tiempo máximo de espera por consulta de 30 segundos, para que una consulta bloqueada no retenga una conexión indefinidamente.

Se ha guardado una copia de la configuración anterior (app.conf.bak-2026-08-18), de modo que revertir el cambio es cuestión de segundos si detectamos cualquier efecto no deseado. El cambio requiere recargar el servicio para surtir efecto.

Ese informe tiene lo que Marta necesita: qué cambió, cuándo, por qué y cómo se deshace.

Solución 3

cat no muestra el problema porque el problema es invisible por definición. Diagnóstico por pasos:

# Paso 1: ¿qué tipo de archivo es realmente?
operador@srv-tramontana:~$ file /tmp/config-luis.conf
/tmp/config-luis.conf: Unicode text, UTF-8 (with BOM) text, with CRLF line terminators

file ya da el diagnóstico completo en una línea: BOM de UTF-8 y terminadores CRLF. Dos problemas, ambos causados por haber editado el archivo en un editor de Windows.

# Paso 2: confirmarlo viendo los caracteres de control
operador@srv-tramontana:~$ cat -A /tmp/config-luis.conf
M-oM-;M-?puerto=8080^M$
timeout=30^M$
log_nivel=debug^M$

# Paso 3: verlo byte a byte para no dejar dudas
operador@srv-tramontana:~$ xxd /tmp/config-luis.conf | head -n 2
00000000: efbb bf70 7565 7274 6f3d 3830 3830 0d0a  ...puerto=8080..
00000010: 7469 6d65 6f75 743d 3330 0d0a 6c6f 675f  timeout=30..log_

Qué está pasando exactamente:

Problema 1: el BOM (ef bb bf). Son tres bytes invisibles al principio del archivo, una marca que algunos editores de Windows insertan para señalar que el fichero es UTF-8. La aplicación, al leer la primera línea, no ve la clave puerto, sino \xef\xbb\xbfpuerto. No la reconoce como clave válida, así que usa el valor por defecto y sigue como si nada. Solo afecta a la primera línea, lo que hace el fallo aún más confuso: parece que unas opciones funcionan y otras no.

Problema 2: CRLF (0d 0a). Cada línea acaba con retorno de carro más salto de línea, mientras que Unix usa solo salto de línea. La aplicación lee el valor de timeout como 30\r, no como 30. Si espera un número, la conversión falla y cae al valor por defecto. Y si el valor fuera una ruta, intentaría abrir un archivo cuyo nombre acaba en un carácter invisible, con un mensaje de error del tipo No existe el fichero: /var/log/app.log en el que la ruta se ve perfectamente correcta.

La solución:

# Copia antes de tocar, como siempre
operador@srv-tramontana:~$ cp /tmp/config-luis.conf /tmp/config-luis.conf.bak-$(date +%F)

# Instalar la herramienta específica
operador@srv-tramontana:~$ sudo apt install -y dos2unix

# Convertir: dos2unix elimina el BOM y los CR de una vez
operador@srv-tramontana:~$ dos2unix /tmp/config-luis.conf
dos2unix: convirtiendo el fichero /tmp/config-luis.conf a formato Unix...

# Verificar
operador@srv-tramontana:~$ file /tmp/config-luis.conf
/tmp/config-luis.conf: ASCII text

operador@srv-tramontana:~$ cat -A /tmp/config-luis.conf
puerto=8080$
timeout=30$
log_nivel=debug$

operador@srv-tramontana:~$ xxd /tmp/config-luis.conf | head -n 1
00000000: 7075 6572 746f 3d38 3038 300a 7469 6d65  puerto=8080.time

Ahora el archivo empieza directamente por puerto y cada línea acaba en 0a. Comparación final:

operador@srv-tramontana:~$ diff /tmp/config-luis.conf.bak-2026-08-18 /tmp/config-luis.conf
1,3c1,3
< puerto=8080
---
> puerto=8080
...

diff marca las tres líneas como distintas aunque se vean idénticas. Esa salida desconcertante es, por sí sola, la firma de un problema de caracteres invisibles: si diff dice que dos líneas iguales son distintas, la diferencia está en bytes que no se imprimen.

Qué le explicas a Luis:

El archivo es correcto en su contenido, pero no en su codificación. Lo has editado en Windows y el editor ha añadido dos cosas invisibles: una marca de tres bytes al principio del fichero (el BOM) y un retorno de carro al final de cada línea. La aplicación lee la primera clave como si tuviera tres caracteres raros delante y todos los valores con un carácter invisible al final, así que no reconoce ninguno y aplica los valores por defecto. De ahí que «parezca» que no lee el archivo.

Para que no vuelva a pasar: en tu editor de Windows, configura el final de línea como LF y la codificación como UTF-8 sin BOM (en VS Code se ve y se cambia en la barra de estado, abajo a la derecha). Si el archivo ya viene de Windows, dos2unix lo arregla en un comando. Y para comprobarlo antes de dar nada por bueno, file archivo te lo dice en una línea.

Un consejo adicional: es más seguro editar los ficheros de configuración directamente en el servidor con nano o vim que traerlos, editarlos en Windows y devolverlos. Cada viaje de ida y vuelta es una oportunidad de que se cuelen estos caracteres.

Este caso es un buen ejemplo de un principio general: cuando algo «debería funcionar» y no funciona, mira los bytes. Las tres herramientas de esta lección —file, cat -A y xxd— resuelven en un minuto una clase de problema que puede costar una tarde entera.

Conclusión

Ya sabes leer y escribir el contenido de los archivos, que es la materia prima de la administración de sistemas.

  • cat para lo que cabe en pantalla, tac para invertirlo, y sabes qué es el «uso inútil de cat» y por qué importa más allá del purismo.
  • less es el visor de verdad: abre archivos enormes al instante, busca con /, filtra con &, no corta líneas con -S y sigue logs en vivo con +F sin renunciar a buscar hacia atrás. more está superado.
  • head y tail para los extremos, con -n +2 para saltarse cabeceras, y tail -F en lugar de -f siempre que un log pueda rotar.
  • nl y wc para numerar y contar, con la distinción entre bytes y caracteres que importa en UTF-8.
  • Conoces el panorama de editores y la decisión razonable: nano a diario, vim lo justo para no quedarte encerrado.
  • nano completo, con la lectura de su barra de atajos (^ es Ctrl, M- es Alt) y un ~/.nanorc mínimo donde set nowrap evita romper configuraciones.
  • vim de supervivencia: modos, Esc como salida de emergencia, :q! como paracaídas, dd/yy/p/u, /buscar, :%s/a/b/gc y vimtutor pendiente de hacer una vez.
  • La convención que adoptamos a partir de aquí: cp fichero fichero.bak-$(date +%F) antes de editar, y diff -u después para verificar el cambio.
  • file, strings, xxd para lo que no es texto, reset para recuperar el terminal, y la costumbre de comprobar antes de abrir.
  • diff -u para saber qué cambió, con su formato unificado leído línea a línea, y sdiff para revisarlo en paralelo.

Has trabajado todo el módulo con nombres de archivo dando por hecho que cada nombre corresponde a un archivo. En la próxima lección, Enlaces Duros y Simbólicos, esa suposición se rompe: verás que el nombre y el contenido son cosas separadas, que un mismo archivo puede tener varios nombres a la vez, y que hay archivos cuyo contenido es simplemente la ruta de otro. Entenderás qué es un inodo, por qué el número de enlaces de un directorio nunca es 1, por qué /bin aparece con una flecha en tree, y diseñarás el patrón de despliegue con el que Tramontana convertirá una publicación en producción y una vuelta atrás en un cambio de enlace instantáneo.

Curso de Linux: De Principiante a Administrador de Sistemas

Módulo 1: Introducción a Linux

Módulo 2: Comandos Básicos de Linux

Módulo 3: Habilidades Avanzadas en la Línea de Comandos

Módulo 4: Scripting en Shell

Módulo 5: Administración del Sistema

Módulo 6: Redes y Seguridad

Módulo 7: Temas Avanzados

Módulo 8: Proyectos Prácticos

© Copyright 2026. Todos los derechos reservados