Memoria de las prácticas de la asignatura Sistemas Operativos. Andrés Reyes Torres, 2004. http://www.uco.es/~i22retoa i22retoa@uco.es Práctica 1. Scripts para bash. • Ejercicio 1 Crea un guión que ejecute las siguientes tareas: * Visualice una cadena en la pantalla en la que aparezca el autor del shell script. * Muestre el directorio actual. * Muestre la fecha y la hora del sistema. * Muestre los usuarios conectados actualmente a la máquina. Usa comentarios dentro del fichero creado, explicando antes de cada orden su utilidad. #!/bin/bash # Práctica 1 # Ejercicio 1 autor="Andrés Reyes Torres" # muestra la cadena $autor echo $autor # comando 'pwd' (ver ruta actual) pwd # comando 'date' (fecha del sistema) date +%d/%m/%y # comando 'date' (hora del sistema) date +%H:%M:%S # comando 'w' (usuarios conectados) w exit 0 • Ejercicio 2 Ejecuta el guión anterior y almacena su salida en un fichero que se llame salida1.txt (utiliza redireccionamiento de comandos). #!/bin/bash # Practica 1 # Ejercicio 2 # Andris Reyes Torres ./script1 >> salida1.txt • Ejercicio 3 Realiza una macro que realice una copia del fichero anterior cuyo nombre sea salida2.txt y añada al final el contenido ordenado, alfabéticamente por la primera columna, del fichero salida1.txt al fichero salida2.txt. #!/bin/bash # Práctica 1 # Ejercicio 3 # Andrés Reyes Torres cp salida1.txt salida2.txt sort salida1.txt >> salida2.txt • Ejercicio 4 Crea un archivo de guión que realice al ejecutarse la siguiente estructura de directorios: Comprobar el resultado de ejecutar nuevamente la macro. #!/bin/bash # Práctica 1 # Ejercicio 4 # Andrés Reyes Torres mkdir mkdir mkdir mkdir mkdir mkdir $HOME/macros $HOME/macros/ficheros $HOME/macros/otras $HOME/macros/ficheros/practica5 $HOME/macros/otras/practica5 $HOME/macros/otras/util exit 0 • Ejercicio 5 Realizar una macro que reciba como primer parámetro el camino completo de un directorio de la estructura anterior al que se realizará una copia del fichero salida1.txt. La macro deberá ejecutarse desde tu directorio HOME. #!/bin/bash # Práctica 1 # Ejercicio 5 # Andrés Reyes Torres cp $HOME/practicas/segundo/ssoo/prac1/salida1.txt $1/salida1.txt exit 0 • Ejercicio 6 Realizar una macro que reciba como primer parámetro el nombre de un directorio y como segundo parámetro el nombre de un fichero. La macro deberá realizar una copia del fichero salida1.txt del directorio HOME al directorio pasado como primer parámetro y con el nombre indicado por el segundo parámetro. #!/bin/bash # Práctica 1 # Ejercicio 6 cp $HOME/practicas/segundo/ssoo/prac1/salida1.txt $1/$2 exit 0 • Ejercicio 7 Realizar una macro que pida al usuario por teclado el nombre de un fichero para posteriormente realizar una búsqueda de dicho fichero por todo el árbol de directorios de tu cuenta. Si se encuentra alguna copia del fichero deberá salir su camino en la pantalla. La macro deberá llamarse busca. #!/bin/bash # Práctica 1 # Ejercicio 7 # Andrés Reyes Torres echo read find exit • -n "Nombre del fichero:" fichero $HOME -name $fichero 0 Ejercicio 8 La orden ps -af visualiza en la pantalla información acerca de todos los procesos que están ejecutando actualmente en la máquina todos los usuarios. Escribir una macro que visualice únicamente los procesos asociados a un determinado usuario pasado como parámetro. #!/bin/bash # Practica 1 # Ejercicio 8 # Andres Reyes Torres ps -u $1 # otra forma de hacerlo: # ps -af | grep $1 • Ejercicio 9 Modificar la macro anterior para que la propia macro solicite la entrada desde el teclado del nombre de usuario del cual buscar sus procesos e indique el número de dichos procesos que actualmente se están ejecutando en la máquina. #!/bin/bash # Practica 1 # Ejercicio 9 # Andres Reyes Torres echo -n "Usuario:" read usuario ps -u $usuario # Se resta 1, que seria la primera linea de salida de ps # si se elige el propio usuario que ejecuta este script, # la salida sera mas grande que el numero de procesos # ejecutandose actualmente, ya que se cuentan los propios # procesos que se llaman desde este script. echo "$usuario esta ejecutando $(($(ps -u $usuario | wc -l)-1)) procesos" exit 0 Práctica 2. Scripts para bash (II). • Ejercicio 1 Desarrolle un script que reciba dos argumentos por la línea de órdenes, el nombre de un fichero y un número que representa el número de línea del fichero que el script debe enviar a su salida estándar. #!/bin/bash # Práctica 2 # Ejercicio 1 # Andrés Reyes Torres head -n$2 $1 | tail -1 exit 0 • Ejercicio 2 El fichero /etc/passwd contiene información administrativa sobre los usuarios del sistema; en particular contiene los nombres de los usuarios dentro del sistema y en la vida real. Desarrollar un programa que muestre en pantalla un listado de los nombres, de usuario y reales, existentes en ese fichero. #!/bin/bash # Práctica 2 # Ejercicio 2 # Andrés Reyes Torres cut -d: -f1,5 /etc/passwd • Ejercicio 3 Desarrollar un shell script que reciba dos parámetros, un directorio y una cadena de caracteres a buscar en todos los ficheros regulares que cuelguen debajo del directorio especificado. #!/bin/bash # Práctica 2 # Ejercicio 3 # Andrés Reyes Torres # hace una busqueda, a partir de la ruta especificada, # de la cadena pasada como segundo parametro # otra forma posible es: # find $1 -type f -exec grep -n $2 {} \; find $1 -type f -print | xargs grep -ni $2 • Ejercicio 4 Definir un alias para la orden anterior de forma que busque en todo el árbol de directorios la cadena que se especifique. Utilice el alias definido para crear otro que muestre el número de ficheros en los que se menciona su nombre de usuario y el nombre de los ficheros. #!/bin/bash # Práctica 2 # Ejercicio 4 # Andrés Reyes Torres # para cargar estos alias en el sistema, ejecutar: # source script4 alias rastrea="$HOME/practicas/segundo/ssoo/prac2/script4-1" alias dondeestoy="$HOME/practicas/segundo/ssoo/prac2/script4-2" ------#!/bin/bash # Práctica 2 # Ejercicio 4-1 # Andrés Reyes Torres echo -n "Cadena a buscar:" read cadena # sustituir ./ por / para hacer la búsqueda desde el raíz $HOME/practicas/segundo/ssoo/prac2/script3 ./ $cadena exit 0 ------#!/bin/bash # Práctica 2 # Ejercicio 4-1 # Andrés Reyes Torres # sustituir ./ por / para hacer la búsqueda desde el raíz RUTA="./" $HOME/practicas/segundo/ssoo/prac2/script3 $RUTA $LOGNAME num=$($HOME/practicas/segundo/ssoo/prac2/script3 $RUTA $LOGNAME | wc -l) echo "Número de ficheros en los que se te menciona: $num" exit 0 • Ejercicio 5 Cree su propia versión de la orden administrativa adduser, que permite añadir un nuevo usuario al sistema. Este proceso consiste en crear una nueva entrada en su fichero passwd y generar un subdirectorio con el nombre del nuevo usuario. #!/bin/bash # Practica 2 # Ejercicio 5 # Andres Reyes Torres echo read echo read echo read -n "Nombre de usuario:" login -n "Nombre real:" nombre -n "Contraseqa:" pass rutahome="$HOME/practicas/segundo/ssoo/prac2/$login" # creo el directorio mkdir $login # anado la entrada al fichero passwd echo "$login:$pass:1001:1001:$nombre:$rutahome:/bin/bash" >> passwd exit 0 • Ejercicio 6 Desarrolle un alias que permita eliminar un usuario y su directorio asociado de su fichero de contraseñas. #!/bin/bash # Practica 2 # Ejercicio 6 # Andrés Reyes Torres # source script6 para cargar el alias alias borrauser="$HOME/practicas/segundo/ssoo/prac2/script6-1" ------#!/bin/bash # Practica 2 # Ejercicio 6 # Andrés Reyes Torres echo -n "Usuario a borrar:" read USUARIO RUTA="$HOME/practicas/segundo/ssoo/prac2" # borro el directorio asociado rm -rf $RUTA/$USUARIO # volcamos todo el fichero menos la línea del usuario # con la ayuda de un fichero temporal cat $RUTA/passwd > $RUTA/.temp cat $RUTA/.temp | grep -v $USUARIO > $RUTA/passwd rm -f $RUTA/.temp exit 0 • Ejercicio 7 Desarrolle un shell script, de nombre matador, que reciba como parámetro el nombre de un proceso en ejecución y lo elimine, mostrando además un mensaje como: El proceso nombre_proceso con PID PID_proceso_eliminado ha sido eliminado #!/bin/bash # Practica 2 # Ejercicio 7 # Andréss Reyes Torres # Script que elmina el proceso nombrado por $1 # comprueba el argumento if [ -z $1 ]; then echo "uso: matador proceso" echo " proceso: nombre del proceso a matar." exit 1 fi # recogemos el PID del proceso IDPROC=$(ps | grep $1 | cut -f2,3 -d' ') kill -9 $IDPROC echo "El proceso $1 con PID $IDPROC ha sido eliminado." exit 0 • Ejercicio 8 Desarrolle el script invierteLinea que recibe un número cualquiera de palabras por la línea de órdenes y las envía en una única línea a la salida estándar en orden inverso al que aparecían en la llamada. Ejemplo: bash$ invierteLinea que sirve como interfaz con el el con interfaz como sirve que bash$ #!/bin/bash # Practica 2 # Ejercicio 8 # Andrés Reyes Torres # Este script muestra sus parámetros en orden inverso. # número de parámetros que se le pasa al script num=$# # guardamos los parámetros en un temporal for i in $*; do echo $1 >> .temp shift done # leemos el temporal desde la última línea a la primera while [ $num -gt 0 ]; do txt=$( head -n$num .temp | tail -1 ) echo -n "$txt " let "num=num-1" done # borramos el temporal rm -f .temp • Ejercicio 9 Empleando el script anterior, escriba otro de nombre invertir, que recibe como parámetro el nombre de un fichero cuyas palabras serán enviadas a la salida estándar en orden inverso, empezando por la última línea, tal y como se muestra en el siguiente ejemplo: bash$ cat fichero El intérprete de órdenes es la parte del sistema operativo que sirve como interfaz con el usuario también puede ser considerado como un poderoso lenguaje de programación cuyos programas se denominan shell scripts bash$ invertir fichero scripts shell denominan se programas cuyos programación de lenguaje poderoso un como considerado ser puede también usuario el con interfaz como sirve que operativo sistema del parte la es órdenes de interprete El bash$ #!/bin/bash # Práctica 2 # Ejercicio 9 # Andrés Reyes Torres NUMLINEAS=$(wc -l $1) while [ $NUMLINEAS -gt 0 ]; do LINEA=$(head -n$NUMLINEAS $1 | tail -1) $HOME/practicas/segundo/ssoo/prac2/invierteLinea $LINEA let "NUMLINEAS=NUMLINEAS-1" echo done exit 0 • Ejercicio 10 Un mecanismo para evitar el borrado involuntario de ficheros es implementar una papelera, parecida a la que existe en el S.O. Windows. Para ello, crearemos un script llamado borra que, en lugar de borrar los ficheros, los mueve a un directorio oculto ~/.papelera previa compresión de estos (para evitar que ocupen demasiado espacio. A continuación, hacemos que el alias para la orden borra sea rm. Así, cuando borremos un fichero, se estará transfiriendo a la papelera en lugar de borrarse: 1. Implemente el script anterior y construya el alias para disponer de la papelera activa 2. Implemente un script para la gestión de la papelera, que indique los ficheros existentes en ella y permita el borrado y/o recuperación de ficheros. 3. Modifique su fichero de arranque en el sistema para que, en cada sesión, se arranque el script de gestión de la papelera, lo que le recordará que tiene que borrar la información almacenada en ésta. #!/bin/bash # Practica 2 # Ejercicio 10 # Andrés Reyes Torres # Este script implementa una papelera virtual donde se guardan los archivos # borrados para su posterior recuperacion. # Para sustituir el comando rm por este script, añadir a .bashrc: # # alias borra="$HOME/practicas/segundo/ssoo/prac2/borra $1 $2" # alias rm="$HOME/practicas/segundo/ssoo/prac2/borra -d $1" # echo "Contenido de la papelera:" # $HOME/practicas/segundo/ssoo/prac2/borra -l # echo "Recuerda mantenerla limpia." PAPELERA="$HOME/.papelera" # función que comprueba la existencia de un fichero function existe() { if [ ! -e "$1" ]; then return 1 else return 0 fi } # si no existe la papelera, la creamos if [ ! -d $PAPELERA ]; then mkdir $PAPELERA fi # ayuda if [ $# -eq 0 ]; then echo "uso: borra -[drcl] fichero" echo " d mueve el fichero a la papelera de reciclaje." echo " r restaura el fichero a la ruta actual." echo " c borra el contenido de la papelera." echo " l lista el contenido de la papelera." echo "Los ficheros colocados en la papelera son comprimidos con gzip." exit 0 fi #proceso los parámetros case $1 in # si se va a borra un fichero -d) if existe $2; then mv $2 $PAPELERA gzip $PAPELERA/$2 else echo "$2 no existe." exit 1 fi ;; # si se va a recuperar un fichero de la papelera -r) if existe "$PAPELERA/$2.gz"; then gzip -d $PAPELERA/$2.gz mv $PAPELERA/$2 ./ else echo "$2 no existe." exit 1 fi ;; # si se quiere listar el contenido de la papelra -l) ls -la $PAPELERA ;; esac exit 0 # borra el contenido de la papelera -c) rm -f $PAPELERA/* ;; Práctica 3. Scripts para bash (III). En esta práctica, todo shell script desarrollado debe llevar una comprobación de los argumentos que espera que se le pasen como parámetros. Entre ellos, debe permitir la opción -h, que supone mostrar una ayuda que contenga la sintaxis de la llamada al script, y una explicación del significado de los parámetros que espera. • Ejercicio 1 Realizar un script de nombre ayuda que pueda recibir como parámetro la opción -h o el nombre de un fichero. Si recibe el nombre de un fichero, muestra si existe o no y de que modo es accesible. Si recibe como parámetro -h, muestra por pantalla un menú de ayuda. A partir de este ejercicio, todos los shell scripts que se generen deberán contar con una parte de comprobación de argumentos y ayuda muy similar a la realizada en este ejercicio. #!/bin/bash # Práctica 3 # Ejercicio 1 # Andrés Reyes Torres if [ $# -eq 0 ]; then echo "Número de parámetros incorrecto." echo "Pruebe: ./ayuda -h" exit 1 fi case $1 in -h) *) echo echo echo exit ;; "uso: ayuda [-h] fichero" " -h muestra esta ayuda" " fichero nombre de fichero a tratar" 0 if [ ! -e $1 ]; then echo "$1 no existe." exit 1 else if [ -r $1 ]; then echo "Tienes permiso de lectura sobre $1" fi if [ -w $1 ]; then echo "Tienes permiso de escritura sobre $1" fi if [ -x $1 ]; then echo "Tienes permiso de ejecución sobre $1" fi if [ -f $1 ]; then echo "$1 es un fichero regular." fi if [ -d $1 ]; then echo "$1 es un directorio." fi ;; esac • fi Ejercicio 2 Crear un shell script de nombre crear que reciba como parámetro el nombre de un fichero. Comprobará si existe y en caso negativo lo creará, permitiendo que el usuario introduzca texto en él. Ampliar el script anterior para que opere del mismo modo pero permitiendo como parámetros un número cualquiera de nombres de fichero. #!/bin/bash # Práctica 3 # Ejercicio 2 # Andrés Reyes Torres if [ $# -eq 0 ]; then echo "Número de parámetros insuficiente." echo "Pruebe con ./crear -h" exit 1 fi case $1 in -h) *) esac echo echo echo echo ;; "uso: crear [-h] [fichero]" " -h muestra esta ayuda" "[fichero] nombre del fichero a crear." " No es necesario que exista." if [ ! -e $1 ]; then echo > $1 fi CADENA="z" echo "Introduzca texto para $1 (cadena vacia termina):" while [ -n "$CADENA" ]; do read CADENA echo "$CADENA" >> $1 done ;; exit 0 ------Ejercicio 1 ampliado: #!/bin/bash # Práctica 3 # Ejercicio 1 # Andrés Reyes Torres if [ $# -eq 0 ]; then echo "Número de parámetros incorrecto." echo "Pruebe: ./ayuda -h" exit 1 fi case $1 in -h) *) echo echo echo exit ;; "uso: ayuda [-h] fichero1 fichero2 ... ficheroN" " -h muestra esta ayuda" " fichero nombre de fichero a tratar" 0 for each in $*; do if [ ! -e $1 ]; then echo "$1 no existe." else if [ -r $1 ]; then echo "Tienes permiso de lectura sobre $1" fi if [ -w $1 ]; then echo "Tienes permiso de escritura sobre $1" fi if [ -x $1 ]; then echo "Tienes permiso de ejecución sobre $1" fi if [ -f $1 ]; then echo "$1 es un fichero regular." fi fi shift done ;; esac • if [ -d $1 ]; then echo "$1 es un directorio." fi Ejercicio 3 Ahora se desea tener un script de nombre anyadir, que puede recibir como parámetros uno o dos nombres de fichero. Si recibe uno, permite al usuario añadir texto a ese fichero de modo interactivo. Si son dos, añade al segundo el contenido del primero. #!/bin/bash # Práctica 3 # Ejercicio 3 # Andrés Reyes Torres, 2003 if [ $# -eq 0 ]; then echo "Número de parámetros incorrecto." echo "Prueba con: anyadir -h " exit 0 fi case $1 in -h) echo "anyadir [fichero1] [fichero2]" echo "Si se indica un solo fichero, lee texto para introducirlo en el." echo "Si se introducen dos ficheros, concatena el primero al segundo." exit 0 ;; *) terminar):" if [ $# -eq 1 ]; then echo "Eescriba el texto para $1 (cadena vacía para echo > $1 CADENA="z" while [ -n "$CADENA" ]; do read CADENA echo "$CADENA" >> $1 done else esac • cat $1 >> $2 fi ;; Ejercicio 4 Se pide realizar el script de nombre datos que responde a la siguiente sintaxis de llamada: datos fich_destino Este script pedirá el nombre, primer y segundo apellido, DNI, edad y fecha de nacimiento, añadiendo esta información al fichero fich_destino con el siguiente formato: DNI|apellido1|apellido2|nombre|edad|fecha_nacimiento Realizar la petición de los datos del modo más compacto posible, es decir, utilizando el mínimo número de órdenes que se le ocurra. #!/bin/bash # Práctica 3 # Ejercicio 4 # Andrés Reyes Torres, 2003 if [ $# -eq 0 ]; then echo "Número de argumentos erróneo." echo "Pruebe con: datos -h" exit 1 fi case $1 in -h) los datos." *) >> $1 esac echo "datos [fichero]" echo "fichero: nombre del fichero donde se guardarán exit 0 ;; echo read echo read echo read echo read echo ;; -n "Introduzca nombre y apellidos:" NOMBRE APELLIDO1 APELLIDO2 -n "Introduzca DNI:" DNI -n "Introduzca fecha de nacimiento (dd/mm/aa):" FECNAC -n "Introduzca la edad:" EDAD "$DNI|$APELLIDO1|$APELLIDO2|$NOMBRE|$EDAD|$FECNAC" • Ejercicio 5 Desarrollar un shell script ordena_parametros que envía ordenados a la salida estándar los parámetros que recibe por la línea de órdenes. El número mínimo de parámetros a procesar por la shell script será de 2, no estando limitando el número máximo. Si fuera invocada con menos parámetros mostrará en la salida de errores estándar un mensaje en el que se indique la forma de invocarla. Ejemplo: bash$ ordena_parametros ordena estas palabras con todo adios adios con estas ordena palabras todo bash$ ordena_parametros palabra Error. Numero de parametros insuficiente. Sintaxis: ordena_parametros param1 param2 ... paramN bash$ #!/bin/bash # Práctica 3 # Ejercicio 5 # Andrés Reyes Torres, 2003 case $1 in -h) esac echo "ordena_parametros [param1] [param2] ... [paramN]" echo "ordena los parámetros pasados." exit 1 ;; if [ $# -lt 2 ]; then echo "Número de parámetros incorrecto." echo "Pruebe con: ordena_parametros -h" exit 1 fi for each in $*; do echo $1 >> .temp shift done sort .temp rm .temp • Ejercicio 6 Implemente el script generador, que recibe 2 argumentos por su línea de órdenes. La función de este script consiste en enviar a su salida estándar las líneas del fichero que recibe como segundo argumento precedidas por la cadena de caracteres que recibe como primer argumento. Ejemplo: bash$ cat fichero glicérido dimensional ciclo ángulo bash$ generador tri fichero triglicérido tridimensional triciclo triángulo bash$ #!/bin/bash # Práctica 3 # Ejercicio 6 # Andrés Reyes Torres case $1 in -h) echo "generador [cadena] [fichero]" echo "Genera como salida cada línea de fichero precedida por cadena." esac exit 1 ;; if [ $# -lt 2 ]; then echo "Número de argumentos incorrecto." echo "Pruebe con: generador -h" exit 1 fi NUMLINEAS=$(cat $2 | wc -l) I=1 while [ $NUMLINEAS -ge $I ]; do TEXTO=$(head -n$I $2 | tail -1) echo "$1$TEXTO" let "I=I+1" done exit 0 EOF Editado con AbiWord. Formateado a PDF gracias a ps2pdf. (C) Andrés Reyes Torres, 2004