- Linux utiliza prioridades (PR) y valores de niceness (NI) para decidir qué procesos obtienen más tiempo de CPU.
- nice fija la prioridad al iniciar un comando, mientras que renice la modifica en procesos que ya están en ejecución.
- ionice controla la prioridad de acceso a disco y complementa a nice/renice cuando el cuello de botella es la E/S.
- Solo root puede asignar prioridades altas (niceness negativo o clases de tiempo real), mientras que usuarios normales solo pueden bajar la prioridad.
Cuando un servidor Linux se satura de carga, casi siempre la causa está en unos pocos procesos que acaparan CPU o disco. Ahí es donde entran en juego nice, renice e ionice, tres herramientas clave para decidir quién manda de verdad sobre los recursos del sistema.
Dominar estas utilidades te permite hacer cosas tan prácticas como lanzar tareas pesadas sin que ralenticen todo, bajar la prioridad de procesos poco críticos o dar preferencia absoluta a un servicio vital. Vamos a ver, con calma y con muchos ejemplos, cómo aprovecharlas en el día a día de administración de sistemas Linux.
Conceptos básicos: procesos, PID y prioridades en Linux
En Linux absolutamente todo lo que se ejecuta es un proceso: desde el servidor web hasta tu shell. Cada proceso tiene un PID (Process ID), un identificador numérico único que el kernel utiliza para gestionarlo en la tabla de procesos. Esa tabla se consulta con comandos como ps, top o htop.
Los procesos no aparecen de la nada, sino que uno genera a otro mediante la famosa secuencia fork() + exec(). El proceso que crea al nuevo se denomina padre, y el recién nacido es el hijo. Esta relación padre-hijo forma un árbol jerárquico de procesos, que puedes visualizar con herramientas como ps axjf o pstree.
El kernel de Linux es multitarea, pero eso no significa que un único núcleo ejecute varios procesos al mismo tiempo. Lo que hace es alternar procesos a gran velocidad, cargando el contexto de uno, ejecutándolo un instante, guardándolo y pasando al siguiente. Para decidir a quién le toca, se basa en un sistema de prioridades.
Cada proceso tiene una prioridad efectiva (PR) y un valor asociado llamado niceness (NI). Puedes ver ambos campos claramente en la salida de top o htop, en las columnas PR y NI. Mientras menor es el valor de PR, más preferencia tiene el proceso para acceder a la CPU.
El valor de niceness NI es una «pista» para el planificador, que indica cuán «amable» es un proceso con los demás: cuanto más alto es NI, más dispuesto está ese proceso a ceder CPU a los otros. En el rango de usuario, NI va de -20 (muy alta prioridad) a 19 (prioridad baja), siendo 0 la prioridad por defecto para nuevos procesos.
Rangos de prioridad en Linux: PR, NI y tiempo real
Bajo el capó, Linux maneja 140 niveles de prioridad, numerados desde 0 hasta 139. Estas mejoras del kernel pueden afectar la planificación; ver novedades del kernel Linux 6.18. Estas niveles se dividen en dos grandes grupos: prioridades de tiempo real y prioridades normales de espacio de usuario.
Las prioridades de tiempo real ocupan el rango de 0 a 99. Están reservadas para procesos que no pueden permitirse retrasos apreciables (por ejemplo, tareas relacionadas con hardware crítico). En herramientas como top o htop estos procesos suelen aparecer con PR = rt o marcados como «RT».
Las prioridades normales de usuario van aproximadamente de 100 a 139, pero en la mayoría de utilidades verás un rango 0-39 para PR, derivado de NI. En este contexto se utiliza la relación:
PR = 20 + NI
Eso significa que si NI = 0, la prioridad efectiva será aproximadamente PR = 20, que es la prioridad media. Si NI = -20, PR será muy baja (0) y el proceso tendrá máxima prioridad relativa. Si NI = 19, PR estará cerca de 39, es decir, prioridad muy baja.
Hay que diferenciar bien NI de PR: NI es el valor «nice» que tú manipulas directamente con nice o renice, mientras que PR es la prioridad que finalmente aplica el kernel, calculada a partir de NI y otros factores internos como el comportamiento del proceso y la carga del sistema.
Ver procesos y sus prioridades con ps, top y htop
Antes de tocar prioridades a ciegas, conviene tener claro qué está corriendo en la máquina. Para eso Linux tiene varias herramientas de monitorización de procesos, cada una con su enfoque.
El comando ps muestra una «foto fija» del estado actual de los procesos. Con la combinación clásica:
Comando: ps aux
Obtendrás un listado completo con usuario, PID, uso de CPU y memoria, entre otros campos. Si quieres centrarte en prioridades y niceness, puedes usar algo como:
Filtro recomendado: ps -eo pid,ppid,ni,comm
En este caso, la columna ni te enseña el valor de niceness de cada proceso. El campo ppid refleja el PID del proceso padre, lo que te ayuda a entender la jerarquía de procesos que comentábamos antes.
Si necesitas monitorización en tiempo real, top es la navaja suiza estándar. Con:
Orden: top -o %CPU
Verás los procesos ordenados por uso de CPU, con columnas como PR (prioridad efectiva) y NI (niceness). Desde la propia interfaz de top puedes usar la tecla r para aplicar un renice interactivo, introduciendo primero el PID y luego el nuevo valor nice.
htop es una versión vitaminada de top, con una interfaz más amigable y colorida. Tras instalarlo (por ejemplo con sudo apt-get install htop), basta con ejecutar htop para ver el árbol de procesos, barras de CPU, RAM y columnas como PRI, NI y S (estado del proceso).
Una ventaja muy cómoda de htop es que permite cambiar la prioridad desde el teclado: seleccionas un proceso y usas F7 para subir la prioridad (disminuir NI) o F8 para bajarla (aumentar NI), siempre que tengas permisos suficientes (sobre todo si quieres ir a valores negativos).
Estados de los procesos y su relación con la planificación
En la salida de top o htop verás una columna S que indica el estado del proceso. Este estado también afecta a cómo el planificador decide a quién darle CPU en cada momento.
Los estados más habituales en Linux son los siguientes:
- R (Running): el proceso está ejecutándose en la CPU o listo para hacerlo.
- S (Interruptible sleep): el proceso está «dormido» esperando un evento (por ejemplo, que haya datos disponibles) pero se puede despertar con señales.
- D (Uninterruptible sleep): espera ininterrumpible, normalmente bloqueado en una operación de E/S con un dispositivo; no responde a señales hasta que termina esa operación.
- T (Stopped): proceso detenido, a menudo por una señal como
SIGSTOPoSIGTSTP. - Z (Zombie): el proceso terminó, pero su padre aún no ha recogido su estado; sigue apareciendo en la tabla de procesos.
Cambiar el niceness de un proceso no cambia su estado (S, R, D, etc.), pero sí influye en cuánto tiempo de CPU recibe cuando está listo para ejecutarse. Un proceso en estado D, por ejemplo, está esperando E/S; ahí ajustar nice puede servir de poco y es mejor pensar en ionice, como veremos más adelante.
Enviar señales a procesos: kill, pkill y killall
La gestión de prioridades normalmente se combina con el envío de señales a procesos problemáticos. En Linux las señales son mensajes especiales que indican a un proceso que debe hacer algo: terminar, reiniciarse, recargar configuración, etc.
El comando más común para enviar señales es kill, que por defecto manda la señal SIGTERM. Un uso típico sería:
Ejemplo: kill 1234
Esto pide al proceso con PID 1234 que termine de forma ordenada. Si el proceso ignora la señal o está bloqueado, puedes forzar su terminación con:
Forzar: kill -9 1234
La opción -9 envía SIGKILL, que el programa no puede interceptar; el kernel mata el proceso sin darle oportunidad de limpiar nada, así que hay que usarlo con cuidado.
Si prefieres trabajar por nombre de proceso, dispones de pkill y killall. Por ejemplo:
Por nombre: pkill firefox
Enviará la señal por defecto (SIGTERM) a todos los procesos cuyo nombre coincida con «firefox». Y algo como:
Todos: killall chrome
Terminará todos los procesos llamados «chrome» en el sistema. Esto es útil cuando tienes varias instancias del mismo programa y quieres cerrarlas todas de golpe.
nice: ejecutar comandos con una prioridad específica
El comando nice sirve para arrancar procesos con un valor de niceness concreto, en vez de utilizar el valor por defecto 0. Es la herramienta ideal cuando sabes de antemano que una tarea será pesada y quieres que no interfiera demasiado con el resto del sistema.
Sintaxis:
nice -n valor_nice comando
nice valor_nice comando
nice --adjustment=valor_nice comando
Si no indicas ningún valor, nice suele aplicar por defecto un NI = 10, es decir, baja un poco la prioridad del proceso respecto a la normal. Un ejemplo sencillo:
Uso típico: nice -n 10 ./script_largo.sh
Aquí el script se lanzará con NI = 10, lo que implica que tendrá menos prioridad que procesos con NI 0 cuando compitan por CPU. Es una buena práctica para tareas de mantenimiento o reportes que no son urgentes.
Para cargar un comando con prioridad positiva (es decir, menor prioridad) también puedes usar la forma abreviada:
Forma abreviada: nice 15 comando_pesado
En cambio, si necesitas aumentar la prioridad (es decir, usar un niceness negativo), sólo el usuario root está autorizado. Por ejemplo:
Con root: sudo nice -n -5 xclock &
Este comando lanza xclock con NI = -5, de forma que obtendrá más tiempo de CPU que otros procesos con NI >= 0. Para expresarlo con la forma larga, podrías hacer:
Forma larga: sudo nice --adjustment=-5 xclock &
Recuerda también que un proceso lanzado sin nice hereda la prioridad por defecto NI = 0, salvo que haya configuraciones especiales a través de PAM o límites del sistema que modifiquen ese comportamiento para ciertos usuarios o grupos.
renice: cambiar la prioridad de procesos ya en ejecución
Mientras que nice sólo actúa al iniciar un comando, renice permite modificar la prioridad de procesos que ya se están ejecutando. Es la herramienta de cabecera cuando detectas que un proceso vivo está consumiendo recursos de más o, al contrario, quieres favorecerlo.
La forma genérica de usar renice es:
Formato: renice prioridad pids] pgrps] usuarios]
Donde el primer argumento es el nuevo valor de niceness, y luego puedes indicar si quieres actuar sobre PIDs concretos (-p), grupos de procesos (-g) o todos los procesos de ciertos usuarios (-u). Por ejemplo, para cambiar la prioridad del proceso con PID 324 a NI = 10:
Caso: renice -n 10 -p 324
Este comando ajusta el valor de niceness del proceso 324, mostrándote normalmente la prioridad antigua y la nueva. Si quisieras modificar la prioridad de todos los procesos de un usuario, podrías hacer algo como:
Con privilegios: sudo renice -n -10 -u gacanepa
Aquí todos los procesos del usuario gacanepa pasarían a tener NI = -10, siempre que ejecutemos el comando como root. Usuarios normales solamente pueden aumentar el valor NI (es decir, bajar prioridad) en sus propios procesos, nunca hacerlo más negativo.
También puedes cambiar varios objetivos a la vez, combinando PIDs y usuarios. Por ejemplo:
Múltiples objetivos: renice 3 -p 12122 31313 -u Antonio Maria
En este caso se fija NI = 3 para los procesos con PIDs 12122 y 31313, y para todos los procesos de los usuarios Antonio y Maria. Resulta útil cuando quieres homogeneizar la prioridad de un conjunto de trabajos relacionados.
ionice: priorizar la entrada/salida de disco
Muchos cuellos de botella no están en la CPU, sino en el subsistema de almacenamiento. Un proceso puede tener poca carga de CPU, pero saturar el disco con operaciones de lectura/escritura intensivas. En estos casos, nice y renice no son suficientes; necesitas ionice.
Aunque en el contenido original se menciona sobre todo CPU, ionice complementa este control al permitirte establecer la prioridad de E/S (I/O) de un proceso en función de la clase de planificación del I/O scheduler.
Sintaxis I/O: ionice -c clase -n nivel comando
Las clases más habituales son:
- 1 (real-time): prioridad de E/S en tiempo real, casi nunca debería usarse salvo casos muy controlados.
- 2 (best-effort): clase por defecto, con niveles de 0 (más prioritario) a 7 (menos prioritario).
- 3 (idle): el proceso sólo realiza E/S cuando el disco está ocioso.
Por ejemplo, para ejecutar una copia de seguridad que no quieres que moleste al resto del sistema, podrías hacer:
Copia segura: ionice -c 3 tar czf backup.tgz /datos &
De este modo, el proceso de tar se programará únicamente cuando no haya otra actividad de disco, reduciendo mucho el impacto perceptible sobre otros servicios. Combinado con nice, puedes lograr que una tarea pesada sea casi «invisible» para los usuarios.
Comandos de apoyo para listar, buscar y controlar procesos
Ajustar prioridades es solo una parte de la administración de procesos. Antes de decidir qué tocar, necesitas localizar y entender qué está pasando en la máquina. Linux ofrece varias utilidades muy útiles para ello.
Además de ps, top y htop, ya mencionados, conviene familiarizarse con:
pgrep, que busca procesos por nombre y devuelve sus PIDs. Por ejemplo:pgrep apachemostrará todos los procesos del servidor Apache que estén activos.pstree, que presenta los procesos como un árbol jerárquico, facilitando ver quién es padre de quién.lsof, que lista los archivos abiertos por un proceso concreto:lsof -p PIDayuda a detectar qué puertos o ficheros está utilizando.fuser, ideal para saber qué proceso está usando un archivo o puerto concreto:fuser -v -n tcp 8080te dice quién ocupa el puerto 8080.
Para depuración avanzada dispones de herramientas como strace, que traza las llamadas al sistema de un proceso en tiempo real mediante, por ejemplo, strace -p PID. Muy útil cuando un proceso se queda «colgado» y quieres saber en qué syscall está atascado.
Ajustar procesos en segundo plano: bg, fg y nohup
La forma en que lanzas un proceso también influye en cómo lo gestionas después. Desde la shell, puedes enviarlo al segundo plano y seguir usando el terminal, o mantenerlo en primer plano según te interese.
Si arrancas un comando y pulsas Ctrl+Z, se suspende y vuelve al prompt. Con el comando bg puedes reanudarlo en segundo plano para que siga ejecutándose sin bloquear la terminal, mientras que con fg lo traes de vuelta al primer plano.
Cuando quieres que un proceso sobreviva al cierre de la sesión o del terminal, nohup es tu aliado. Por ejemplo:
Uso desligado: nohup script_largo.sh &
Ejecutará el script de forma desacoplada del terminal, redirigiendo la salida estándar a nohup.out (por defecto) y permitiendo que siga corriendo aunque cierres la conexión SSH.
Gestión de servicios del sistema y su relación con prioridades
Los servicios en segundo plano (daemons) como servidores web, BBDD o colas de tareas son procesos al fin y al cabo. Para gestionarlos en sistemas modernos con systemd, usarás casi siempre systemctl:
systemctl start apache2
Este comando arranca el servicio apache2, mientras que systemctl stop, restart o status controlan su ciclo de vida. En sistemas más antiguos basados en SysVinit, sigue existiendo el comando service:
service apache2 restart
Aunque normalmente no cambias el niceness directamente desde systemctl, sí puedes definir límites y parámetros de CPU y E/S en los ficheros de unidad de systemd (por ejemplo usando Nice= o control de cgroups), logrando un efecto similar al uso de nice/renice pero de manera persistente y declarativa.
Monitoreo general del sistema: CPU, memoria y E/S
Para decidir qué priorizar con nice, renice e ionice, no basta con mirar una lista de procesos; necesitas contexto global sobre cómo está la máquina. Hay varias utilidades muy útiles para ello.
El comando uptime te resume de un vistazo el tiempo que lleva encendido el sistema, el número de usuarios conectados y la carga media en los últimos 1, 5 y 15 minutos:
Resumen: uptime
La carga media es una pista clara de si tienes demasiados procesos compitiendo por CPU. Valores consistentemente altos, comparados con el número de núcleos, indican que puede ser buena idea bajar prioridad a tareas no críticas.
Para ver estadísticas detalladas de rendimiento dispones de vmstat y iostat. Por ejemplo:
Muestreo: vmstat 5
Muestra cada 5 segundos el uso de CPU, memoria, procesos en ejecución y en espera, entre otros. Y con:
Estadísticas I/O: iostat
Obtendrás información sobre E/S de disco, tiempos de espera y throughput, crucial para decidir cuándo tiene sentido tirar de ionice además de nice/renice.
Configurar niceness por defecto para usuarios y límites del sistema
Si quieres ir un paso más allá y establecer prioridades por defecto para ciertos usuarios o grupos, puedes hacerlo mediante PAM y el archivo /etc/security/limits.conf.
La sintaxis básica en limits.conf es:
Plantilla: <dominio> <tipo> <elemento> <valor>
Donde el dominio puede ser un usuario, un grupo o un comodín, el tipo especifica si el límite es «hard» o «soft» y el elemento puede ser, entre otros, el valor nice por defecto. De esta manera puedes hacer que ciertos usuarios arranquen siempre sus procesos con un NI concreto sin tener que usar nice explícitamente.
En lugar de modificar directamente limits.conf, también es posible crear ficheros adicionales en /etc/security/limits.d/, que se cargan en orden alfabético y pueden sobrescribir la configuración general. Esta aproximación es más limpia y fácil de mantener.
Cuando trabajes con nice, renice e ionice, no olvides que siempre puedes consultar su manual con:
Manuales:
man nice
man renice
man ionice
Entender bien cómo Linux planifica procesos y saber manejar con soltura comandos como nice, renice e ionice te da un control fino sobre CPU y disco, permitiéndote mantener el sistema ágil incluso bajo carga intensa, priorizar servicios críticos y relegar a segundo plano las tareas pesadas que pueden esperar sin molestar a nadie.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.