Matar un proceso en Linux: kill, pkill y killall
Un programa se ha quedado colgado y no hay forma de cerrar su ventana. O un servidor de desarrollo sigue corriendo en segundo plano. En Linux lo cierras desde la terminal en dos pasos: averiguas su número y le mandas la orden de parar.
Cada proceso tiene un PID, un número único, como el número de un ticket en la cola de la carnicería. Para echar a alguien de la cola necesitas saber qué número tiene.
1. Averigua el PID
La forma clásica es listar todos los procesos y filtrar por el nombre del programa:
ps -ef | grep idea
Devuelve algo así. El PID es la segunda columna:
ana 7927 1 4 20:36 ? 00:00:00 ruby /home/ana/IdeaProjects/test ruby/.idea/iterator.rb
ana 7932 7930 0 20:36 ? 00:00:00 grep idea
Fíjate en la última línea: es el propio grep buscándose a sí mismo. Ignórala.
Más cómodo es pgrep, que hace las dos cosas a la vez y no se encuentra a sí mismo. Aquí «idea» no está en el nombre del programa sino en su ruta, así que añade -f para buscar en la orden completa:
pgrep -af idea
7927 ruby /home/ana/IdeaProjects/test ruby/.idea/iterator.rb
| Opción | Qué hace |
|---|---|
pgrep nombre |
Muestra solo los PID de los procesos con ese nombre |
pgrep -a nombre |
Añade la orden completa, para saber cuál es cuál |
pgrep -f texto |
Busca el texto en la orden completa, no solo en el nombre |
2. Cierra el proceso
kill 7927
kill no «mata» directamente: envía una señal. Por defecto envía SIGTERM (la 15), que es pedirle al programa que termine. El programa puede guardar lo que tenga pendiente y salir limpio.
Si no hace caso, fuérzalo:
kill -9 7927
-9 es SIGKILL: el sistema cierra el proceso sin preguntarle. Funciona siempre, pero el programa no puede guardar nada ni limpiar sus ficheros temporales.
Primero pide; solo si no hace caso, fuerza.
Cerrar procesos por nombre
Si no quieres buscar el PID, pkill y killall cierran por nombre:
pkill idea # cierra los procesos cuyo nombre contiene "idea"
pkill -f "rails s" # busca en la orden completa
killall firefox # cierra los procesos que se llaman exactamente "firefox"
Ten cuidado con pkill: busca coincidencias parciales, así que pkill java cierra todos los procesos con «java» en el nombre. Comprueba antes con pgrep -a qué va a cerrar; usa la misma búsqueda.
killall viene en el paquete psmisc. Si no lo tienes, pkill (del paquete procps) está en casi cualquier distribución.
Las señales más usadas
| Señal | Número | Qué pide | Ejemplo |
|---|---|---|---|
SIGTERM |
15 | Que termine de forma ordenada (la de por defecto) | kill PID |
SIGKILL |
9 | Que el sistema lo cierre ya, sin preguntar | kill -9 PID |
SIGINT |
2 | Lo mismo que pulsar Ctrl + C | kill -2 PID |
SIGHUP |
1 | Muchos servicios lo usan para recargar su configuración | kill -1 PID |
La lista completa sale con kill -l. Estas son sus primeras líneas:
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
Puedes escribir la señal por su número o por su nombre: kill -15 PID, kill -TERM PID y kill -s TERM PID hacen lo mismo.
Compruébalo: kill frente a kill -9
La diferencia entre pedir y forzar se ve con un script que se prepara para recibir SIGTERM. La orden trap de Bash dice qué hacer cuando llega una señal; aquí, avisar y salir limpio:
#!/bin/bash
trap 'echo "SIGTERM recibida: guardo el trabajo y salgo"; exit 0' TERM
echo "tarea en marcha con PID $$"
while true; do sleep 1; done
Guárdalo como tarea.sh, dale permisos con chmod +x tarea.sh y lánzalo en segundo plano. $! guarda el PID del último proceso lanzado así, y wait espera a que termine y devuelve su código de salida. El sleep 1 espera un segundo a que el script prepare el trap: si la señal llega antes, el script muere sin ejecutarlo y sale con 143 (128 + 15):
./tarea.sh &
sleep 1
kill $!
wait $!; echo "código de salida: $?"
tarea en marcha con PID 3241
SIGTERM recibida: guardo el trabajo y salgo
código de salida: 0
El script ha tenido su oportunidad de guardar y ha salido con 0, «todo bien». Ahora, con -9:
./tarea.sh &
sleep 1
kill -9 $!
wait $!; echo "código de salida: $?"
En una terminal se ve así ([1] 3255 es el número de trabajo y el PID que Bash muestra al lanzar algo en segundo plano):
[1] 3255
tarea en marcha con PID 3255
[1]+ Killed ./tarea.sh
código de salida: 137
El trap no se ha ejecutado: la página de manual signal(7) dice que SIGKILL y SIGSTOP no se pueden capturar, bloquear ni ignorar. Bash avisa con la línea Killed, y el código es 137, que es 128 + 9: «terminado por la señal 9». Es la misma idea que el exit code 137 que verás cuando el sistema o Docker cierran un proceso a la fuerza.
Liberar un puerto ocupado
Si arrancas un servidor y el puerto ya está en uso, el error suele ser parecido a este (aquí, con el servidor web de Python en el 8080):
OSError: [Errno 98] Address already in use
Algún proceso sigue escuchando en ese puerto, muchas veces un servidor de desarrollo que quedó abierto en otra terminal. Para encontrarlo tienes tres herramientas. Todas las salidas de esta sección son de la misma prueba: un servidor (PID 3278) escuchando en el 8080 y un cliente (PID 3280) conectado a él.
ss, de iproute2, viene en casi todas las distribuciones actuales. -l muestra solo los que escuchan, -t solo TCP, -n los puertos como números y -p el proceso:
sudo ss -ltnp 'sport = :8080'
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 5 0.0.0.0:8080 0.0.0.0:* users:(("python3",pid=3278,fd=3))
El PID es el número de pid=3278. Con -l, ss solo enseña el que escucha, no al cliente.
lsof («lista los ficheros abiertos») da una tabla más fácil de leer. -n y -P evitan que traduzca direcciones y puertos a nombres (sin -P, el 8080 sale como http-alt):
sudo lsof -nP -i :8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 3278 root 3u IPv4 2487289 0t0 TCP *:8080 (LISTEN)
python3 3278 root 4u IPv4 2487292 0t0 TCP 127.0.0.1:8080->127.0.0.1:51184 (ESTABLISHED)
python3 3280 root 3u IPv4 2491068 0t0 TCP 127.0.0.1:51184->127.0.0.1:8080 (ESTABLISHED)
Fíjate en que -i :8080 encuentra todo lo que usa ese puerto, también el cliente (la última línea). Con -t solo devuelve los PID, y ahí está la trampa:
sudo lsof -t -i :8080
3278
3280
Para quedarte solo con el proceso que escucha, añade -sTCP:LISTEN:
sudo lsof -t -i TCP:8080 -sTCP:LISTEN
3278
Y así puedes buscar y cerrar en una sola línea sin llevarte por delante al cliente:
sudo kill $(sudo lsof -t -i TCP:8080 -sTCP:LISTEN)
fuser, del paquete psmisc, busca y cierra a la vez con -k. Con -v te enseña antes qué ha encontrado:
sudo fuser -v 8080/tcp
USER PID ACCESS COMMAND
8080/tcp: root 3278 F.... python3
Ojo: según su página de manual, fuser -k envía SIGKILL salvo que indiques otra señal. Si quieres pedirlo por las buenas, usa sudo fuser -k -TERM 8080/tcp.
Lo mismo en Windows lo tienes en Matar un proceso en un puerto en Windows.
Errores frecuentes
1. «No such process»
El PID ya no existe: el proceso terminó solo o lo cerraste antes. El mensaje cambia un poco según uses la orden kill de Bash o el programa /bin/kill de procps:
bash: kill: (99999) - No such process
/bin/kill: (99999): No such process
Los PID se reutilizan, así que no guardes uno en un script durante horas y lo mates después a ciegas: comprueba antes con pgrep -a que sigue siendo el proceso que crees.
2. «Operation not permitted»
Intentas cerrar un proceso de otro usuario. Lanzado por la usuaria de prueba ana, en una sesión abierta con su - ana, contra un proceso de root (el guion delante de bash indica una sesión de inicio; en una terminal normal sale bash:):
-bash: kill: (3266) - Operation not permitted
Con sudo funciona, pero piénsalo dos veces si el proceso es del sistema. Lo mismo pasa al buscar: sin sudo, lsof -i :8080 no devuelve nada si el proceso es de otro usuario (y sale con código 1), y ss -ltnp muestra el puerto pero deja vacía la columna del proceso.
3. pkill cierra más de lo que querías
Con dos programas llamados api y api-pruebas en marcha, la búsqueda por nombre encuentra los dos:
pgrep -a api
3267 api 300
3268 api-pruebas 300
pkill api habría cerrado los dos. Con -x, el nombre tiene que coincidir entero:
pgrep -ax api
3267 api 300
Haz siempre primero pgrep con las mismas opciones que vas a usar en pkill: busca exactamente lo mismo.
4. Un proceso zombi que no muere
Un proceso zombi (Z en la columna STAT) ya ha terminado; solo queda su entrada en la tabla porque su padre no ha recogido su código de salida. La página de manual de ps lo define así: «terminated but not reaped by its parent» (terminado, pero sin recoger por su padre).
ps -o pid,ppid,stat,cmd --ppid 3278
PID PPID STAT CMD
3280 3278 Z [python3] <defunct>
kill -9 3280 no cambia nada: no se puede matar algo que ya está muerto. Un zombi no consume CPU ni memoria, solo una entrada en la tabla. Si se acumulan, el problema es el padre (el PID de la columna PPID): al cerrarlo, el sistema recoge sus zombis. En la prueba, tras kill 3278, el zombi desapareció.
5. Usar kill -9 a la primera
Funciona, pero el programa no puede cerrar ficheros, borrar sus temporales ni terminar de escribir, como se vio en la prueba de arriba. Con una base de datos o un programa que está guardando, puede dejar datos a medias. Primero kill, espera unos segundos y, solo si sigue vivo, kill -9.
Cuándo no usar kill
- Con un servicio gestionado por systemd (nginx, PostgreSQL, Docker…). Usa
sudo systemctl stop servicioorestart. Si lo matas conkill, systemd puede volver a arrancarlo, según cómo esté configurado, y además ya tiene registrado cómo pararlo de forma ordenada. - Con un contenedor. Usa
docker stop, que primero envíaSIGTERMy, si el contenedor no termina en el tiempo de espera,SIGKILL. - Para poner un límite de tiempo a una orden. En vez de lanzarla y matarla tú, usa
timeout:timeout 2 sleep 10la corta a los 2 segundos y sale con el código 124, según su página de manual, para que un script sepa que se agotó el tiempo. - Para «arreglar» algo que se cuelga siempre. Si tienes que matar el mismo programa cada día, el problema está en el programa, no en cómo lo cierras.
Ejercicio de cinco minutos
- Copia
tarea.sh, lánzalo, espera un segundo a que prepare eltrap(sleep 1) y ciérralo conkill -HUPen vez dekill. ¿Se ejecuta eltrap? ¿Qué código de salida dawait? (Pista: 128 + el número de la señal.) AñadeHUPal final de la línea deltrap(trap '…' TERM HUP) y repítelo. - Arranca
python3 -m http.server 8080en una terminal y, desde otra, encuentra su PID conssy conlsof. Ciérralo conkilly comprueba que el puerto queda libre. - Ejecuta
timeout 3 sleep 10; echo $?y luegotimeout 30 sleep 1; echo $?. ¿Qué código da cada uno?
Tu chuleta
| Quiero… | Orden |
|---|---|
| Buscar un proceso | pgrep -af nombre |
| Cerrarlo por PID | kill PID |
| Forzar el cierre | kill -9 PID |
| Cerrar todos por nombre | pkill nombre |
| Ver todas las señales | kill -l |
| Ver qué proceso usa un puerto | sudo ss -ltnp 'sport = :8080' o sudo lsof -nP -i :8080 |
| Cerrar lo que escucha en un puerto | sudo kill $(sudo lsof -t -i TCP:8080 -sTCP:LISTEN) |
| Cerrar solo el nombre exacto | pkill -x nombre |
| Poner un límite de tiempo | timeout 10 orden |
Fuentes
Comprobado en noviembre de 2026 en las páginas man oficiales publicadas en man7.org: kill(1), pgrep(1) y pkill(1), ps(1) (procps-ng; estado Z, «defunct (“zombie”) process, terminated but not reaped by its parent»), killall(1) y fuser(1) (psmisc; -k envía SIGKILL salvo que se indique otra señal), signal(7) (SIGKILL y SIGSTOP no se pueden capturar, bloquear ni ignorar), ss(8) (iproute2; -l, -t, -n, -p), timeout(1) (coreutils; código 124) y lsof(8) en Debian. Para contenedores, la referencia de docker container stop: primero SIGTERM y, tras el tiempo de espera, SIGKILL.
El 11 de noviembre de 2026 se ejecutaron en un contenedor debian:stable (Debian 13.7, Bash 5.2, procps-ng 4.0.4, psmisc 23.7, lsof 4.99.4, iproute2 6.15.0, Python 3.13.5), lanzado con docker run --rm --init: el script con trap frente a kill, kill -9 y kill -HUP con sleep 1 antes de la señal (códigos 0, 137 y 129; con HUP en el trap, 0) y sin sleep 1 (143 en 3 de 3 ejecuciones), el bloque de kill -9 y los mensajes de error en una Bash interactiva dentro de una pseudoterminal, los dos mensajes de «No such process», «Operation not permitted» con la usuaria de prueba ana, pgrep y pkill con y sin -x, el proceso zombi, el puerto 8080 ocupado con python3 -m http.server y un cliente conectado, y su búsqueda con ss, lsof (con y sin -sTCP:LISTEN) y fuser, también sin privilegios, y timeout. Los PID cambian en cada ejecución.
Todas las órdenes se han ejecutado en un contenedor debian:stable (Debian 13.7) con procps-ng 4.0.4 y psmisc 23.7, sobre procesos sleep de prueba. Se comprobó también que un proceso que ignora SIGTERM sigue vivo tras kill y se cierra con kill -9. Las salidas de ps -ef | grep idea y pgrep -af idea se obtuvieron el 8 de noviembre de 2026 en la imagen ruby:latest (Ruby 4.0.9, Debian 13.7, procps-ng 4.0.4), con el script de Ruby en bucle y las dos búsquedas lanzados por una usuaria de prueba, ana, tras lanzar procesos hasta llegar al PID 7927, para que cuadre con los ejemplos de kill.