Enunciado de la práctica "Programación de la BASH 1"

Objetivos

Demostrar al mundo que ya somos unos expertos en el desarrollo de scripts de BASH ;-)

Nuestro propio comando ps

¿Alguna vez te has preguntado de donde saca el comando ps la información acerca de los procesos en el sistema? La respuesta es muy sencilla, del directorio /proc.

Entra en el directorio /proc y obsérvalo un momento. Verás muchas cosas pero lo más interesante es que cada directorio /proc/<numero> representa a un proceso donde <numero> es el PID de dicho proceso. Del contenido de los archivos de cada directorio podemos obtener toda la información que necesitamos:

  • /proc/<pid>/cmdline la línea de comandos con la que se ejecutó el programa.
  • /proc/<pid>/cwd es un enlace al directorio actual de trabajo del proceso (para obtener la dirección a la que apunta un enlace simbólico se puede usar el comando readlink <ruta_del_enlace>)
  • /proc/<pid>/status permite obtener
    • El PPID (PID del proceso padre) 
    • UID y GID del proceso. Se muestra por columnas. La primera es el UID/GID real y la segunda el UID/GID efectivo.
    • Estado (state)
    • Número de hilos (Threads)
  • etc. (ver http://linux.die.net/man/5/proc)

Tareas

Te proponemos que realices un script que al menos incluya las siguientes funcionalidades:

1. Listado de procesos

Usando lo aprendido hasta el momento en clase desarrolla el script 'myps' que, si no se especifica opción, muestre una lista de todos los procesos del sistema:

  1. Crea una función para extraer cada unidad de información de un proceso a partir del PID:
    1. Por ejemplo, una función get_cmdline que reciba el PID e imprima la línea de comandos:
      get_cmdline 805
      /usr/bin/kate
    2. O una función get_user que reciba el PID e imprima el nombre de usuario:
      get_user 805
      jmtorres
      Recuerda que /proc/pid/status sólo te da el UID, así que debes buscar en /etc/passwd el nombre de usuario que corresponde a ese UID.
    3. O una función get_cmd que reciba el PID e imprima el directorio actual de trabajo:
      get_cwd 805
      /home/jmtorres
    4. Y así para toda la información que haya que mostrar en estra práctica...
  2. Imprime una tabla con proceso por fila y para cada uno muestra:
    1. PID PPID usuario grupo estado "nº de hilos" "Directorio de trabajo" "Línea de comandos"
    2. Recuerda usar printf o column para que las columnas queden correctamente alienadas.
  3. Maneja adecuadamente los errores.
    1. Si el script no se ejecuta como root, es posible que no tengamos permisos para abrir alguno de los archivos y, por tanto, para recuperar cierta información. Evita mensajes de error en ese caso, detectando la condición antes de provocarla y usando las comillas adecuadamente para devolver y usar cadenas vacías en las columnas.
    2. En caso de error grave muestra un mensaje y sal con código de salida distinto de 0. Recuerda la función error_exit de ejercicios anteriores y, si lo crees conveniente, reúsala o haz la tuya propia.
    3. Trata como un error que el usuario emplee opciones no soportadas
    4. Haz lo mismo con las otras posibles condiciones de error que se te ocurran ¿has probado a invocar tu programa opciones absurdas a ver si lo haces fallar?
  4. Recuerda facilitar la lectura de tu código:
    1. Usa comentarios en los elementos más complejos del programa para que te sea más sencillo entenderlo cuando haya pasado un tiempo y no te acuerdes
    2. Usa funciones para compartimentar el programa, así como variables y constantes (variables en mayúsculas) que hagan tu código más legible.
  5. Incluye código para procesar la línea de comandos.
    1. Se debe mostrar ayuda sobre el uso si el usuario emplea la opción -h o --help.
    2. Se debe indicar el error y mostrar ayuda sobre el uso si el usuario emplea uno opción no soportada
  6. Ojo con la sustitución de variables y las comillas. En caso de problemas piensa en cómo quedarían las sentencias si las variables no valieran nada ¿tendría sentido para BASH el comando a ejecutar?

2. Buscar un proceso por el nombre de comando

  1. Crea una función a la que pasar la línea de comandos del proceso (el contenido de /proc/pid/cmdline) y que prima sólo el nombre del comando, sin ruta ni opciones. Para eso recuerda el comando basename.
  2. Añade la opción '-n comando' de tal forma que sólo se muestren aquellos procesos que ejecuten el programa del comando 'comando'. Recuerda que en el paso anterior escribiste una función que te será muy útil.
  3. Añade la opción '-p pid' de tal forma que sólo muestre el proceso con el PID indicado.
  4. Ambas opciones son excluyentes. Si se indican las dos hay, que indicar el error al usuario.
  5. Si se usan las opciones -n o -p, después de imprimir la línea de información de cada proceso hay que mostrar información adicional antes de imprimir la siguiente línea: estadísticas de operaciones de entrada/salida extraídas de /proc/pid/io, los límites configurados para el proceso (/proc/pid/limits) y cualquier otra cosa que te llame la atención...

Evaluación

  1. El script realizado se subirá en cualquier momento a esta tarea, desde la fecha actual hasta el día de la próxima sesión práctica.
  2. Esta actividad se calificará por la correcta realización de los cambios al script que los profesores propongan durante la próxima sesión práctica (la de la semana del 24 al 28 de noviembre). Por lo tanto es importante llegar a la misma con esta actividad ya hecha.
  3. El trabajo bien hecho al desarrollar esta actividad y el grado de ajuste a los requisitos establecidos, modulará la nota final de la actividad siempre que los profesores la valores como correcta, por la realización de los cambios propuestos comentados en el punto anterior.