Módulo 4: Permisos, procesos y entorno

5. Procesos, trabajos y señales: ps, top, kill y jobs

Descripción

Al terminar esta lección vas a poder listar cualquier proceso que corra en tu sistema y leer su PID, su consumo de CPU y memoria y su relación padre-hijo; enviarle la señal correcta según lo que de verdad quieras lograr —no siempre la más agresiva—; suspender un proceso, mandarlo a segundo plano y devolverlo al primer plano sin perder su trabajo; y, el caso más concreto de todos, encontrar exactamente qué proceso está ocupando un puerto y terminarlo con criterio.

Esto es exactamente lo que pasa la próxima vez que corras npm run dev, python manage.py runserver o cualquier servidor local y el sistema te responda con algo como Error: listen EADDRINUSE: address already in use :::3000. La reacción instintiva de casi todo junior es reiniciar la computadora —treinta segundos de espera para "arreglar" algo que en realidad se resuelve en cinco segundos con un comando—. Lo que dejó el puerto ocupado casi siempre es un proceso de una sesión anterior que nunca terminó bien: una terminal que cerraste de golpe, un servidor que lanzaste hace dos horas y olvidaste, un proceso que quedó colgado. Diagnosticar en vez de reiniciar es exactamente la diferencia que este módulo promete.

Conexión con el módulo: la lección anterior te enseñó quién puede tocar qué archivo. Esta lección cambia la pregunta: ya no es "quién puede", sino "qué está corriendo ahora mismo, y qué relación tiene con lo demás". Vas a usar sudo en algún ejemplo cuando el proceso pertenezca a otro usuario o al sistema —eso ya lo entiendes de la lección anterior—, pero el tema de hoy es otro: procesos, señales y trabajos. Todavía no vas a tocar el PATH ni las variables de entorno; eso es exactamente lo que viene después, cuando resuelvas el tercer error clásico del módulo, command not found.

Un proceso es un trabajador con gafete, no una casilla en una lista

Piensa en tu sistema operativo como una oficina que contrata trabajadores temporales para cada tarea. Cada vez que ejecutas un programa, el sistema contrata a un trabajador nuevo y le entrega un gafete con un número que nadie más va a tener mientras ese trabajador siga activo. Ese número es el PID (process ID). Ningún trabajador aparece de la nada: alguien más lo contrató —otro trabajador que ya estaba activo—, y ese alguien es su padre, identificado por el PPID (parent PID). Cuando escribes un comando en tu terminal y presionas Enter, es tu propia shell —que es, a su vez, un proceso con su propio PID— la que contrata al nuevo trabajador para ejecutar justo esa tarea. Si cierras la shell, en la mayoría de los casos también se van los trabajadores que ella contrató: por eso a veces cerrar una terminal mata de golpe todo lo que corría adentro.

Formalmente: un proceso es una instancia en ejecución de un programa. No es el programa en sí —el archivo node en disco es un solo programa, pero puedes tener diez procesos node corriendo al mismo tiempo, cada uno con su propio PID, su propia memoria y su propio estado—. Cada proceso tiene, como mínimo: un PID único, un PPID que apunta a quien lo creó, un usuario dueño (la identidad que viste en la lección 2 de este módulo), un estado, y una porción de CPU y memoria que está usando en este instante.

Ejemplo trabajado

La herramienta más directa para ver todos los trabajadores activos es ps (process status). Con las opciones aux —sin guion, es una convención histórica de BSD— ves la lista completa de procesos de todos los usuarios, no solo los tuyos:

ps aux

Qué esperar (salida recortada; en tu máquina van a aparecer decenas de líneas más):

USER       PID  %CPU %MEM    VSZ    RSS TTY      STAT START   TIME COMMAND
root         1   0.0   0.1  16800   9312 ?        Ss   09:03   0:01 /sbin/init
dev        842   0.2   0.5 715200  42112 ?        Sl   09:04   0:03 /usr/bin/dockerd
dev       2210   0.0   0.0   9028   5120 pts/0    Ss   09:14   0:00 -bash
dev       3391  12.4   2.1 981200 168420 pts/0    Sl+  10:02   1:47 node server.js
dev       3402   0.0   0.0   9028   1560 pts/0    S+   10:02   0:00 grep node

Léela columna por columna, de izquierda a derecha:

  • USER: el dueño del proceso —el mismo modelo de identidad que viste en la lección 2—. Nota que init pertenece a root: es el primer proceso que arranca al encender la máquina, y el padre, directo o indirecto, de todos los demás.
  • PID: el gafete único de ese trabajador. Es el número que vas a necesitar cuando quieras enviarle una señal más adelante en esta lección.
  • %CPU y %MEM: cuánto procesador y cuánta memoria está consumiendo ese proceso en este instante, como porcentaje. El proceso node server.js con 12.4 en %CPU es el candidato más claro si tu ventilador empezó a sonar de repente.
  • VSZ (virtual size) y RSS (resident set size): dos formas distintas de medir memoria, ambas en kibibytes. VSZ es toda la memoria que el proceso podría llegar a usar, incluida la que nunca toca; RSS es la memoria física que realmente está ocupando ahora mismo. RSS es casi siempre el número que te interesa cuando sospechas una fuga de memoria.
  • TTY: la terminal a la que está atado el proceso. El signo de interrogación (?) significa que no tiene una terminal asociada —es el caso normal de un servicio del sistema como dockerd—; pts/0 significa que está corriendo en tu terminal actual.
  • STAT: el estado del proceso, la columna que más vas a mirar para diagnosticar. S es reposo interrumpible (esperando algo, como entrada del teclado); R es corriendo activamente; Z es un proceso zombie —ya terminó, pero su padre todavía no leyó su código de salida—; T es detenido por una señal de control de trabajos, que es justo el tema de una sección más adelante en esta misma lección. El símbolo + junto al estado significa que el proceso corre en primer plano de su terminal; l indica que usa varios hilos internos; s marca al líder de sesión.
  • START y TIME: cuándo arrancó el proceso, y cuánto tiempo de CPU acumulado ha consumido —no cuánto tiempo lleva vivo, sino cuánto tiempo de procesador realmente usó—.
  • COMMAND: el comando exacto con el que se lanzó, con sus argumentos.

Fíjate en la última línea: grep node aparece en la propia salida, con %CPU en cero. No es casualidad ni un error: estabas buscando "node" con un grep, y el propio proceso de grep tiene la palabra "node" en su línea de comando, así que se encuentra a sí mismo. Es el mismo tipo de sorpresa que ya viste con grep en el módulo 2, aplicada esta vez a procesos en lugar de líneas de texto.

Para evitar ese ruido y no tener que leer una lista completa, pgrep busca directamente por nombre de proceso y te devuelve solo los PIDs que coinciden, sin que aparezca su propio grep de por medio:

pgrep -l node

Qué esperar:

3391 node

-l agrega el nombre del proceso junto al PID, para que no tengas que adivinar a qué corresponde cada número. Si necesitas buscar por algo que no es el nombre del programa sino un fragmento de sus argumentos —por ejemplo, el nombre del script exacto—, -f amplía la búsqueda a la línea de comando completa:

pgrep -fl "server.js"

Qué esperar:

3391 node server.js

Ver el consumo en vivo: top y htop

ps aux es una fotografía: el estado exacto de todos los procesos en el instante en que lo ejecutaste, y nada más. Si quieres ver cómo cambia el consumo de CPU y memoria segundo a segundo —por ejemplo, para confirmar si un proceso realmente está consumiendo cada vez más recursos o si fue un pico momentáneo— necesitas algo que se actualice solo. Para eso existe top:

top

Qué esperar: una pantalla que se actualiza sola, cada pocos segundos, con un resumen del sistema arriba (carga promedio, memoria total y en uso) y, debajo, la misma clase de columnas que ya conoces de ps aux —PID, USER, %CPU, %MEM, COMMAND— pero ordenadas por consumo de CPU de mayor a menor, así el proceso que más está exigiendo a la máquina queda siempre arriba, a la vista. Sales con q. Los atajos internos para reordenar, filtrar o matar un proceso desde ahí mismo varían un poco entre la versión de macOS y la de Linux —la forma más confiable de aprenderlos es presionar ? o h dentro del propio programa, exactamente el hábito de leer la ayuda que ya practicaste en el módulo 1.

htop es una alternativa con interfaz a color, barras de uso de CPU por núcleo y navegación con el mouse o las flechas, que a la mayoría le resulta más cómoda de leer que top. No viene preinstalado en todas las distribuciones ni en macOS —se instala con el gestor de paquetes de tu sistema, un tema que queda fuera del alcance de esta guía—. Si ya lo tienes disponible, vale la pena probarlo; si no, top hace exactamente el mismo trabajo con una interfaz más austera.

Señales: pedirle algo a un proceso, no golpearlo

Antes de tocar kill, vale la pena corregir la idea que casi todo el mundo trae de entrada: kill no mata un proceso directamente. Envía una señal —un mensaje corto, identificado por un nombre y un número, que el sistema operativo entrega al proceso—. Lo que pasa después depende de qué señal sea y de cómo esté escrito ese proceso: la mayoría de las señales pueden ser capturadas, ignoradas o manejadas con código propio antes de terminar; solo una no puede.

Las que más vas a usar:

SeñalNúmero (típico en Linux x86)Qué significaQuién la dispara
SIGINT2Interrupción desde el tecladoCtrl+C
SIGTSTP20Detente, pero puedes seguir despuésCtrl+Z
SIGTERM15Pedido de terminar, con oportunidad de limpiarkill sin flags (es el valor por defecto)
SIGKILL9Terminación inmediata, sin excepción posiblekill -9

Los números exactos pueden variar según la arquitectura o el sistema operativo —por eso en la práctica casi nadie los memoriza y casi todo el mundo usa el nombre o, cuando mucho, el número de SIGTERM y SIGKILL, que son estables en la inmensa mayoría de sistemas—.

Ctrl+C envía SIGINT al proceso que tienes en primer plano en este momento. Por defecto, SIGINT termina el proceso —pero el proceso puede decidir capturar esa señal y hacer otra cosa: guardar su estado, preguntar "¿seguro que quieres salir?", o de plano ignorarla—. Por eso a veces presionas Ctrl+C y el proceso sigue vivo: no falló el atajo, el proceso decidió no obedecer esa señal en particular.

kill PID envía SIGTERM por defecto: un pedido educado de terminar, que le da al proceso la oportunidad de cerrar archivos abiertos, liberar bloqueos, guardar su estado o desconectarse limpiamente de una base de datos antes de irse. kill -9 PID (equivalente a kill -SIGKILL PID) envía una señal que ni el proceso ni el propio kernel pueden posponer: el proceso termina de inmediato, en el punto exacto en que estaba, sin ninguna oportunidad de limpieza.

Ejemplo trabajado

Retomas el proceso node server.js con PID 3391 que viste antes con ps aux. Le pides que termine, de la forma más respetuosa posible:

kill 3391

Qué esperar: nada en pantalla. Si vuelves a correr ps aux | grep node, ese PID ya no aparece —el proceso recibió SIGTERM, tuvo la oportunidad de cerrar su conexión y sus archivos, y terminó por su cuenta.

Ahora imagina un proceso distinto, uno que quedó verdaderamente colgado —esperando una operación de red que nunca va a completarse, por ejemplo— y que ni siquiera responde a SIGTERM después de varios segundos de espera. Solo entonces escalas:

kill -9 4820

Qué esperar: el proceso desaparece de inmediato, sin excepción posible. Y exactamente por eso kill -9 es el último recurso y no el primero: si ese proceso tenía un archivo a medio escribir o una transacción de base de datos a medio confirmar, SIGKILL no le dio ninguna chance de cerrarla con cuidado —simplemente se detuvo donde estaba—.

Control de trabajos: pausar, mandar a segundo plano y traer de vuelta

Tu terminal es un solo escritorio: en primer plano, en un momento dado, solo puede haber un proceso recibiendo lo que escribes. Pero eso no significa que tengas que elegir entre "esperar a que termine" o "cerrar la terminal y perderlo todo". Puedes pausar un trabajo, dejarlo aparcado, retomar otro, o mandar uno a que siga corriendo solo en segundo plano mientras usas el mismo escritorio para otra cosa.

Cuatro piezas hacen esto posible:

  • Ctrl+Z envía SIGTSTP al proceso en primer plano: lo pausa por completo (no sigue consumiendo CPU) y te devuelve el control de la terminal de inmediato.
  • jobs lista los trabajos pausados o en segundo plano que pertenecen a tu sesión actual de shell, con un número de trabajo para cada uno (%1, %2, …).
  • bg %n reanuda el trabajo número n para que siga corriendo, pero en segundo plano —sin bloquear tu terminal—.
  • fg %n trae el trabajo número n de vuelta al primer plano, exactamente donde lo dejaste.
  • & al final de un comando lo lanza directamente en segundo plano desde el principio, sin que nunca ocupe tu terminal.

Ejemplo trabajado

Lanzas un servidor de desarrollo y, como es normal, la terminal queda ocupada mostrando su salida sin devolverte el prompt:

$ npm run dev
> Server listening on port 3000

Necesitas seguir trabajando en esa misma terminal sin cerrar el servidor. Presionas Ctrl+Z:

$ npm run dev
> Server listening on port 3000
^Z
[1]+  Stopped                 npm run dev

El servidor quedó pausado, no corriendo en segundo plano todavía —nota la diferencia—: en este momento no está atendiendo ninguna petición. Confirmas con jobs:

$ jobs
[1]+  Stopped                 npm run dev

Lo mandas a correr en segundo plano de verdad:

$ bg %1
[1]+ npm run dev &

Ahora sí sigue corriendo, atendiendo peticiones, y tu prompt está libre para lo que sigas necesitando. Una cosa a tener en cuenta: si ese proceso sigue imprimiendo su propia salida, esas líneas van a seguir apareciendo en tu terminal aunque el trabajo esté en segundo plano —un trabajo en segundo plano no deja de escribir en pantalla solo porque tú recuperaste el prompt—. Si eso te molesta, ya sabes la solución del módulo 3: la próxima vez que lo lances, redirige su salida a un archivo con npm run dev > server.log 2>&1 &, todo en una sola línea, directo a segundo plano desde el arranque.

Si más tarde necesitas volver a interactuar con él directamente —por ejemplo, para presionar Ctrl+C y cerrarlo con cuidado—, lo traes de regreso al primer plano:

fg %1

Qué esperar: el servidor vuelve a ocupar tu terminal exactamente como si nunca lo hubieras pausado, mostrando su salida en vivo otra vez.

Encontrar y liberar un puerto ocupado

Un puerto se comporta como una línea telefónica: solo un proceso puede estar "atendiendo" en un puerto dado a la vez. Si intentas levantar un segundo servidor en el mismo puerto, el sistema operativo lo rechaza de inmediato —no porque el nuevo comando esté mal escrito, sino porque la línea ya está ocupada por alguien más—.

npm run dev

Qué esperar:

Error: listen EADDRINUSE: address already in use :::3000

El mensaje te dice exactamente cuál es el problema (la dirección ya está en uso), pero no quién la está usando. Para averiguarlo, lsof (list open files —en Unix, un socket de red también cuenta como un archivo abierto—) con -i y el puerto:

lsof -i :3000

Qué esperar:

COMMAND  PID USER   FD   TYPE  NODE NAME
node    4820  dev   22u  IPv6  TCP  *:3000 (LISTEN)

Ahí está: el proceso node con PID 4820, de tu propio usuario, escuchando en el puerto 3000. Es casi seguro un servidor de una sesión anterior que nunca cerraste. En sistemas Linux (incluido WSL) tienes además ss, el reemplazo moderno del viejo netstat, que vas a ver a fondo cuando el módulo 5 entre en diagnóstico de red —aquí solo te interesa que también resuelve la misma pregunta—:

sudo ss -tulpn | grep :3000

Qué esperar:

tcp   LISTEN 0      511          0.0.0.0:3000       0.0.0.0:*    users:(("node",pid=4820,fd=22))

El PID aparece igual, 4820, esta vez dentro del paréntesis final. (Si el proceso perteneciera a otro usuario o a un servicio del sistema, tanto lsof como ss necesitarían el sudo que ya conoces de la lección anterior para mostrarte su información completa.)

Con el PID en la mano, aplicas exactamente el criterio de la sección anterior: primero pides con educación, y solo si no responde escalas.

kill 4820

Qué esperar: nada en pantalla. Verificas que el puerto quedó libre corriendo lsof -i :3000 de nuevo —si no imprime ninguna línea, el puerto está libre y ya puedes lanzar tu servidor sin error—.

Y si tienes prisa y confías en que un SIGTERM directo va a bastar, puedes encadenar todo en una sola línea reutilizando xargs, que ya conoces del módulo 3: -t le pide a lsof que imprima solo el PID, sin las demás columnas, listo para que xargs lo convierta en argumento de kill.

lsof -ti :3000 | xargs kill

Qué esperar: el mismo resultado que antes, en una sola línea: el proceso que ocupaba el puerto 3000 recibe SIGTERM y termina, dejando el puerto libre para tu próximo intento.

Errores comunes

1. Creer que kill -9 es la opción "más fuerte" y por lo tanto la más conveniente de usar siempre (conceptual). Qué pasa: el estudiante escribe kill -9 como reflejo ante cualquier proceso que no responde de inmediato, incluso en su primer intento. Por qué ocurre: kill sin flags suena "más débil" que kill -9, y la intuición asocia "más fuerte" con "mejor". Pero SIGTERM (el valor por defecto) le da al proceso la chance de cerrar archivos, liberar bloqueos y guardar su estado antes de irse; SIGKILL termina el proceso en el kernel, en el punto exacto en que estaba, sin ninguna oportunidad de limpiar nada. Cómo detectarlo: si tu primer comando ante cualquier proceso problemático incluye -9, sin haber esperado ni intentado un kill simple antes. Cómo corregirlo: siempre kill PID primero, esperar unos segundos y verificar con ps si el proceso sigue vivo; solo si sigue ahí, entonces kill -9. Es particularmente importante con cualquier proceso que escriba datos —una base de datos, un proceso que edita un archivo— donde una terminación abrupta puede dejar algo a medio escribir.

2. Confundir el PID con el número de trabajo al usar fg o bg. Qué pasa: el estudiante ve el PID de un proceso (por ejemplo con ps aux) y escribe fg 4820, esperando traerlo al primer plano, y recibe un error del estilo "no such job". Por qué ocurre: fg y bg trabajan con números de trabajo (%1, %2, …), que tu shell asigna y numera para su propia sesión, no con PIDs, que el kernel asigna de forma global a todo el sistema —son dos sistemas de numeración completamente distintos, aunque ambos sean números pequeños que se ven parecidos—. Cómo detectarlo: un mensaje de error mencionando "job" pese a que confirmaste con ps que el proceso existe y sigue vivo. Cómo corregirlo: corre jobs para ver el número de trabajo correcto y antepón el signo de porcentaje (fg %1), o simplemente escribe fg sin ningún argumento para traer el trabajo más reciente.

3. Un trabajo en segundo plano que necesita leer del teclado se detiene solo. Qué pasa: mandas un proceso a segundo plano con bg o &, y en algún momento se detiene por su cuenta sin ningún error visible; al correr jobs, aparece con el estado "Stopped" en vez de "Running". Por qué ocurre: un proceso en segundo plano no puede leer directamente del teclado de tu terminal —si en algún punto intenta pedir una confirmación o una contraseña interactiva, el sistema lo detiene automáticamente en vez de dejarlo esperando entrada que nunca le va a llegar—. Cómo detectarlo: jobs muestra el trabajo detenido (no corriendo) después de haberlo mandado a segundo plano sin que tú hicieras nada. Cómo corregirlo: tráelo al primer plano con fg para darle la entrada que está esperando, o evita el problema de raíz lanzándolo con las banderas que evitan confirmaciones interactivas antes de mandarlo a segundo plano.

Ejercicios

1. Esta es la salida de ps aux en tu máquina. Un proceso está consumiendo muchísimo más CPU de lo normal. Identifícalo y escribe el comando para terminarlo, empezando siempre por el intento más respetuoso.

USER    PID  %CPU %MEM    VSZ    RSS TTY   STAT START   TIME COMMAND
dev     501   0.1   0.3  45200  12100 ?     Ss   08:00   0:02 /usr/lib/systemd/systemd
dev    3120  97.8   4.2 512300 210400 pts/1 R+   09:45   4:12 python train_model.py
dev    3405   0.0   0.1  10200   3200 pts/0 S+   09:50   0:00 bash
Ver solución

El proceso problemático es python train_model.py, con PID 3120 y 97.8 en la columna %CPU. El comando correcto para empezar es el pedido educado, sin flags:

kill 3120

Solo si después de unos segundos el proceso sigue apareciendo en ps aux —confirmando que ignoró el SIGTERM— escalarías a kill -9 3120.

Por qué funciona: %CPU es la columna diseñada exactamente para esto —comparar de un vistazo el consumo relativo de cada proceso— y empezar con SIGTERM le da al proceso la oportunidad de cerrar limpiamente antes de forzar su terminación con SIGKILL.

2. Estás corriendo python train_model.py en primer plano y necesitas el control de la terminal de vuelta sin detener el entrenamiento. Describe la secuencia exacta de comandos que usarías, en orden.

Ver solución
  1. Ctrl+Z — pausa el proceso y devuelve el control de la terminal de inmediato. En este punto el entrenamiento está detenido, no corriendo.
  2. jobs — confirma que el proceso aparece como "Stopped" y averigua su número de trabajo (por ejemplo, %1).
  3. bg %1 — reanuda el proceso, pero en segundo plano, para que el entrenamiento siga corriendo mientras usas la terminal para otra cosa.

Por qué funciona: Ctrl+Z y bg son dos pasos distintos a propósito —pausar y reanudar en segundo plano no son la misma acción—, y separarlos te da la oportunidad de confirmar con jobs que estás por reanudar el trabajo correcto antes de hacerlo.

3. Intentas levantar un servidor con npm run dev y ves Error: listen EADDRINUSE: address already in use :::5000. Describe, paso a paso, cómo diagnosticarías y resolverías esto usando lsof.

Ver solución
  1. lsof -i :5000 — para identificar qué proceso está escuchando exactamente en ese puerto, junto con su PID y su usuario dueño.
  2. Con el PID identificado, kill PID (sin flags) para pedirle que termine de forma respetuosa.
  3. Verificar corriendo lsof -i :5000 de nuevo: si ya no imprime ninguna línea, el puerto quedó libre.
  4. Solo si el proceso sigue apareciendo después de esperar unos segundos, escalar a kill -9 PID.
  5. Relanzar npm run dev.

Por qué funciona: EADDRINUSE te dice que hay un conflicto, pero nunca te dice quién lo causa —lsof -i es la herramienta diseñada específicamente para traducir "un puerto" a "un PID concreto", que es el dato que necesitas para poder actuar.

4. Un compañero de equipo, apurado, corre kill -9 contra el proceso de una base de datos que en ese momento estaba escribiendo una transacción a disco. ¿Por qué esto es más arriesgado que haber usado kill sin flags, y qué pudo haber salido mal?

Ver solución

kill sin flags envía SIGTERM, una señal que el proceso puede capturar para cerrar limpiamente: terminar la transacción en curso, liberar sus bloqueos de archivo, cerrar sus conexiones de red de forma ordenada. kill -9 envía SIGKILL, que ni el proceso ni el kernel pueden posponer —el proceso se detiene de inmediato, exactamente en el punto en que estaba, sin ninguna oportunidad de terminar lo que tenía a medias—. Si la transacción se estaba escribiendo a disco en ese instante, el resultado posible es un archivo de datos corrupto o inconsistente, algo que un SIGTERM bien manejado por la base de datos habría evitado.

Por qué funciona: SIGKILL es intencionalmente imposible de interceptar —esa es justo su utilidad como último recurso ante un proceso que de verdad no responde—, pero esa misma característica es lo que lo vuelve peligroso contra cualquier proceso que en ese momento tenga trabajo a medio terminar.

Resumen y siguiente paso

Ya puedes leer la lista completa de procesos de tu sistema con ps aux, entender qué significa cada columna —especialmente PID, %CPU, %MEM y STAT— y encontrar un proceso por nombre con pgrep sin que su propio comando de búsqueda te confunda. Sabes que top te muestra ese mismo consumo en vivo, y que kill no mata un proceso: le envía una señal, y SIGTERM (el valor por defecto) le da la oportunidad de cerrar con cuidado que SIGKILL (-9) nunca da —razón por la que uno es el primer intento y el otro es el último recurso—. Sabes pausar un trabajo con Ctrl+Z, mandarlo a segundo plano con bg, traerlo de vuelta con fg, y lanzar algo directamente en segundo plano con &. Y sabes resolver, con evidencia y no con superstición, uno de los tres errores que le dan nombre a este módulo: encontrar con lsof -i o ss -tulpn exactamente qué proceso ocupa un puerto, y terminarlo con el mismo criterio de señales que ya conoces.

Antes de avanzar deberías poder:

  • correr ps aux e identificar, sin ayuda, el PID, el %CPU y el estado (STAT) de cualquier proceso de la lista;
  • explicar por qué kill sin flags siempre debería ser tu primer intento, y en qué situación concreta se justifica escalar a kill -9;
  • pausar un proceso en primer plano, mandarlo a segundo plano y devolverlo al primer plano sin perder su trabajo;
  • diagnosticar y liberar un puerto ocupado usando lsof -i :PUERTO (o ss -tulpn en Linux) para encontrar el PID responsable.

Hoy asumiste, en cada ejemplo, que el comando existía y arrancaba sin problema —el único obstáculo fue un puerto ocupado o un proceso que no respondía—. La siguiente lección resuelve el caso en el que ni siquiera llegas a ese punto: el sistema te dice command not found aunque jures que el programa está instalado. Ahí vas a conocer el PATH, la lista de carpetas donde tu shell busca cada comando que escribes, y por qué ese único concepto explica casi todos los command not found que vas a ver en tu carrera.

Recursos