Introducción a Linux. IV. 1. concepto de proceso En un sistema Linux, que es multitarea, se pueden estar ejecutando distintas tareas y programas al unísono, llamándose a cada acción un proceso. Lo de multitarea, refiere a que Linux puede activar procesos en primer y segundo plano, mostrando listas y árboles de procesos, suspendiéndolos y luego volviéndolos a activar, matándolos, haciendo que sigan ejecutándose una vez se halla cerrado la sesión o cambiando la prioridad de las tareas. Cuando se ejecuta un comando en el shell, este pasa a ser un proceso que ocupa parte de la memoria RAM del sistema, lo que deja menos memoria para los restantes procesos que se están ejecutando. Quien gestiona la asignación de memoria a cada proceso es el KERNEL de Linux (la parte central del sistema operativo), “decidiendo” cuánta memoria dar a cada proceso y cómo repartir la capacidad del microprocesador entre los procesos que se están ejecutando. Algunos procesos serán más importantes que otros y tendrán “preferencia” (prioridad) a la hora de pedir cálculos o instrucciones al microprocesador. Como todo en Linux, los procesos también tienen un dueño, que es el usuario que ejecuta el programa que da lugar al proceso. Con respecto a los permisos, un proceso podrá hacer al sistema de archivos, tanto como el usuario al que pertenece. Por ejemplo, un usuario normal no podrá modificar parámetros de procesos que no le pertenezcan mientras que, root podrá ejercer cualquier acción sobre cualquier proceso. Un proceso puede crear nuevos procesos. En la práctica, todos los procesos son hijos del primer proceso ejecutado durante el arranque, el proceso “init”. Tan es así que las relaciones entre los procesos pueden describirse según un único árbol. Las propiedades básicas de los procesos son: a. tienen un número identificador: PID (process ID) b. tienen un número de identificador de su proceso padre: PPID c. un estado; los más importantes son en ejecución (R) y dormido (S -esperando una señal) d. un dueño, generalmente el usuario que lo ejecutó, heredando sus permisos e. una prioridad, que determina su importancia El comando pstree permite ver los procesos y subprocesos en una estructura anidada (árbol). Con la opción -p (pstree -p), muestra entre paréntesis el PID de cada proceso, algo muy importante si queremos interactuar con ellos. Otros dos comandos muy usados son ps y top. El comando ps muestra una lista de los procesos en ejecución (como una “instantánea” de los procesos del sistema en el momento en que ejecutamos el comando). Con la opción u muestra sólo los pertenecientes al usuario actual, mientras que la combinación de opciones aux muestra información detallada de todos los procesos en ejecución. [usuario@maquina ~] $ ps aux El comando top es la versión iterativa de ps, y tiene algunas otras posibilidades. Si se ejecuta en una terminal y sin opciones, aparecerá un encabezado con información del sistema y luego una lista de procesos similar a la que mostraba ps, con la diferencia de que esta se actualiza periódicamente, permitiendo ver la evolución del estado de los procesos. Observa la salida en pantalla del comando top (puedes probar también el comando ps y ver la diferencia): [usuario@maquina ~] $ top 2. tareas de bash en primer y segundo plano Cada línea de comando que ejecutamos en la terminal bash tiene un número de tarea asignado (diferente al PID). Además, estas tareas o jobs pueden ejecutarse en primer o segundo plano, y de hecho pueden pasar de un estado al otro. Una shell está bloqueada cuando un proceso está en primer plano, mientras que si está en segundo plano la terminal está libre y podemos teclear comandos en ella. Recuerda que al ejecutar un comando no recuperamos el prompt hasta que este no termina. En otras palabras, dado una shell de bash, no puedes largar un job hasta que no haya finalizado el anterior. Sin embargo, esto sería desaprovechar el sistema Linux, por lo que puedes ejecutar múltiples jobs al unísono, enviándolos a un segundo plano (background). En bash, ponemos una tarea en segundo plano añadiendo un & al final del comando; el comando se ejecuta mientras el prompt queda libre. Cuando mandas una tarea al segundo plano, bash te indica entre corchetes el número de tarea y a continuación el número del proceso que generó la ejecución del comando. Para recuperar una tarea del segundo al primer plano, se usa fg %N, donde N es el número de la tarea que queremos recuperar. Para vovlerla al segundo plano, deberías suspenderla (CONTROL Z) y entonces digitar bg %N. El programa xterm es un emulador de terminales (para ocasiones donde no se pueden usar directamente los sistemas de ventanas). En este caso vamos a ver que ocurre durante la ejecución del programa, así como probar mover la tarea iniciada entre el primer plano y el background. [usuario@maquina ~] $ xterm CONTROL C [usuario@maquina ~] $ [usuario@maquina ~] $ xterm & [usuario@maquina ~] $ fg %1 [usuario@maquina ~] $ CONTROL Z [usuario@maquina ~] $ bg %1 [usuario@maquina ~] $ fg %1 CONTROL C [usuario@maquina ~] $ Prueba ejecutar nuevamente el programa, suspenderlo, enviarlo al segundo plano y finalmente, recuperarlo en el primero. ¿Cómo lo harías? Otras veces, además de mantener un porceso en el background, puede resultar sumamente útil mantenerlo independiente de la terminal desde la cual fue iniciado. Piensa en un análisis que puede llevar días de cálculo... puedes querer recuperar el prompt de esa terminal (alcanzaría con usar un &), pero también volverlo independiente del entorno gráfico original (que podría dañarse) o incluso independiente de esa sesión de usuario. Esto último es especialmente útil cuando entras a tu máquina Linux desde un PC vía internet o si usas una máquina junto a otros usuarios. El programa screen permite el manejo de terminales virtuales que surgen por la multiplicación de la shell original. Cuando llamas al programa, pasas a estar en una nueva ventana que si te fijas, se identifica por “screen” más un número o nombre. Allí trabajas normalmente y, cuando lo necesites, puedes generar nuevas ventanas para correr otros programas, cambiar de ventana... Lo importante es que todas las ventanas corren sus programas independientemente de las otras y, además, estos programas continuan corriendo aún si la ventana no está visible. Mejor aún, los programas continuan corriendo aún si toda la sesión “screen” es detached de la terminal en la que el usuario trabajaba originalmente. Cuando un programa termina, screen por defecto cierra la ventana que lo contenía y el display salta a la ventana siguiente. Si ninguna permanece abierta, screen finaliza. Si bien existe una descripción muy detallada en man, algunas órdenes más comunes asociadas a screen son: para iniciar una nueva sesión: screen para iniciar una nueva sesión identificándola con un nombre: screen -S nombre_sesión para crear una nueva ventana CONTROL A c para crear una nueva ventana con el nombre del programa que va a ejecutar: screen comando para nombrar la ventana actual: CONTROL A A (título) para ver una lista de las ventanas: CONTROL A “ para ir a otra ventana: CONTROL A 0-9 para detachar la sesión de screen CONTROL A d para reingresar (reattach) a una sesión de screen: screen -r para reingresar a una sesión en una ventana determinada: screen -p nº/nombre para reingresar a una sesión incluso haciendo un log out remoto si es necesario: screen -D -R Intenta iniciar una sesión de screen, generar más de una ventana y probar algunas de las órdenes anteriores. Finalmente, realiza un detach. ¿Qué ocurre si haces ps? 3. señales – prioridad de procesos Las señales son la forma que tienen los procesos de comunicarse entre sí, y el KERNEL de comunicarse con ellos. Existe un número determinado de señales que se pueden enviar a un proceso, y cada una de ellas tiene sobre él una acción distinta: pausarlo, reanudarlo, cancelarlo... Las señales se denotan por SIGnombre, donde nombre es el nombre que se le da a la señal. Además, las señales más usadas tienen un número de señal asociado. Se puede ver información detallada en man signal. Dos de las señales más comunes son: SIGINT (num 2): interrumpe -cancela un programa; es la señal que se le envía a un proceso cuando presionamos CONTROL C en el teclado con un proceso en primer plano. SIGKILL (num 9): “mata” un proceso; los procesos terminan inmediatamente cuando reciben esta señal; sólo debería ser usada en caso de necesitar terminar un proceso que ha dejado de responder y no funciona adecuadamente. El comando kill -señal PID es el que se usa para enviar señales a los procesos. Podemos indicar varios PID para que reciban esa señal en un solo comando separándolos con espacios al final. Son equivalentes: [usuario@maquina ~] # kill -SIGKILL PID [usuario@maquina ~] # kill -9 PID En una misma terminal (sin abrir otra), ejecuta el comando xterm y luego (averiguando su PID), mata el proceso con kill -9. Si bien lo más frecuente es tener varios procesos ejecutándose al unísono en nuestra máquina, no todos ellos son igual de importantes. Por ejemplo, si se desea grabar un CD, este debería ser un proceso más importante que el resto, para asegurarnos que el disco duro envíe los datos a la grabadora a la velocidad suficiente. La idea es indicarle al KERNEL algo así como: “si el procesador no puede con todo, lo último en retrasarse debe ser la grabación del CD”. Para conseguir esto, se ejecuta desde el principio el comando interesado mediante nice, o bien, si ya se está ejecutando, conseguir su PID y usar renice para cambiar su prioridad. Por ejemplo: [usuario@maquina ~] $ nice -n PRIORIDAD COMANDO_proceso [usuario@maquina ~] # renice PRIORIDAD PID_proceso PRIORIDAD es un valor que va desde -20 a +20 (con el signo incluido). -20 es la prioridad más alta que se le puede asignar a un proceso (al contrario de lo intuíble) y, +20 la más baja. Sólo root puede establecer a un proceso una prioridad negativa, los usuarios como máximo pueden poner a un proceso prioridad 0. 4. expresiones regulares y sed Las expresiones regulares son patrones que se utilizan para buscar, sustituir... cadenas de texto. Si bien aquí las explicaremos orientadas a su uso con sed, existen otras implementaciones para su uso con POSIX, Perl... El comando sed (Stream EDitor) es muy útil para hacer modificaciones en ficheros de texto o en flujos de datos. Estas modificaciones pueden ser añadir o borrar una línea, o un conjunto de ellas, buscar y reemplazar patrones, etc. La sintaxis de sed normalmente es: [usuario@maquina ~] $ sed 's/patrón/reemplazo/g' archivo > archivo_reemplazado Esta sintaxis con la opción s permite reemplazar patrones. Para eliminar patrones se puede usar 's/patrón//opción'. Otro dato: sed acepta otro tipo de sintaxis (que puede resultar útil si es necesario “escapar” caracteres): [usuario@maquina ~] $ sed 's:patrón:reemplazo:g' archivo > archivo_reemplazado Para su construcción, las expresiones regulares se separan en átomos, partes menores que serán las que buscaremos y las que deberíamos hacer suficientemente generalizadas. Para ello se utilizan referencias y wildcards. Por ejemplo, para indicar el comienzo de una línea y el final de línea se utilizan como referencias el ∧ y $ respectivamente. Por ejemplo, para añadir texto a continuación de cada línea se usaría: [usuario@maquina ~] $ sed 's/$/texto al final/g' archivo > archivo_reemplazado ¿Qué ocurriría si en el patrón a sustituir el caracter $ fuera parte del mismo? Para aclararle a sed que una wildcard es parte literal del patrón se debe escapar, esto es, se debe escribir la wildcard a continuación de una barra \, por ejemplo, \$. Debido al uso de \ para escapar caracteres de referencia, separar los elementos de la sintaxis con : puede ser menos confuso. Si quieres puedes ver una lista de wildcards para las expresiones regulares en el archivo wildcards.pdf. Sed también acepta “expresiones regulares con formato Perl”. En este lenguaje de programación, las expresiones regulares se construyen como combinaciones de w* (cualquier combinación de letras) y d* (cualquier combinación de dígitos), ambas precedidas por un \ que hace que se interpreten justamente como expresiones y no como un número repetido de w y d. Otra ventaja de este formato, es que permite utilizar un patrón también durante la operación de reemplazo, lo cual se indica con el &. Observa el ejemplo: El comando sed también es útil para la rápida inserción, deleción de líneas. Algunos ejemplos: para insertar una línea en blanco luego de la sexta línea: [usuario@maquina ~] $ sed '6a\\'' archivo para insertar una línea en blanco antes de la séptima línea: [usuario@maquina ~] $ sed '7i\\' archivo borrar las líneas 3 a 5: [usuario@maquina ~] $ sed '3,5D' archivo insertar una última línea en blanco: [usuario@maquina ~] $ sed '$a\\' archivo el símbolo ! es usado para indicar todas las líneas NO especificadas; por ejemplo, para borrar todas las líneas excepto 5 a 7 sería: [usuario@maquina ~] $ sed '5,7!D' archivo A partir del archivo de texto Monica.txt construye otro (llamado Historias), sin usar editores de texto, que hable sobre Sandra en lugar de Mónica. Haz que en Historias exista otra copia del mismo texto pero donde tanto Sandra como Juan estén sustituidos por “NOMBRE” (en una sola línea de comando). Inserta una línea en blanco que separe ambos textos y una última línea en blanco. Prueba realizar el Ejercicio3 de la hoja de ejercicios. 5. awk En su uso más simple, el comando awk permite separar por campos; es similar a cut pero algo más flexible. Su sintaxis es: [usuario@maquina ~] $ awk -F fs '{print $N}' archivo [usuario@maquina ~] $ awk -F fs '{print $N1 “ “ $N2 “ “ ... $Nn}' archivo [usuario@maquina ~] $ awk -F fs '{print $N1 “algo”}' archivo La opción -F es para ingresar el separador de campos (fs). N, N1, N2... Nn indican cuales campos van a ser impresos. Los espacios entre comillas permiten imprimir espacios en blanco que faciliten la visualización de los datos. Entre comillas también se pueden indicar puntos (“.”), tabuladores (“\t”) u otro texto (“algo”). Otra sintaxis posible es: [usuario@maquina ~] $ awk '{FS=”\t”}{OFS=”\t”}{print $N1,$N2,...$Nn}' archivo En este caso, tanto el elemento que actúa como separador de campos en el archivo de entrada (FS), como el que va a servir de separador de campos en la salida (OFS) se indican aparte de los campos requeridos. Intenta realizar el Ejercicio4 de la hoja de ejercicios.