Nivel inicial14 min de lectura · Publicado el

Matar un proceso en Linux: kill, pkill y killall

Matar un proceso en Linux: el PID 7927 como un número de turno; pgrep lo busca, kill le pide que salga y kill -9 lo cierra a la fuerza. Primero pide; luego, kill -9rubentejera.com 7927pgrep -af ideabusca su númerokill 7927le pide que salgakill -9 7927lo saca a la fuerza
El PID es el número de turno del proceso. pgrep -af idea lo busca (7927); kill 7927 le pide que termine y, si no hace caso, kill -9 7927 hace que el sistema lo cierre sin preguntar.

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 servicio o restart. Si lo matas con kill, 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ía SIGTERM y, 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 10 la 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

  1. Copia tarea.sh, lánzalo, espera un segundo a que prepare el trap (sleep 1) y ciérralo con kill -HUP en vez de kill. ¿Se ejecuta el trap? ¿Qué código de salida da wait? (Pista: 128 + el número de la señal.) Añade HUP al final de la línea del trap (trap '…' TERM HUP) y repítelo.
  2. Arranca python3 -m http.server 8080 en una terminal y, desde otra, encuentra su PID con ss y con lsof. Ciérralo con kill y comprueba que el puerto queda libre.
  3. Ejecuta timeout 3 sleep 10; echo $? y luego timeout 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.