2.7.2. Control de procesos¶
linux es un sistema operativo multitarea, esto es, capaz de ejecutar varios programas en paralelo. Al hilo de este asunto, cabe hacer una serie de definiciones:
- Proceso
Se denomina proceso, simplemente, a un programa que está en ejecución. Cada procesos tiene una serie de propiedades que definen su estado. Una de ellas, muy importante es el PID.
- PID (Process IDentifier)
Es el número asociada a un proceso que lo identifica de manera inequívoca. Esto implica que es único.
- Demonio (servicio en la terminología de los sistemas windows)
Es un proceso que se ejecuta en segundo plano, es decir, que se ejecuta sin que intervenga en su ejecución de manera interactiva el usuario.
- Prioridad
Es la preferencia que el sistema le da a la ejecución de un proceso. Está representada por un número entre -20 (máxima prioridad) y 19 (mínima prioridad). La prioridad normal es 0.
Bajo este epígrafe trataremos el modo de conocer cuáles son los procesos que ejecuta el sistema, qué recursos consumen, cómo cancelarlos o como traerlos a primer plano y mandarlos a segundo plano. La gestión de los demonios, por ser más un asunto de servidor, se dejará para más adelante.
2.7.2.1. Consulta¶
- ps
Permite obtener información sobre los procesos que se ejecutan en el sistema. Hay dos modos de pasarle opciones: siguiendo el estilo BSD, en que las opciones no van precedidas de guión; y siguiendo el estilo unix, en que son precedidas por uno. Por coherencia con el resto de comandos, usaremos este segundo método[1].
El modo más elemental de uso es aquel que muestra todos los procesos:
$ ps -e PID TTY TIME CMD [...] 518 ? 00:00:00 ntpd 520 ? 00:00:00 samba 522 ? 00:00:00 samba 523 ? 00:00:00 samba 524 ? 00:00:00 samba 525 ? 00:00:00 samba 526 ? 00:00:00 smbd 527 ? 00:00:00 samba 528 ? 00:00:00 samba 529 ? 00:00:00 samba 530 ? 00:00:00 samba 531 ? 00:00:00 samba 532 ? 00:00:00 winbindd 533 ? 00:00:00 samba 534 ? 00:00:00 samba 535 ? 00:00:00 samba 536 ? 00:00:00 samba 541 ? 00:00:00 smbd-notifyd 542 ? 00:00:00 cleanupd 544 ? 00:00:00 winbindd 545 ? 00:00:00 lpqd [...]
o bien todos los procesos que están asociados a una terminal:
$ ps -a PID TTY TIME CMD 3068 pts/1 00:00:06 vim 3913 pts/0 00:00:00 tmux: client 4354 pts/5 00:00:00 su 4368 pts/5 00:00:00 bash 5490 pts/4 00:00:00 vim 5654 pts/7 00:00:00 su 5667 pts/7 00:00:00 bash 5672 pts/3 00:00:00 ps
En la salida se observan entre otros el PID del proceso, la terminal asociada y el ejecutable que lo originó. Puede obtenerse un formato largo que da más información con
-f
:$ ps -ef [...] ntp 518 1 0 11:08 ? 00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 107:111 root 520 1 0 11:08 ? 00:00:00 /usr/sbin/samba root 522 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 523 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 524 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 525 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 526 522 0 11:08 ? 00:00:00 /usr/sbin/smbd -D --option=server role check:inhibit=yes --foreground root 527 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 528 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 529 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 530 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 531 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 532 531 0 11:08 ? 00:00:00 /usr/sbin/winbindd -D --option=server role check:inhibit=yes --foreground root 533 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 534 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 535 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 536 520 0 11:08 ? 00:00:00 /usr/sbin/samba root 541 526 0 11:08 ? 00:00:00 /usr/sbin/smbd -D --option=server role check:inhibit=yes --foreground root 542 526 0 11:08 ? 00:00:00 /usr/sbin/smbd -D --option=server role check:inhibit=yes --foreground root 544 532 0 11:08 ? 00:00:00 /usr/sbin/winbindd -D --option=server role check:inhibit=yes --foreground root 545 526 0 11:08 ? 00:00:00 /usr/sbin/smbd -D --option=server role check:inhibit=yes --foreground [...]
Los procesos derivan unos de otros, de manera que un proceso tiene un proceso padre. SI se quiere observar esta jerarquía de permisos puede usarse la opción
-H
:$ ps -eH [...] 518 ? 00:00:00 ntpd 520 ? 00:00:00 samba 522 ? 00:00:00 samba 526 ? 00:00:00 smbd 541 ? 00:00:00 smbd-notifyd 542 ? 00:00:00 cleanupd 545 ? 00:00:00 lpqd 523 ? 00:00:00 samba 524 ? 00:00:00 samba 525 ? 00:00:00 samba 527 ? 00:00:00 samba 528 ? 00:00:00 samba 529 ? 00:00:00 samba 530 ? 00:00:00 samba 531 ? 00:00:00 samba 532 ? 00:00:00 winbindd 544 ? 00:00:00 winbindd 533 ? 00:00:00 samba 534 ? 00:00:00 samba 535 ? 00:00:00 samba 536 ? 00:00:00 samba [...]
Alternativa a la opción
-H
es--forest
, con la que obtenemos una salida más vistosa y elocuente:$ ps -e --forest [...] 518 ? 00:00:00 ntpd 520 ? 00:00:00 samba 522 ? 00:00:00 \_ samba 526 ? 00:00:00 | \_ smbd 541 ? 00:00:00 | \_ smbd-notifyd 542 ? 00:00:00 | \_ cleanupd 545 ? 00:00:00 | \_ lpqd 523 ? 00:00:00 \_ samba 524 ? 00:00:00 \_ samba 525 ? 00:00:00 \_ samba 527 ? 00:00:00 \_ samba 528 ? 00:00:00 \_ samba 529 ? 00:00:00 \_ samba 530 ? 00:00:00 \_ samba 531 ? 00:00:00 \_ samba 532 ? 00:00:00 | \_ winbindd 544 ? 00:00:00 | \_ winbindd 533 ? 00:00:00 \_ samba 534 ? 00:00:00 \_ samba 535 ? 00:00:00 \_ samba 536 ? 00:00:00 \_ samba [...]
También hay formas de filtrar los procesos mostrados según distintos criterios. Por ejemplo, para elegir los de un determinado usuario:
$ ps -u josem
o elegir procesos por nombre:
$ ps -C systemd
o por PID[2]:
$ ps 1000
o mostrar los procesos de un determinado padre. Para ello se debe indicar el PID del proceso padre:
$ ps --ppid 1579
ps permite incluir varias opciones de filtrado:
$ ps -C bash -u josem
incluso varias veces la misma opción:
$ ps -C bash -C system
pero nunca acomulan el efecto de filtrado, sino el resultado. Es decir, en el ejemplo:
$ ps -C bash -u josem
no devuelve los procesos de bash que esté ejecutando el usuario «josem», sino cualquier proceso de bash (sea o no de «josem») más cualquier proceso que pertenezca a «josem» (sea de bash o de cualquier otro programa). En el segundo ejemplo:
$ ps -C bash -C system
la orden devuelve cualquier proceso de bash o de systemd. Cuando el criterio es el mismo también se puede usar esta alternativa:
$ ps -C systemd,bash
Advertencia
Tenga presente que si quiere que los criterios de filtrado sean acomulativos, esto es, que el resultado cumpla ambos criterios, tendrá que recurrir a pgrep.
También se puede definir exactamente qué campos se quieren obtener mediante la opción
-o
seguida de los nombres de los campos (véase la página del manual ps). Por ejemplo, esto mostraría para todos de los procesos el nombre del usuario que lo ejecuta, el pid, el ppid y el ejecutable:$ ps -eo user=,pid=,ppid=,comm=
El signo igual, indica que no se desea que ps incluya para el campo cabecera. Si todos los campos incluyen un igual, entonces no habrá cabecera alguna.
Se pueden también ordenar los resultados con
-sort
:$ ps -eo user=,pid=,ppid=,comm= --sort ppid,pid
- pstree
Muestra los procesos del sistema en forma de árbol, tal como hace el comando tree con los directorios y ficheros. Para constituir este árbol debe saber que todo proceso tiene un proceso padre del que deriva. Por ejemplo, si en una sesión de bash ejecutamos este comando pstree, el proceso correspondiente a éste es hijo del proceso de bash.
- pgrep
Permite obtener el PID de un proceso atendiendo a distintos criterios. Su uso más sencillo es obtener los PID asociado al nombre de un programa. Por ejemplo, esto devolvería todos los procesos que se corresponden con sesiones de bash:
$ pgrep bash 2966 3004 3084 3588 3811 3967 4368 4546 5529
Puede no indicarse el nombre del programa, en cuyo caso se entenderá que deseamos el de cualquier programa, o bien, utilizar una expresión regular que nos permitirá hacer búsquedas más poderosas. Por ejemplo, esta búsqueda:
$ pgrep 'sh$'
nos devolverá los PID de todos los procesos cuyo nombre de programa acabe en «sh».
Advertencia
En realidad el argumento de pgrep es simplemente un patrón expresado en forma de expresión regular extendida, incluso en el primer ejemplo:
$ pgrep bash
Por tanto, este primer ejemplo no devuelve los PID de los procesos de bash, sino los PID de cualquier programa que dentro de su nombre incluya la cadena «bash».
En principio, la concordancia se realiza únicamente con el nombre del proceso, pero puede buscarse concordancia con la orden completa (que incluye parámetros) utilizando la opción -f. Por ejemplo:
$ pgrep -f 'systemd.*user' 937523
concordaría con procesos de systemd propios de usuarios:
$ pgrep -af 'systemd.*user' 937523 /lib/systemd/systemd --user
Para filtrar los resultados podemos añadir opciones que fija criterios adicionales. Por ejemplo:
$ pgrep -u usuario 1223 1300 1311 1328 1380 1387
permite obtener los PID de todos los procesos (no hemos indicado qué programa) que pertenezcan al usuario de nombre «usuario». O bien:
$ pgrep -P 1114 1116 2602
devuelve los procesos cuyo proceso padre es el proceso 1114.
A diferencia de ps los criterios de filtro son acumulativos, por lo que si se utilizan varios, pgrep sólo devolverá aquellos que cumplan con todos. En consecuencia:
$ pgrep -u usuario bash
devolverá los procesos de bash a nombre del usuario «usuario». Además, debe tenerse en cuenta que en las opciones (pero no en el patrón que debe ser único), pueden indicarse varios criterios a la vez:
$ pgrep -u usuario,root bash
que devolverá los procesos de bash a nombre de «usuario» o «root».
Otra opción interesante es -c que en vez de devolver los PID de los procesos, devuelve cuántos procesos en total. Por tanto, pasa saber cuántos procesos está ejecutando el usuario «usuario»:
$ pgrep -cu usuario 6
Lamentablemente, pgrep sólo devuelve el PID (y la orden completa con -a) y no una información tan completa y configurable como ps.[3]
- top
Permite observar los procesos en tiempo real:
$ top
- htop
Es una aplicación que mejora la interfaz de top:
$ htop
Es probable que no esté incluida en la instalación base y requiera su instalación explícita.
- uptime
Muestra el tiempo trascurrido desde el arranque. el número de usuarios conectados y la carga media del sistema en el último minuto, los cinco últimos minutos y los quince últimos minutos:
$ uptime 00:07:44 up 116 days, 12:15, 2 users, load average: 0,00, 0,03, 0,09
Tiene algunas opciones. Con
-s
da una respuesta muy parecida a who con la opción-b
:$ uptime -s 2016-09-09 12:52:12
- time
Permite conocer el tiempo que tarda una orden en completarse:
$ time sleep 2 real 0m2.009s user 0m0.004s sys 0m0.000s
real es el tiempo trascurrido desde que comenzó la orden hasta que se completo. user el tiempo de CPU fuera del kernel empleado y sys el tiempo de CPU dentro del kernel empleado. Por tanto, la suma de las dos últimas cantidad indica el tiempo total de CPU empleada.
2.7.2.2. Manipulación¶
Ya se ha explicado cómo dar órdenes. Una orden provoca la creación de un proceso durante un determiando tiempo. Ahora bien, es posible modificar la forma en que se da la orden para lograr distintos fines.
- nice
Modifica la prioridad de un proceso. Cuando se ejecuta una orden, la prioridad del proceso es 0. Sin embargo, nice permite cambiar esta prioridad. Para usuarios distintos del administrador sólo se puede disminuir la prioridad, es decir, dar valores positivos.
Para usar nice basta con anteponerlo al proceso que se quiere ejecutar. Por ejemplo:
$ nice ffmpeg -i input.wmv -s hd720 -c:v libx264 -crf 23 -c:a aac -strict -2 output.mp4
recodifica una película en calidad HD720, haciendo que para este proceso bastante costoso disminuya la prioridad. Cuando nice se usa sin indicar la prioridad, se supone que esta es 10. Puede especificarse la prioridad exacta con la opción
-n
:$ nice -n10 ffmpeg [...]
Valores negativos hace el proceso más prioritario de lo normal, pero deben adjudicarse como root.
- renice
Modifica la prioridad de un proceso ya comenzado. Para seleccionar este proceso necesitamos el pid del mismo, el cual podemos obtener a traves de ps, por ejemplo. Suponiendo que sea el 5789:
$ renice -n 10 -p 5789
- kill
Envía señales a los procesos, muy comúnmente para acabar con ellos, de ahí su nombre. Hay una larga lista de señales que pueden obtenerse mediante la opción -L:
$ 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 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Las más usadas para acabar procesos son:
- SIGTERM (15)
Que le indica al proceso que haga un apagado suave e intente cerrar antes todo los recursos que tenga abiertos. Es el apagado más recomentable, aunque no siempre funciona, sobre todo si el proceso tiene algún hijo. Es el apagado que kill, pkill o killall intentan por defecto si no se especifica otro concreto.
- SIGHUP (1)
HUP proviene de hang up, esto es, colgar y es la señal que recibían los programas cuando en accesos remotos por conexión serie el usuario decide colgar. En sistemas modernos este acceso no es tan común y la señal se ha reciclado y significa que la terminal dentro de la que corre el programa se ha cerrado. En bastantes programas interactivos la señal puede tener el efecto de un apagado suave como SIGTERM, pero en los demonios, que como no son interactivos, no suelen ejecutarse en una terminal, es común que se interprete como que es necesario volver a leer la configuración y, en consecuencia, el programa no acabe. Por tanto, si nuestra intención es acabar un proceso de forma suave, es más recomendable la opción anterior.
- SIGINT (2)
Acaba taxativamente el proceso, aunque éste puede no hacer caso a la señal. Equivale a Ctrl+C sobre un proceso en primer plano.
- SIGKILL (9)
Provoca el apagado obligatorio, por lo que, aunque tiene las mismas consecuencias de la señal anterior (puede quedar algo abierto), la señal no puede ser obviada por el proceso.
Lo habitual, cuando se intenta acabar manualmente con un proceso, es intentar el apagado suave (SIGTERM) y, si este no es posible, intentar el apagado forzoso (SIGKILL). Por tanto, si quisiéramos acabar con los procesos de PID 1037 y 1000, haríamos:
$ kill 1897 1000
o bien:
$ kill -15 1897 1000
que es lo mismo. Y, si esto no funciona, no tendremos más remedio que hacer:
$ kill -9 5675 6676
Nota
En ocasiones, es imposible acabar del todo con un proceso ni aun con la señal
SIGKILL
(9). En estos casos, el proceso acaba en un estado zombi por tiempo indefinido, que se nota con un Z al consultar el proceso con ps.- SIGTSTP (20)
Suspende el proceso, esto es, lo deja en estado «Suspendido» a la espera de que otra orden de usuario vuelva a ponerlo en ejecución. Equivale a Ctrl+Z sobre un proceso en primer plano.
- SIGSTOP (19)
Como el anterior, pero la parada es más agresiva. Es preferible la orden anterior.
- SIGCONT (18)
Reanima un proceso suspendido.
El uso de kill es bastante sencillo:
$ kill -SEÑAL PID1 PID2 ...
o sea, se indica la señal y se indican la relación de PID correspondientes a los procesos a los que se quiere enviar la señal. Para expresar la señal podemos usar el número (p.e. 9), su nombre (p.e. SIGKILL) o su nombre abreviado (p.e. KILL).
Advertencia
kill es una orden interna del intérprete, por lo que depende de este. Usar el nombre completo (SIGKILL) funciona en la versión de bash, pero no en dash
También es posible utilizar en vez del PID del proceso, su identificador de trabajo en la sesión (véase jobs), pero antecediéndolo con un «%»:
$ sleep 1000 & [1] 12699 $ jobs [1]+ Ejecutando sleep 1000 & $ kill -TSTP 12699 $ jobs [1]+ Detenido sleep 1000 $ kill -CONT %1 $ jobs [1]+ Ejecutando sleep 1000 &
- pkill
Es una orden que, como kill, permite enviar señales a los procesos, pero para cuya selección se usa la sintaxis de pgrep. Por tanto, podremos referirlos mediante su nombre (no su PID) añadiendo criterios acomulativos de selección como con pgrep, y además, indicar qué señal enviar como con kill:
# pkill -15 -uroot bash
- killall
Cancela procesos identificándolos por su nombre. Pueden usarse las señales indicadas anteriormente. Por ejemplo, esto cancela de forma suave todas las sesiones de bash abiertas que pueda cancelar quien lo ejecuta:
$ killall bash
Tiene opciones (-u, -g, etc.) para ser más específico, pero no dispone de tantas como pkill.
Advertencia
killall es parte del paquete psmisc, que puede no encontrarse instalado por defecto.
Por lo general, cuando se ejecuta una orden, la shell espera hasta que esta haya acabado para liberar la línea de comandos. Esto es debido a que la orden se ejecuta en primer plano. Arrancada de este modo, podemos escribir Ctrl+C para cancelar la orden tal como haríamos con kill; pero también podemos escribir Ctrl+Z para detener la orden. Si hacemos esto segundo, la orden deja de ejecutarse, pero no están cancelada: simplemente queda a la espera de que demos la orden de proseguir. Por ejemplo, supongamos que hacemos una cuenta de 1 a 10 esperando un segundo entre número y número:
$ (for i in {1..10}; do sleep 1; echo $i; done)
1
^Z
[1]+ Detenido ( for i in {1..10};
- jobs (orden interna de la shell)
Permite consultar la lista de trabajos activos en la sesión actual:
$ jobs [1]+ Detenido ( for i in {1..10};
Por tanto, hay una tarea detenida. Si deseamos que prosiga, hay dos posibilidades: que mandemos que se ejecute en primer plano…
- fg (orden interna de la shell)
Manda una tarea a primer plano (y la activa en caso de que estuviera suspendida). Para referirse a ella se debe especificar el número de trabajo que proporciona jobs:
$ fg %1 2 3 ... 10 $
Nota
Para refefir el proceso por su PID en vez de por su número de trabajo debe antecederse el número con # en vez de con %.
o mandamos que se ejecute en segundo plano…
- bg (orden interna de la shell)
Manda una tarea a segundo plano. Para referirse a ella se debe especificar el número de trabajo que proporciona jobs:
$ bg %1
Es posible también ejecutar una tarea en segundo plano acabando la orden con un &:
$ sleep 60 &
[1] 15991
$ jobs
[1]+ Ejecutando sleep 60 &
2.7.2.3. Ejercicios sobre gestión de procesos¶
Mostrar los procesos ejecutados por el usuario «usuario».
Mostrar:
las shells que se están ejecutando en el sistema.
Lo mismo, pero sólo aquellas que ejecutan el usuario «usuario» (en este segundo casa, basta con indicual cuáles son los PID)
Mostrar todos los procesos ordenados por uso de la CPU.
Mostrar todos los procesos indicando el PID, el UID del propietario, la memoria utilizada, la prioridad y el comando completo.
¿Cúantos procesos tiene corriendo en el sistema el usuario «usuario»?
¿Desde cuándo lleva encencida la máquina?
Ejecutar el comando sleep 1000, suspenderlo y ponerlo a trabajar en segundo plano; volverlo a traer a primer plano y, por último, cancelarlo
Ejecutar el comando sleep 1000, suspenderlo, ponerlo a trabajar en segundo plano y, sin traerlo a primer plano, acabar con él.
Indicar qué tiempo tarda el ordenador en buscar dentro del directorio de configuraciones el fichero dhclient.conf.
La orden:
$ programa_muy_pesado
tarda mucho en ejcutarse y consume mucho procesamiento, y hace que la película que estamos viendo mientras esperamos a que se complete, vaya a tirones. ¿Cömo puedo ejecutarla para poder ver la película sin problemas?
Notas al pie