Guía
Mata todos los procesos Node colgados en tu Mac (sin cargarte el editor)
20 de julio de 20265 min de lectura
Llevas todo el día saltando entre proyectos. Un next dev por aquí, un vite por allá, un watcher de nodemon, quizás un servidor de Expo. Terminales que crashearon, pestañas que cerraste, el portátil que se durmió y despertó. Ahora los ventiladores están a tope, npm run dev dice que el puerto está ocupado, y el Monitor de Actividad muestra una docena de entradas node que no reconoces.
Los quieres fuera. La gracia está en deshacerte de los que están colgados sin matar los procesos Node que sí necesitas.
Por qué terminas con una pila de procesos Node huérfanos
Cada servidor de desarrollo es un proceso node de larga vida que ocupa un puerto y un buen trozo de RAM. Cerrar la pestaña de la terminal no lo mata de forma fiable: npm run dev lanza un proceso node hijo, y si el shell padre desaparece de golpe el hijo pasa a depender de launchd y sigue corriendo. Un crash duro, un Ctrl+Z (que suspende en vez de matar), o un ciclo de dormir/despertar pueden dejar un servidor pegado a su puerto sin nada que apunte claramente a él. Haz eso unas cuantas veces en unos cuantos proyectos y se van acumulando.
Paso 1: mira con qué estás lidiando realmente
La vista bruta es todos los procesos node:
ps aux | grep -i node
Pero es ruidosa. También lista los language servers de TypeScript/ESLint de tu editor, cualquier servidor MCP, y herramientas en segundo plano que resultan estar en Node. La lista que de verdad te importa es la de los que ocupan un puerto:
lsof -iTCP -sTCP:LISTEN -P -n | grep -i node
Esto muestra solo los procesos Node en estado LISTEN, es decir, servidores de desarrollo. Las columnas que importan son la segunda (PID) y la última (la dirección, para distinguir :3000 de :5173).
Paso 2: conoce el martillo bruto, y por qué es peligroso
Verás esto recomendado en todas partes:
killall node
Mata todos los procesos llamados node, de un golpe. Ese es el problema. También se lleva los language servers de tu editor (hola, subrayados rojos por todos lados), cualquier servidor MCP corriendo, un worker en segundo plano que olvidaste, y una app que quizás estés usando. pkill -f node es aún más amplio, hace match con toda la línea de comando, así que atrapa cosas que killall se salta y cosas que no querías tocar.
Usa killall node solo cuando de verdad quieras todos los procesos Node muertos y no te importe reiniciar tu editor.
Paso 3: mata los servidores colgados, no todo
La mayoría de las veces quieres ser quirúrgico. Mata un servidor por su puerto:
lsof -ti :5173 | xargs kill
-t hace que lsof imprima solo el PID, y xargs se lo pasa a kill. Prefiere kill a secas (SIGTERM) primero, para que el proceso cierre limpio; escala a kill -9 (SIGKILL) solo si se niega a morir. (La historia completa de SIGTERM vs SIGKILL está en ¿Puerto 3000 ocupado en tu Mac?.)
Si quieres limpiar todos los servidores de desarrollo pero perdonar los language servers y demás herramientas, mata solo los procesos Node que estén escuchando de verdad:
lsof -iTCP -sTCP:LISTEN -P -n | grep -i node | awk '{print $2}' | xargs kill
Ese one-liner es la versión segura de killall node: un proceso Node que no está escuchando (como el servidor de TypeScript de tu editor) queda intacto, y solo los servidores que ocupan un puerto reciben la señal.
Por qué cerrar la terminal no lo mató
Porque lo que cerraste normalmente no es el servidor. npm run dev (o yarn/pnpm) es un envoltorio que lanza el proceso node real como hijo. Según tu shell y su configuración, cerrar la pestaña puede dejar a ese hijo huérfano en vez de terminarlo. Herramientas como nodemon añaden otra vuelta de tuerca: están diseñadas para relanzarse al cambiar archivos, así que un watcher mal matado puede traer a su hijo de vuelta al instante. Matar por puerto se salta todo esto: apuntas a lo que sea que ocupe el socket, sin importar cómo se arrancó.
FAQ rápido
¿Cómo mato todos los procesos Node menos uno?
Lista los que escuchan con lsof -iTCP -sTCP:LISTEN -P -n | grep -i node, anota el PID del que quieres conservar, y mata el resto por PID o por puerto. No hay una opción limpia de “todos menos uno”, así que es un trabajo de ver-y-elegir, que es justo por lo que una lista visual le gana a un killall a ciegas.
¿killall node dice “No matching processes”?
El proceso no se llama literalmente node. Un puerto publicado por Docker aparece como com.docker.backend (ver Docker: bind: address already in use), y algunos runtimes reportan otro nombre de binario. Encuéntralo por puerto con lsof -i :PUERTO.
¿Funciona con Bun o Deno?
Sí. Cambia el nombre en el grep (bun, deno) para la vista de procesos, o ignora el nombre por completo y mata por puerto: los comandos basados en puerto no les importa qué runtime hay detrás del socket.
¿Esto matará el language server de mi editor?
killall node y pkill -f node sí. Los comandos por puerto y de solo-escuchando de arriba no, porque los language servers no ocupan un puerto TCP en escucha como sí lo hace un servidor de desarrollo.
Ve esto en vez de escribirlo
Bosun vive en tu barra de menú y muestra cada puerto abierto en tu Mac, en vivo, mapeado al proceso detrás. Un clic para matarlo, SIGTERM primero. Útil la primera vez que pasa esto. Realmente útil la quinta vez que pasa en una misma tarde.
