Saltar al contenido
sudoquest@root
Linux

Procesos y servicios

Qué se ejecuta en un servidor y cómo gobernarlo: ps y top, kill, los servicios de systemd (start, stop, enable) y el diario con journalctl.

25 min de lectura

Un servidor nunca está quieto: mientras lo miras, nginx sirve la web, cron espera a su hora, sshd atiende a quien entra y, a veces, un script se queda colgado comiéndose la CPU. Cada programa en marcha es un proceso, y los que tienen que estar siempre funcionando son servicios, que vigila systemd.

En este tema aprendes a ver qué se ejecuta y cuánto gasta, a parar lo que sobra (y solo eso), a arrancar y habilitar servicios y a leer el diario para saber qué pasó. Los ejemplos usan srv-tienda, el servidor de la tienda online, una mañana cualquiera.

Qué se está ejecutando: ps

Cada proceso tiene un número, el PID, y un dueño. ps, sin más, enseña los de tu terminal: tu bash y el propio ps:

tecnico@srv-tienda:~$ ps
    PID TTY          TIME CMD
 2600 pts/2    00:00:00 bash
 2601 pts/2    00:00:00 ps

Para verlos todos, de todos los usuarios, ps aux (la forma BSD, sin guion) o ps -ef (la de siempre de Unix). El primero es el 1, /sbin/init, que en Ubuntu es systemd: el padre de todo lo demás.

tecnico@srv-tienda:~$ ps aux | head -3
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.3 166972 11984 ?        Ss   Oct10   0:12 /sbin/init
root          88  0.0  0.3  35388 12688 ?        Ss   Oct10   0:03 /lib/systemd/systemd-journald

Las columnas que más se miran: el usuario y el PID; %CPU y %MEM; TTY, la terminal (? si no tiene: los servicios); STAT, el estado (S durmiendo, R corriendo, T parado); START, cuándo empezó, y TIME, cuánta CPU lleva gastada en total. Para buscar uno, grep o, mejor, pgrep -a, que da el PID y la orden entera:

tecnico@srv-tienda:~$ pgrep -a nginx
401 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
402 nginx: worker process
403 nginx: worker process

nginx son tres procesos: el maestro (de root, que lee la configuración) y dos trabajadores (de www-data, que atienden las peticiones). ps -ef enseña además el PPID, el padre de cada uno.

Ejercicio

Lo que se está ejecutando: ps

Te conectas a srv-tienda para echar un vistazo. Antes de tocar nada, mira qué se está ejecutando.

Preparando la máquina…

Cuánto trabaja la máquina: top, uptime y free

top es una foto de la máquina: arriba, cuánto lleva encendida, la carga y la memoria; abajo, los procesos, primero los que más CPU gastan. (En un servidor de verdad top se va actualizando hasta que pulsas q; aquí es una foto, como top -b -n 1.)

tecnico@srv-tienda:~$ top | head -12
top - 09:20:06 up 3 days,  5:00,  1 user,  load average: 1.01, 0.99, 0.90
Tasks:  15 total,   2 running,  13 sleeping,   0 stopped,   0 zombie
%Cpu(s): 49.5 us,  0.8 sy,  0.0 ni, 49.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3921.0 total,   2462.3 free,    280.9 used,   1177.7 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   3640.0 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 2417 marta     20   0   31248  24876  16418 R  99.0   0.6 118:53.94 python3
  402 www-data  20   0   55852   5536   3653 S   0.0   0.1   0:05.54 nginx
  403 www-data  20   0   55852   5536   3653 S   0.0   0.1   0:05.54 nginx
  401 root      20   0   55284   1648   1087 S   0.0   0.0   0:02.77 nginx
    1 root      20   0  166972  11984   7909 S   0.0   0.3   0:12.40 systemd

Aquí salta a la vista: un python3 de marta al 99 % de CPU, que lleva casi dos horas de CPU (TIME+). La carga (load average) son tres medias, de 1, 5 y 15 minutos, de cuántos procesos quieren CPU a la vez: en una máquina de 2 núcleos, 1.00 es medio llena y 2.00, llena. uptime da esa misma primera línea, y free -h la memoria en unidades que se leen (-h):

tecnico@srv-tienda:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       281Mi       2.4Gi        21Mi       1.2Gi       3.6Gi
Swap:          2.0Gi          0B       2.0Gi

La columna que importa es available: lo que queda de verdad (Linux usa la memoria libre como caché, buff/cache, y la suelta cuando hace falta). Para ordenar ps por CPU: ps aux --sort=-%cpu (el - es de más a menos).

Ejercicio

Cuánto trabaja la máquina: top, uptime y free

Dicen que la tienda va lenta esta mañana. Mira cuánto trabaja srv-tienda y quién se lleva la CPU.

Preparando la máquina…

Parar un proceso: kill y las señales

Para parar un proceso se le manda una señal con kill y su PID. La de siempre es SIGTERM (15): “termina, por favor”, y el programa cierra lo suyo antes de irse. Solo puedes mandarlas a tus procesos; a los de otro, con sudo:

tecnico@srv-tienda:~$ kill 2417
bash: kill: (2417) - Operation not permitted
tecnico@srv-tienda:~$ sudo kill 2417
tecnico@srv-tienda:~$ pgrep -a python3
2417 python3 informe.py --trimestre

Sigue ahí: un programa colgado puede no hacer caso de SIGTERM. Entonces, SIGKILL (9), que no se puede ignorar: el núcleo lo quita de en medio, sin dejarle cerrar nada.

tecnico@srv-tienda:~$ sudo kill -9 2417

kill -9, kill -KILL y kill -s KILL son lo mismo; kill -l lista todas las señales. pkill y killall buscan por nombre en lugar de por PID (pkill -f mira la orden entera).

Ejercicio

Parar un proceso desbocado: kill

Un script de marta, informe.py, lleva dos horas con la CPU al 100 % y la tienda va a pedales. Marta dice que lo pares, que ya lo lanzará esta noche.

Preparando la máquina…

Los servicios: systemctl

Lo que tiene que estar siempre en marcha (nginx, sshd, cron, una API) no se lanza a mano: es un servicio, y lo arranca y vigila systemd. Se gobiernan con systemctl, y lo primero es siempre mirar su estado:

tecnico@srv-tienda:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2026-10-10 04:20:00 UTC; 3 days ago
     Docs: man:nginx(8)
 Main PID: 401 (nginx)
    Tasks: 3 (limit: 4556)
   Memory: 12.4M
      CPU: 13.861s
   CGroup: /system.slice/nginx.service
           ├─401 nginx: master process /usr/sbin/nginx -g daemon on; master_p…
           ├─402 nginx: worker process
           └─403 nginx: worker process

Oct 10 04:20:00 srv-tienda systemd[1]: Starting A high performance web server and a reverse proxy server...
Oct 10 04:20:00 srv-tienda systemd[1]: Started A high performance web server and a reverse proxy server.

Se lee de arriba abajo: el punto (● verde en marcha, ○ parado, × rojo fallido); Loaded, de qué archivo sale y si está habilitado; Active, su estado y desde cuándo; Main PID, su proceso principal; CGroup, todos sus procesos, y al final, sus últimas líneas del diario.

Para cambiarlo, con sudo: start, stop, restart (parar y arrancar) y reload (que relea la configuración sin parar, si el programa sabe). systemctl is-active nginx responde solo active o inactive (útil en scripts).

Ejercicio

Los servicios: systemctl

nginx no se lanza a mano: es un servicio, y lo vigila systemd. Toca pararlo un momento para una revisión.

Preparando la máquina…

Que arranque sola: enable

Arrancar un servicio y habilitarlo son cosas distintas. start lo pone en marcha ahora; enable hace que arranque con la máquina (crea un enlace en multi-user.target.wants). Un servicio arrancado a mano y sin habilitar funciona… hasta el próximo reinicio:

tecnico@srv-tienda:~$ systemctl status tienda
○ tienda.service - Tienda online (API)
   Loaded: loaded (/etc/systemd/system/tienda.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
tecnico@srv-tienda:~$ sudo systemctl enable --now tienda
Created symlink /etc/systemd/system/multi-user.target.wants/tienda.service → /etc/systemd/system/tienda.service.

--now hace las dos cosas a la vez (y disable --now las deshace). systemctl is-enabled tienda dice enabled, disabled o static (una unidad sin sección [Install], que no se habilita: la lanza otra cosa, como cron).

Ejercicio

Que arranque sola: enable

La API de la tienda (tienda.service) está parada desde el último reinicio. Que vuelva, y que la próxima vez arranque sola.

Preparando la máquina…

Las unidades y daemon-reload

Cada servicio se describe en un archivo de unidad: los de los paquetes en /lib/systemd/system, los tuyos en /etc/systemd/system. systemctl cat lo enseña:

tecnico@srv-tienda:~$ systemctl cat informes
# /etc/systemd/system/informes.service
[Unit]
Description=Informe diario de ventas

[Service]
Type=oneshot
ExecStart=/usr/local/bin/informe-diario.sh

ExecStart es lo que se ejecuta; User, con qué usuario; Type=oneshot, que hace su trabajo y termina (una copia, un informe), y [Install], a qué se engancha al habilitarlo.

Qué ha pasado: el diario

Los servicios apuntan lo que les pasa en el diario de systemd, y journalctl lo lee. Lo primero, qué ha fallado:

tecnico@srv-tienda:~$ systemctl --failed
  UNIT             LOAD   ACTIVE SUB    DESCRIPTION
● informes.service loaded failed failed Informe diario de ventas

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.
1 loaded units listed.

Y luego, su parte del diario, con -u (de unit):

tecnico@srv-tienda:~$ journalctl -u informes
Oct 13 06:00:00 srv-tienda systemd[1]: Starting Informe diario de ventas...
Oct 13 06:00:00 srv-tienda informe-diario.[404]: Generando el informe diario de ventas
Oct 13 06:00:00 srv-tienda informe-diario.[404]: ls: cannot access '/srv/informes/salida': No such file or directory
Oct 13 06:00:00 srv-tienda systemd[1]: informes.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
Oct 13 06:00:00 srv-tienda systemd[1]: informes.service: Failed with result 'exit-code'.
Oct 13 06:00:00 srv-tienda systemd[1]: Failed to start Informe diario de ventas.

Ahí está: a las 6 no existía la carpeta de salida. Lo que escribe el programa sale con su nombre (informe-diario.[404]), y lo de systemd, con el suyo. Lo más útil de journalctl: -n 20 las últimas 20 líneas; -p err solo errores (y lo más grave); --since "2026-10-13 05:00" desde una hora; -x, con una explicación de cada mensaje de systemd, y -e, saltar al final (journalctl -xeu nginx, lo que te sugiere systemctl cuando algo falla).

El núcleo también apunta lo suyo: si la máquina se queda sin memoria, elige un proceso y lo mata (Out of memory: Killed process 412 (python3)…, que sale con journalctl -p err). Si era el principal de un servicio, este se queda en failed (Result: signal), con status=9/KILL, y no vuelve solo: hay que arrancarlo otra vez con sudo systemctl start.

Para leer el diario entero hace falta estar en el grupo adm (o systemd-journal), o usar sudo: sin ello, solo ves lo tuyo.

Ejercicio

Qué ha pasado: journalctl

Esta mañana no ha llegado el informe diario de ventas. Algo falló a las 6: averigua qué.

Preparando la máquina…