martes, 22 de diciembre de 2020

Administración de procesos del sistema - Ubuntu

Posted by q3it on martes, diciembre 22, 2020 in ,


Qué son los procesos y cómo podemos gestionarlos 
Hoy en día Ubuntu y la mayoría de distros GNU/Linux cuentan con una Interfaz de Usuario, que permite al usuario usar el Sistema casi sin saber nada sobre él, y eso está bien. Se parte de la premisa de que el usuario no tiene por qué tener conocimientos avanzados, y es por ello por lo que el uso de Ubuntu y GNU/Linux en general es de cada vez más intuitivo. 

Ahora bien, nunca está de más saber cómo funciona lo que estamos usando. Además, sabemos que si usas GNU/Linux es en parte por tu inconformidad, por tu curiosidad y por tus ganas de aprender. 

Cómo todos sabremos, Ubuntu (GNU/Linux) es un Sistema Operativo multitarea. Esto significa que es capaz de ejecutar varios procesos (tareas) simultáneamente, sin que haya problemas entre ellos. 

Pero… ¿Qué es un proceso? 
Un proceso no es más que una instancia de un programa. O dicho de otra forma, un programa no es más que una serie de procesos que se están ejecutando. Así que de un modo coloquial, un proceso se podría entender cómo un programa que se está ejecutando. 

Los procesos, como ya sabemos, pueden ejecutarse de dos modos; en foreground (en primer plano) o en background (en segundo plano). 

Además, un proceso también tiene un estado, puesto que no sólo puede estar ejecutándose. Si por ejemplo un proceso A lanza otro proceso B, el A pasa a conocerse como el proceso padre y el B como el proceso hijo (child). Lo más frecuente es que cuando esto ocurre, A quede en estado suspendido. 

Podemos verlo con un ejemplo: 
Si abrimos la Terminal de Ubuntu, ya estamos lanzando un nuevo proceso, puesto que la terminal es otro programa más. Y si desde la Terminal lanzamos otro programa, veremos que queda suspendida. Es decir, si una vez abierta la Terminal, ejecutamos: 

gedit f_prueba 

para abrir un nuevo fichero llamado f_prueba (con el editor de texto Gedit), veremos que la terminal queda suspendida y que “ya no la podemos seguir usando”. Si queríamos seguir usando esa misma Terminal después de lanzar el proceso, basta con que lo lancemos en background (segundo plano), es decir, basta que ejecutemos: 

gedit f_prueba & 

El símbolo “&” indica que queremos que dicho proceso se ejecute en background. De este modo, una vez lanzado el proceso, podemos seguir usando la Terminal, puesto que no habrá quedado suspendida y ambos procesos se seguirán ejecutando con normalidad. 

¿Cómo puedo saber qué procesos se están ejecutando en Ubuntu? 

PS 
El comando ps es el que permite informar sobre el estado de los procesos. PS esta basado en el sistema de archivos /proc, es decir, lee directamente la información de los archivos que se encuentran en este directorio. Tiene una gran cantidad de opciones, incluso estas opciones varían dependiendo del estilo en que se use el comando. Estas variaciones sobre el uso de ps son las siguientes: 
  • Estilo UNIX, donde las opciones van precedidas por un guión. 
  • Estilo BSD, donde las opciones no llevan guión.
  • Estilo GNU, donde se utilizan nombres de opciones largas y van precedidas por doble guión.
Sea cual sea el estilo utilizado, dependiendo de las opciones indicadas, varias columnas se mostrarán en el listado de procesos que resulte, estas columnas pueden ser entre muchas otras, las siguientes (y principales):

Columna                                         Descripción 

p o PID                         Process ID, número único o de identificación del proceso. 

P o PPID                      Parent Process ID, padre del proceso 

U o UID                       User ID, usuario propietario del proceso 

t o TT o TTY               Terminal asociada al proceso, si no hay terminal aparece entonces un '?' 

T o TIME                    Tiempo de uso de cpu acumulado por el proceso 

c o CMD                      El nombre del programa o camando que inició el proceso 

RSS                              Resident Sise, tamaño de la parte residente en memoria en kilobytes 

SZ o SIZE                   Tamaño virtual de la imagen del proceso 

NI                             Nice, valor nice (prioridad) del proceso, un número positivo significa menos                                   tiempo de procesador y negativo más tiempo (-19 a 19) 

C o PCPU                   Porcentaje de cpu utilizado por el proceso 

STIME                       Starting Time, hora de inicio del proceso 

S o STAT                   Status del proceso, estos pueden ser los siguientes 
  • R runnable, en ejecución, corriendo o ejecutándose 
  • S sleeping, proceso en ejecución pero sin actividad por el momento, o esperando por algún evento para continuar 
  • T sTopped, proceso detenido totalmente, pero puede ser reiniciado 
  • Z zombie, difunto, proceso que por alguna razón no terminó de manera correcta, no debe haber procesos zombies 
  • D uninterruptible sleep, son procesos generalmente asociados a acciones de IO del sistema 
  • X dead, muerto, proceso terminado pero que sigue apareciendo, igual que los Z no deberían verse nunca 
Las opciones completas de ps las encuentras en las páginas del manual (man ps), o escribiendo en la terminal ps L, y para ver un resumen de sus opciones más comunes usa ps --help: 

A continuación algunos ejemplos de ps con la salida recortada. 

># ps -e (-e muestra todos los procesos) 

PID TTY                           TIME CMD 

1 ?                                      00:00:01 init 
2 ?                                     00:00:00 kthreadd 
3 ?                                     00:00:00 migration/0 
4 ?                                     00:00:00 ksoftirqd/0 

#> ps -ef (-f muestra opciones completas) 

UID        PID  PPID  C STIME TTY          TIME             CMD

root         1     0         0 10:12     ?             00:00:01             init [5]

root         2     0         0 10:12     ?             00:00:00             [kthreadd]

root      6130  5662  0 10:24    pts/0         00:00:00             su -

root      6134  6130  0 10:24    pts/0         00:00:00             -bash

sergon 6343  5604  0 10:28      ?      00:00:00 kio_file [kdeinit] file /home/sergon/tmp/ksocket-sergon/kl

root      6475  6134  0 10:38    pts/0         00:00:00             ps -ef


#> ps -eF (-F muestra opciones completas extra) 

UID        PID       PPID      C      SZ     RSS     PSR    STIME   TTY          TIME       CMD

root         1            0           0      412     556        1        16:59     ?              00:00:01 init [5]

root         2            0            0     0         0            1        16:59     ?              00:00:00 [kthreadd]

sergon    8326  8321          0     902    1272       0        17:07      ?             00:00:00 /bin/sh /usr/lib/firefox-2.0.0.8/run-mozilla.sh /usr/lib/f

sergon    8331  8326     4     53856 62604  0   17:07    ?   00:00:50 /usr/lib/firefox-2.0.0.8/mozilla-firefox-bin

sergon    8570  7726        2     15211 37948    0     17:17      ?                 00:00:10 quanta


#> ps ax (formato BSD sin guión, a muestra todos, x sin mostrar tty) 


PID TTY      STAT   TIME COMMAND

    1    ?           Ss          0:01 init [5]

    2    ?           S<         0:00 [kthreadd]

    3    ?           S<         0:00 [migration/0]

    4    ?           S<         0:00 [ksoftirqd/0]


#> ps aux (formato BSD sin guión, u muestra usuarios y demás columnas) 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root             1      0.0       0.0       1648   556    ?          Ss    16:59        0:01 init [5]

root             2      0.0       0.0          0         0     ?           S<   16:59        0:00 [kthreadd]

root             3      0.0       0.0          0         0      ?           S<   16:59       0:00 [migration/0]

root            4       0.0       0.0          0         0      ?           S<   16:59       0:00 [ksoftirqd/0]

root            5       0.0       0.0          0         0      ?           S<   16:59       0:00 [migration/1]


#> ps -eo user,pid,tty (-o output personalizado, se indican los campos separados por coma, ver ps --help o ps L) 

USER       PID TT

root            1    ?

root            2    ?

sergon    8570 tty 1

root         8876 pts/1

#> ps -eH  (muestra árbol de procesos)

#> ps axf  (lo mismo en formato BSD)

#> ps -ec  (el comando  que se esta ejecutando, sin la ruta, solo el nombre real)

#> ps -el  (muestra formato largo de varias columnas, muy práctico)

#> ps L    (No muestra procesos, lista todos los códigos de formatos)

Para ver la lista de procesos que se están ejecutando, basta con que abramos una Terminal y ejecutamos: 

ps -aux

La única información que nos interesa de la lista, es el PID. El PID (Identificador de Proceso) es un número entero que se encarga de identificar a un único proceso. 

Además, Ubuntu (y todas las distros GNU/Linux) cuentan con un fichero que determina el valor máximo del PID. Esto, obviamente nos determina la cantidad máxima de procesos que se van a ejecutar. El fichero se llama pid_max y está dentro del directorio /proc/sys/kernel/. Si queremos ver su contenido basta con que ejecutar: 

cat /proc/sys/kernel/pid_max

Como se ve en la figura anterior, que por defecto, la cantidad máxima de procesos que se pueden ejecutar son 32768. Por otro lado, si queremos buscar los procesos asociados a un determinado programa podemos usar una tubería y el comando grep para filtrar el resultado. Es decir, si por ejemplo queremos ver todos los procesos asociados a Gimp, podemos ejecutar: 

ps -aux | grep writer

Cómo se ve, en mi caso hay 3 procesos asociados a Writer. 

pstree 
Muestra los procesos en forma de árbol, pstree --help te da las opciones más comunes. Recomendable la opción -A y -G para que te de un árbol con líneas con líneas estilo ASCII y de terminal VT100 respectivamente, puedes añadir también -u para mostrar entre paréntesis al usuario propietario del proceso: 

#> pstree -AGu 
init---acpid 
    |-atd(daemon) 
    |-automount----2*[{automount}] 
    |-avahi-daemon(avahi) 
    |-beagled(sergon)----7*[{beagled}] 
    |-beagled-helper(sergio)----3*[{beagled-helper}] 
    |-compiz(sergon)----kde-window-deco 
    |-console-kit-dae----61*[{console-kit-dae}] 
    |-crond 
    |-dbus-daemon(messagebus) 
    |-dbus-daemon(diego) 
    |-dbus-launch(diego) 
    |-dcopserver(diego) 
    |-dhclient 
    |-gam_server(diego) 
    |-gconfd-2(diego) 
    |-hald(haldaemon)----hald-runner(root)----hald-addon-acpi(haldaemon) 
    | |-hald-addon-cpuf 
    | |-hald-addon-inpu 
    | |-hald-addon-stor 
    |-httpd---8*[httpd(apache)] 
    |-2*[ifplugd] 
    |-ipw3945d 
    |-kaccess(diego) 

ps axjf (que mostrará un árbol jerárquico con la ruta del programa al que pertenece el proceso).


TOP 
Top es otro gestor de procesos integrado en la mayoría de sistemas Linux. Mientras que ps nos muestra un listado de procesos estático, es decir, nos informa de los procesos, nombres, usuarios o recursos que se están usando en el momento de la petición; top nos da un informe en tiempo real de los mismos.


top -d 5 (Donde 5 es el número de segundos a transcurrir entre cada muestreo) 
top -o %CPU (Donde %CPU es el valor por el que vamos a ordenar los procesos ) 
top -u diego (Donde diego es el usuario del cual queremos mostrar los procesos) 


HTOP 
Otro gestor de procesos muy interesante y usado es ‘ htop ’, que nos mostrará sin salir de la terminal (si es que lo ejecutamos desde ésta…) algo similar a top, pero donde mediante las teclas de función del teclado, accederemos a menús de configuración al estilo de las aplicaciones DOS.

En htop, al tratarse de una aplicación en sí donde ya podremos configurar algunos de sus aspectos y criterios de orden, hay poco que configurar, no obstante, tal y como podemos leer en su manual, podemos hacer que inicie en modo monocromo, predefinir el delay o intervalo de refresco, etc. 

Y… ¿Cómo puedo matar un proceso? 

KILL 
Los sistemas Linux vienen con la herramienta KILL instalada, que usaremos para detener los procesos que necesitemos. Por defecto el comando kill envía una señal denominada TERM a un proceso que le pasaremos mediante su PID como argumento. Esta señal TERM pedirá a dicho proceso que termine, permitiéndole gestionar su función de cierre, completando las tareas necesarias y limpiando la información que ha cargado en memoria. 

Así por ejemplo, es posible enviar una señal de STOP al proceso y se detendrá su ejecución, después cuando se quiera mandar una señal de CONTinuar y el proceso continuará desde donde se quedó. 

#> kill -l (lista todas las posibles señales que pueden enviarse a un proceso) 

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 

La lista previa presenta todas las posibles señales que pueden mandarse a un proceso y estas pueden ser invocadas a través del número de la señal o de su código, por ejemplo: 

#> kill -9 11428 (termina, mata un proceso completamente) 

#> kill -SIGKILL 11428 (Lo mismo que lo anterior) 

Las señales más comunes son la 19 y 20 que detienen momentáneamente la ejecución de un proceso o programa, 18 la continua, 1 qué es la señal de hang up que obliga al proceso a releer sus archivos de configuración estando en ejecución y 9 que termina rotundamente un proceso. 

killall 
El comando killall, que funciona de manera similar a kill, pero con la diferencia de en vez de indicar un PID se indica el nombre del programa, lo que afectará a todos los procesos que tengan ese nombre. Así por ejemplo si se tienen varias instancias ejecutándose del proxy server squid, con killall squid eliminará todos los procesos que se estén ejecutando con el nombre 'squid' 

#> killall -l (lista de posibles señales) 

#> killall -HUP httpd (manda una señal de "colgar", detenerse releer sus archivos de configuración y reiniciar) 

#> killall -KILL -i squid (manda señal de matar a todos los procesos squid pero pide confirmación en cada uno) 

NICE 
Permite cambiar la prioridad de un proceso. Por defecto, todos los procesos tienen una prioridad igual ante el CPU que es de 0. Con nice es posible iniciar un programa (proceso) con la prioridad modificada, más alta o más baja según se requiera. Las prioridades van de -20 (la más alta) a 19 la más baja. Solo root o el superusuario puede establecer prioridades negativas que son más altas. Con la opción -l de ps es posible observar la columna NI que muestra este valor. 

#> nice (sin argumentos, devuelve la prioridad por defecto ) 

#> nice -n -5 comando (inicia comando con una prioridad de -5, lo que le da más tiempo de cpu) 

renice 
Así como nice establece la prioridad de un proceso cuando se inicia su ejecución, renice permite alterarla en tiempo real, sin necesidad de detener el proceso. 

#> nice -n -5 yes  (se ejecuta el programa 'yes' con prioridad -5) 

                                (dejar ejecutando 'yes' y en otra terminal se analiza con 'ps') 

#> ps -el 

F S   UID   PID  PPID  C PRI  NI ADDR SZ   WCHAN  TTY       TIME       CMD

4 S     0 12826 12208  4  75    -5   -        708  write_     pts/2      00:00:00  yes#> renice 7 12826 

#> renice 7 12826

12826: prioridad antigua -5, nueva prioridad 7

#> ps -el

F S   UID   PID  PPID  C PRI  NI ADDR SZ     WCHAN  TTY          TIME     CMD

4 S     0 12826 12208  4  87    7   -         708     write_     pts/2         00:00:15 yes

(obsérvese el campo NI en el primer caso en -5, y en el segundo con renice quedó en 7, en tiempo real) 

Procesos en segundo plano 
NOHUP Y & 
Cuando se trata ejecutar procesos en background (segundo plano) se utiliza el comando nohup o el operador & . Aunque realizan una función similar, no son lo mismo. 

Para que un proceso no se termine al cerrar la sesión de usuario o ssh deberemos ejecutar el comando nohup seguido del comando a ejecutar. 

Así por lo tanto, Si disponemos de un disco duro inmenso en que queremos buscar la totalidad de archivos con un tamaño superior a 100M ejecutaremos el siguiente comando en la terminal: 

nohup find /home -type f -size +100M > ~/resultados & 
La función de cada uno de los parámetros es la siguiente: 
  • nohup: Parte del comando que hace que no se cierre la acción que estemos ejecutando. 
  • find /home -type f -size +100M: Parte del comando que busca todos los archivos de nuestra partición home con tamaño superior a 100 MB. 
  • > ~/resultados: Corresponde a la ruta y nombre del archivo que almacenará los resultados de nuestras búsqueda. En el caso que quisiéramos que ningún archivo almacene los resultados deberíamos reemplazar > ~/resultados por > ~/dev/null 2>&1. 
  • &: Parámetro utilizado para que podamos seguir introduciendo comandos en la terminal donde ejecutamos el comando. 
JOBS 
Si por ejemplo, se tiene acceso a una única consola o terminal, y se tienen que ejecutar varios comandos que se ejecutarán por largo tiempo, se pueden entonces como ya se vió previamente con nohup y el operador '&' mandarlos a segundo plano o background con el objeto de liberar la terminal y continuar trabajando. 

Pero si solo se está en una terminal esto puede ser difícil de controlar, y para eso tenemos el comando jobs que lista los procesos actuales en ejecución: 

#> yes > /dev/null & 

[1] 26837 

#> ls -laR > archivos.txt & 

[2] 26854 

#> jobs 

[1]- Running               yes >/dev/null & 

[2]+ Running             ls --color=tty -laR / >archivos.txt & 

En el ejemplo previo, se ejecutó el comando yes y se envió a background (&) y el sistema devolvió [1] 26837, indicando asi que se trata del trabajo o de la tarea [1] y su PID, lo mismo con la segunda tarea que es un listado recursivo desde la raíz y enviado a un archivo, esta es la segunda tarea. 

Con los comandos fg (foreground) y bg background es posible manipular procesos que estén suspendidos temporalmente, ya sea porque se les envió una señal de suspensión como STOP (20) o porque al estarse ejecutando se presionó ctrl-Z. Entonces para reanudar su ejecución en primer plano usaríamos fg: 

#> jobs 

[1]- Stopped                 yes >/dev/null & 

[2]+ Stopped               ls --color=tty -laR / >archivos.txt & 

#> fg %1 

#> jobs 

[1]+ Running               yes >/dev/null & 

[2]- Stopped                ls --color=tty -laR / >archivos.txt & 

Obsérvese como al traer en primer plano al 'job' o proceso 1, este adquirió el símbolo [+] que indica que está al frente. Lo mismo sería con bg que volvería a reiniciar el proceso pero en segundo plano. Y también es posible matar los procesos con kill indicando el número que devuelve jobs: kill %1, terminaría con el proceso en jobs número 1. 
Usuarios con privilegios en el sistema 

En general, los usuarios tienen un acceso determinado al sistema dependiendo del tipo de privilegios. Para hacer frente a una mala administración, se sugiere las siguientes prácticas con respecto a la gestión de sus cuentas de usuario: 
  • No otorgue cuentas de usuario a las personas que realmente no las necesitan. Otorgar una cuenta de usuario shell en su sistema debe ser visto como un último recurso en la mayoría de los casos. 
  • Si usted necesita tener varios administradores en un sistema, en lugar de compartir una sola contraseña root entre todas estas personas, utilice sudo para dar "acceso root", pero obligue a los usuarios a autenticarse con sus propias contraseñas. El comando sudo también proporciona un registro más detallado, por lo que usted puede saber cuáles comandos root fueron ejecutados por qué usuario. 
  • Administre adecuadamente los grupos de usuarios y permisos para proporcionar un acceso granular cuando no tenga otra opción sino otorgar una cuenta de usuario en su sistema. 
  • Deshabilite las cuentas de usuario no utilizadas, ya sea eliminando la cuenta completamente con el comando userdel o bloqueando la cuenta de usuario con usermod. 
Teniendo en cuenta las recomendaciones anteriores podemos administrar de forma eficiente los procesos de nuestro sistema. Conociendo los procesos padre evaluaríamos si son necesarios que corran o si es mejor matarlos y también los subprocesos que cuelgan de él. También hay que tener claro que el usuario que no tenga privilegios de administrador solo podrá gestionar los procesos que estén bajo su perfil de usuario local.