PRÁCTICAS DE SISTEMAS OPERATIVOS I

CUARTA SESIÓN


  1. Palabras previas

    Esta sesión tiene cierta importancia porque en ella vamos fijar nomenclatura y conceptos. Hasta ahora hemos usado ciertas palabras carentes de rigor para facilitar la comprensión y porque todavía no habíamos aprendido los conceptos técnicos necesarios. No se trata en este caso, pues, de eufemismos (centro penitenciario en lugar de cárcel, comisión evaluadora en lugar de tribunal, proceso de enseñanza-aprendizaje en lugar de docencia, etc.) sino de algo más inocuo y práctico.
  2. Procesos

    El primer concepto que debemos aclarar es el de proceso y cuál es su diferencia con el de programa. UNIX fue, desde su comienzo, un sistema operativo multitarea y multiusuario. Lo segundo significa que pueden convivir y trabajar a la vez en el sistema varios usuarios, como podéis comprobar en el trabajo diario en el servidor.

    Para que un sistema sea multiusuario, es imprescindible que sea capaz de ejecutar varios programas a la vez, es decir, que sea multitarea. Los primeros sistemas operativos para ordenadores personales no eran multitarea y, por consiguiente, eran monousuario.

    Por consiguiente, en nuestro UNIX debe haber muchos programas ejecutándose a la vez. Cada programa que se encuentre en ejecución se denomina proceso. El concepto de programa es estático; el de proceso, dinámico. Si cinco personas estuvieran ejecutando un ls en estos momentos, habría cinco procesos y un único programa.

    Pero llega el momento de abandonar la teoría y movernos a la práctica. Para ver un listado de procesos, usamos la orden ps (process status):
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ps
       PID TTY         TIME CMD
      3991 pts/1       0:00 bash
      4000 pts/1       0:00 ps
    
    La verdad es que el listado no es nada emocionante... Aparecen solamente dos procesos, un tal bash (luego veremos que en realidad es femenino y debemos decir una tal bash) y el propio ps, que sale en su misma foto.

    Todos los procesos tienen un número identificador único, que se denomina PID. Aparece en la primera columna del la orden ps. Lo usaremos para poder actuar sobre el proceso. La segunda columna nos da el terminal. La tercera columna nos muestra el tiempo de CPU o tiempo de trabajo útil que la CPU ha dedicado al proceso y la cuarta columna es el nombre de la orden.

    Si queremos ver más procesos y más información, debemos añadir alguna opción a la orden. La mala noticia es que estos argumentos no suelen ser muy estándares entre UNIXes diferentes. Demos un par de ellos como referencia para Solaris y dejemos el resto para que lo podáis consultar en la página de manual, llegado el caso.

    Para mostrar todos nuestros procesos, o los de otros usuarios, os recomendamos las opciones -fcu, como en este ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ps -fcu gyermo
         UID   PID  PPID  CLS PRI    STIME TTY         TIME CMD
      gyermo  3989  3986   TS  59 18:12:42 ?           0:00 /usr/lib/ssh/sshd
      gyermo  3991  3989   TS  49 18:12:42 pts/1       0:00 bash
      gyermo  7188  3991   TS  49 18:27:21 pts/1       0:00 ps -fcu gyermo
    
    Vemos que, con estas opciones, aparecen las columnas adicionales de UID (usuario que ejecuta el proceso), PPID (identificador del proceso padre del proceso), CLS (clase de proceso; TS=tiempo compartido), PRI (prioridad del proceso) y STIME (hora a la que fue lanzado).

    Si lo que queréis es un listado general, con todos los procesos del sistema, usad las opciones -efc. Podéis combinar estas órdenes con lo ya aprendido. Por ejemplo, para saber cuántos procesos hay en ejecución en el sistema, podemos poner:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $((`ps -efc | wc | cut -c 1-8`-1))
    43
    
    Evidentemente, no es un cálculo exacto, puesto que el propio ps, e incluso wc y cut, pueden interferir, como procesos que son, en el resultado. Es similar, salvando las distancias, al conocido efecto de la mecánica cuántica en que, para poder medir algo, el observador altera sin remedio el resultado de su medida.

    Otra orden muy interesante es la orden top. Al invocarla también se nos da información de los procesos, pero es dinámica y, además ordena los procesos por consumo de CPU.
    load averages:  0.07,  0.10,  0.10                                18:40:48
    38 processes:  37 sleeping, 1 on cpu
    CPU states: 96.4% idle,  0.0% user,  3.6% kernel,  0.0% iowait,  0.0% swap
    Memory: 2048M real, 1511M free, 140M swap in use, 5429M swap free
    
       PID USERNAME LWP PRI NICE  SIZE   RES STATE    TIME    CPU COMMAND
      9317 gyermo     1  59    0 4312K 2456K cpu      0:00  0.22% top
       261 root       1 100  -20 2520K 1080K sleep   15:47  0.01% xntpd
       239 daemon     4  59    0   81M   53M sleep   12:53  0.01% nfsmapid
      3989 gyermo     1  59    0 8608K 2736K sleep    0:00  0.01% sshd
         7 root      12  59    0 9312K 3856K sleep    2:30  0.00% svc.startd
      3991 gyermo     1  59    0 3152K 2584K sleep    0:00  0.00% bash
       427 root       2  59    0 5472K 2560K sleep   28.0H  0.00% bacula-fd
       364 root       1   2   19 1576K 1048K sleep  255:15  0.00% pandora_agent
       115 daemon     3  59    0 4816K 2144K sleep   21:10  0.00% kcfd
       121 root      40  59    0   11M 6544K sleep   12:42  0.00% nscd
         1 root       1  59    0 2576K  896K sleep    8:02  0.00% init
       358 root       2  59    0 2296K 1432K sleep    7:46  0.00% apcupsd
         9 root      19  59    0   10M 3976K sleep    5:28  0.00% svc.configd
       575 root       1  59    0    0K    0K sleep    3:01  0.00% snmpd
       238 root      16  59    0   15M 5448K sleep    2:08  0.00% fmd
    [[Para salir, pulsad la tecla Q]]
    
    Esta orden nos da mucha información adicional, de la que vamos a destacar: LWP (subprocesos o hilos del proceso), SIZE (tamaño total de la memoria del proceso), RES (tamaño de la memoria del proceso que está realmente en RAM), STATE (estado del proceso) y CPU (porcentaje de CPU usado por el proceso en estos momentos).

    Al ser agosto, el servidor está alejado del bullicio de los meses de clase y el proceso que más le tiene ocupado es el propio top. Con eso, está todo dicho (0.22% de CPU).

    Es top una orden muy usada por los administradores de sistemas. Si el ordenador va muy lento, puede que sea porque algún proceso se ha quedado colgado y consume mucha CPU o mucha memoria. En tal caso, solamente tiene que localizarlo con top y eliminarlo.
  3. La shell

    Llega el momento de aclarar el segundo concepto que, hasta ahora, se ha usado de un modo confuso y, de paso, resolver quién es el misterioso proceso que aparece en los listados con el nombre de bash.

    En sesiones anteriores, siempre que se describía una orden o un comportamiento del sistema, se han usado frases como: si el ordenador se encuentra con una expresión regular, la sustituye por las rutas de los ficheros que casen con ella. En realidad el ordenador como tal, no hace nada. Los que hacen algo son los programas/procesos que hay en él. Y uno de los procesos más importante en estas sesiones de prácticas es la shell.

    Cuando establecéis una conexión con el servidor o cuando, en vuestro Linux, abrís un terminal, automáticamente se lanza un proceso, vuestra shell. Este proceso se encarga de:
    La shell
    Luego, en la mayor parte de sitios donde escribimos el ordenador, deberíamos haber escrito la shell. Existes muchas shells diferentes. Vosotros estáis usando una de las más completas: bash (Bourne again shell).
  4. Procesos en segundo plano

    De poco sirve que nuestro sistema sea multitarea, si no podemos fácilmente aprovecharnos de ello. El primer contacto con la multitarea lo podemos tener enviando procesos a segundo plano. Consiste esto en lanzar el proceso pero recuperar el control inmediatamente, sin esperar a que el proceso acabe (comportamiento por defecto). Como la mayor parte de órdenes que podéis ejecutar no tardan mucho en dar el resultado, es difícil notar las diferencias entre enviar un proceso a segundo plano o no. Es por ello que usaremos una orden que no hace nada: sleep. La probamos:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 5
        [[...transcurridos 5 segundos...]]
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    
    Esta orden la hemos lanzado en primer plano. La shell no nos va a devolver el control hasta que la orden acabe. Notad la diferencia con la ejecución siguiente:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 10 &
    [1]     21165
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ps      
       PID TTY         TIME CMD
     19034 pts/1       0:00 ksh
     21166 pts/1       0:00 ps
     21165 pts/1       0:00 sleep
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    [1] +  Done                    sleep 20 &
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    
    Al lanzar un proceso en segundo plano, el proceso comienza a ejecutarse inmediatamente y, simultáneamente, la shell imprime el número de proceso de segundo plano que tiene entre corchetes y su PID, y nos devuelve el control para que podamos seguir trabajando. En el ejemplo, hemos dado la orden ps para observar el proceso de segundo plano y ver que el PID coincide. Transcurridos los 10 segundos, el proceso se muere (acaba) y la shell nos informa de ello a la primera opción que tiene.

    Podemos lanzar a segundo plano tantos procesos como como queramos:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 60 &
    [1]     23285
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 70 &
    [2]     23286
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 80 &
    [3]     23287
    
    En la variable de entorno $! nos aparece el PID del último proceso lanzado, por si nos resulta de interés:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $!
    23287
    
    En cualquier momento, se puede preguntar por los procesos que tenemos en segundo plano con la orden jobs:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs
    [3] +  Running                 sleep 80 &
    [2] -  Running                 sleep 70 &
    [1]    Running                 sleep 60 &
    
    Si nos interesa conocer los PIDs de los procesos, disponemos de la opción -l de la orden jobs.

    Se puede matar (cancelar) cualquier proceso con la orden kill. Para referirnos a un proceso de segundo plano, anteponermos a su número de segundo plano el carácter de porcentaje:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ kill %2
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    [2]-  Terminated              sleep 70
    <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs
    [1]-  Running                 sleep 60 &
    [3]+  Running                 sleep 80 &
    
    Podemos, también, traer a primer plano un proceso de segundo plano, pero en ese caso, perdemos el control...
    <gyermo@ENCINA>/usuarios/profes/gyermo$ fg %3
    sleep 80
        [[...pasado un rato...]]
    [1]-  Done                    sleep 60
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    
    Por otro lado, a un proceso de primer plano, como hemos ya visto, se le puede matar con CTRL-C. Pero si en lugar de CTRL-C pulsamos CTRL-Z, podemos también recuperar el control y el proceso no muere. Solamente se queda parado:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 60 
    [[Pulsad aquí CTRL-Z]]
    [1]+  Stopped                 sleep 60
    <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs
    [1]+  Stopped                 sleep 60
    <gyermo@ENCINA>/usuarios/profes/gyermo$ 
    
    A los procesos parados se les puede rearrancar, bien en primer plano con la orden fg, bien en segundo plano con la orden bg:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs
    [1]+  Stopped                 sleep 60
    <gyermo@ENCINA>/usuarios/profes/gyermo$ bg %1
    [1]+ sleep 60 &
    <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs
    [1]+  Running                 sleep 60 &
    
    ¿Qué ocurre con los procesos de segundo plano si nos desconectamos (o sea, si la shell se muere)? Pues lo normal es que mueran con ella. Hay veces, sin embargo, en que no nos interesa que algún proceso que hemos lanzado (imaginad que es un cálculo complicado que tarda varios días) muera al desconectarnos. Para lograrlo se usa la orden nohup (No hang up):
    nohup orden_que_queremos_que_no_muera &
    
    En cuanto a la orden kill, en realidad sirve para enviar lo que se denominan señales. Trataremos del asunto más adelante en estas prácticas.

    En ocasiones deseamos lanzar a segundo plano una secuencia de órdenes, es decir, una serie de órdenes que queremos que se ejecuten una detrás de otra, pero en segundo plano. Para ello, nos podemos ayudar del punto y coma (;). La shell lo utiliza para separar órdenes que tecleemos en una misma línea. Por ejemplo, la siguiente línea hace que aparezcan las dos palabras con un intervalo de 5 segundos entre ellas:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo Hola... ; sleep 5 ; echo ...caracola
    Hola...
    [[Transcurridos cinco segundos...]]
    ...caracola
    
    Para lograr lo mismo, pero en segundo plano, se os puede ocurrir añadir un ampersand al final, pero esto no va a funcionar. El ampersand solo afectaría a la última orden, no al global de ellas. La shell permite agrupar órdenes mediante paréntesis. La solución consiste en combinar ambos:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ (echo Hola... ; sleep 5 ; echo ...caracola ) &
    Hola...
    [1] 743
    <gyermo@ENCINA>/usuarios/profes/gyermo$ [[Transcurridos 5 segundos...]]...caracola
    
  5. Shell scripts

    Los ficheros de configuración son un ejemplo de lo que se conoce como scripts o guiones de la shell. Al igual que ocurre con ciertos programas con apariencia de espontaneidad, del estilo del de Buenafuente, el guion es en realidad el que marca lo que va a ocurrir. Para construir un guion de la shell, debemos conocer unas reglas muy sencillas, que vienen reflejadas en este ejemplo:
    #!/bin/bash
    
    # Esto es un comentario.  Los comentarios empiezan por almohadilla
    
    echo El número de parámetros pasados es $#
    echo Los parámetros son: $*
    
    echo El primer parámetro es $1
    echo El segundo parámetro es $2
    
    # Vamos a devolver un 0 a la shell
    exit 0
    
    
    Observad lo siguiente:
    1. Aunque no es obligatorio, es conveniente que en la primera línea se indique cuál es la shell para la que está pensado este guion, con el formato que se muestra
    2. Los comentarios se indican con una línea que comience por el carácter de almohadilla (#)
    3. El número de argumentos, sin contar el nombre del guion, se pasa en la variable de entorno #
    4. Todos los argumentos, separados por espacios, se pueden obtener de la variable de entorno *
    5. Los argumentos, si los hay, vienen en variables numeradas: el primero en 1, el segundo en 2, y así sucesivamente
    6. Dentro del guion podéis ejecutar cualquiera de las órdenes vistas e incluso otros guiones
    7. Para devolver un valor concreto, se usa la orden exit, que acaba, en cualquier punto, con el programa
    8. Si no se acaba con exit, el valor devuelto es el de la última orden ejecutada

    En el directorio de vuestra preferencia (puede ser uno nuevo), editad un fichero que se llame ejemplo.sh e introducid el contenido del listado. Para ejecutarlo, simplemente hay que dar el nombre del guion, como si de otra orden cualquiera se tratase. Pero, ¡atención!:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh
    bash: ./ejemplo.sh: Permission denied
    
    Por defecto, los ficheros nuevos no se crean con el permiso de ejecución activado. Es por ello, que si los tratáis de ejecutar directamente, os va a dar un error de permisos. Pues los cambiamos:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ls -l ejemplo.sh 
    -rw-r--r--   1 gyermo   profes       239 ago 26 17:37 ejemplo.sh
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh
    bash: ./ejemplo.sh: Permission denied
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ chmod 755 ejemplo.sh
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh
    El número de parámetros pasados es 0
    Los parámetros son: 
    El primer parámetro es
    El segundo parámetro es
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh hola adiós chimpún
    El número de parámetros pasados es 3
    Los parámetros son: hola adiós chimpún
    El primer parámetro es hola
    El segundo parámetro es adiós
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo $?
    0
    
    Los permisos con los que se crean los ficheros por defecto se pueden modificar con la orden umask que, de querer que sus efectos sean permanentes, se puede incluir en el .bash_profile. Aunque su efecto es el de quitar permisos, no añadirlos. Se puede usar para restringir los permisos concedidos por defecto a ficheros y directorios recién creados. Los interesados pueden dirigirse a su página de manual.

    La orden shift elimina el primer parámetro y mueve una posición el resto hacia abajo. Se usa para procesar los parámetros uno a uno en un bucle. Modifiquemos el programa anterior para ver qué hace la orden shift:
    #!/bin/bash
    
    # Esto es un comentario.  Los comentarios empiezan por almohadilla
    
    echo ANTES DE SHIFT:
    echo El número de parámetros pasados es $#
    echo Los parámetros son: $*
    echo El primer parámetro es $1
    echo El segundo parámetro es $2
    echo
    
    shift
    echo DESPUÉS DE SHIFT:
    echo El número de parámetros pasados es $#
    echo Los parámetros son: $*
    echo El primer parámetro es $1
    echo El segundo parámetro es $2
    
    # Vamos a devolver un 0 a la shell
    exit 0
    
    
    Y el resultado de la ejecución:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh hola adiós chimpún
    ANTES DE SHIFT:
    El número de parámetros pasados es 3
    Los parámetros son: hola adiós chimpún
    El primer parámetro es hola
    El segundo parámetro es adiós
    
    DESPUES DE SHIFT:
    El número de parámetros pasados es 2
    Los parámetros son: adiós chimpún
    El primer parámetro es adiós
    El segundo parámetro es chimpún
    
  6. Tabla de ficheros y shell scripts

    Todos los procesos en UNIX disponen de una tabla donde aparecen la información relativa a los ficheros que el proceso tiene abiertos. Dichos ficheros se identifican por un número (el descriptor de fichero) que no es más que el índice del lugar de la tabla donde se encuentran la información del fichero.

    Cuando arrancamos una shell script, de no hacer nada especial, la shell tiene tres ficheros abiertos: el de descriptor 0 o entrada estándar (conectado al teclado), el de descriptor 1 o salida estándar (conectado a la pantalla) y el descriptor 2 o canal de errores estándar (también conectado a la pantalla). En las expresiones de redirección, podemos hacer referencia a ellos por su número, como hemos visto ya, o con la expresión /dev/fd/n. Así, para sacar la palabra "Hola" por el canal de errores, podemos escribirlo indistintamente:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Hola" >&2
    Hola
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Hola" >/dev/fd/2
    Hola
    
    Si la shell tiene redireccionadas sus entradas o salidas, al escribir en ellas, el resultado irá a la correspondiente redirección. Pero la propia shell puede cambiar este comportamiento al vuelo, como se puede apreciar en el siguiente ejemplo, usando la orden exec:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Salida normal"
    Salida normal
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec >salida.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Salida cambiada"
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec >&2
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt
    Salida cambiada
    
    En el ejemplo hacemos que, a partir del primer exec, la salida estándar esté redirigida al fichero salida.txt. De este modo, el mensaje del echo vemos que realmente no sale por la pantalla. Una vez restaurada la salida estándar a la pantalla, comprobamos cómo la salida en efecto se añadió al fichero salida.txt.

    La orden exec permite trabajar con descriptores más altos y esto, a su vez, permite trabajar con ficheros como en cualquier otro lenguaje de programación. En este ejemplo, abrimos un fichero, escribimos algo en él y lo cerramos. Usaremos el descriptor número 7:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec 7>salida.txt # Abrimos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Prueba" >&7 # Escribimos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec 7>&-         # Cerramos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt
    Prueba
    
    El problema puede venir al elegir nosotros un número de descriptor, que pudiera estar ocupado. Si dejamos este trabajo a la shell, lo haríamos así:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec {FD}>salida.txt # Abrimos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Prueba" >&$FD  # Escribimos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec {FD}>&-         # Cerramos
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt
    Prueba
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo El descriptor usado fue el $FD
    El descriptor usado fue el 10
    
    Hemos usado el signo de mayor que porque hemos querido abrir el fichero es modo de salida. Si lo hubiéramos querido abrir en modo de entrada, usaríamos el correspondiente signo de menor que y, si lo que deseamos es abrirlo para leer y escribir, la notación es: exec {OTROFD}<>otroFichero.txt.

    Finalmente, se puede duplicar un descriptor en otro, con la notación ya vista, pero también se puede mover un descriptor a otro, esto es, por ejemplo, mover el descriptor 10 al 4: exec 4>&10-. Es evidente que si el descriptor 10 no está abierto por el proceso (no existe para él), pues nos dará error.
  7. Ejercicio

    Programar una shell script a la que se la pasen un número indeterminado de ficheros y les cambie los permisos a rwxr-x---. Probadla con un fichero, con varios y con expresiones regulares para ver que funciona como se espera.
  8. Entrada del usuario: read

    Cualquier lenguaje de programación ofrece la posibilidad de que el usuario introduzca datos. En el caso de la shell que estamos viendo, la orden es read. Lo introducido por el usuario aparece en la variable de entorno REPLY:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ read
    Hola, ¿qué tal?
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo $REPLY
    Hola, ¿qué tal?
    
  9. Ejercicio

    Modificar la shell script de los ejercicios anteriores de modo que se le muestre al usuario un mensaje pidiendo el nombre del fichero y lea lo que teclee. A continuación le pide el código numérico de los permisos y, finalmente, le cambie los permisos al fichero introducido.
  10. Sustituciones

    La shell dispone de un manejo elemental de cadenas de caracteres. Para conseguir una subcadena, la sintaxis es como la del ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ PALABRA=salamanquesa
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA:4:7}
    manques
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA:7}
    quesa
    
    Para saber la longitud de la cadena, se usa:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${#PALABRA}
    12
    
    Las cuatro posibilidades que vienen a continuación, sirven para suprimir el inicio o el fin de la cadena. Usan expresiones regulares y la diferencia entre las dos versiones es que una suprime lo máximo que case (la que tiene dos caracteres) y la otra suprime lo mínimo que case (la que tiene un carácter), como en los siguientes ejemplos:
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA%a*}
    salamanques
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA%%a*}
    s
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA#*[lq]}
    amanquesa
    <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA##*[lq]}
    uesa
    
    También tenemos posibilidad de efectuar sustituciones en general, basándonos o no, en expresiones regulares:
    <gyermo@ENCINA</usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA/ques/c}
    salamanca
    <gyermo@ENCINA</usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA/*e/ca}
    casa
    
    Aunque existen algunas posibilidades más, como en el resto de estas prácticas, nos hemos centrado solamente en las más útiles. Para saber más, se puede consultar la página de manual de bash.
  11. Ejercicio

    Hacer un guion de la shell al que, pasándole la ruta de un fichero con una extensión de longitud variable, pero que existe, se la cambie a .gif
  12. Órdenes de la shell relacionadas.

    ps
    muestra información de los procesos
    top
    muestra información dinámica de los procesos de más consumo de CPU
    sleep
    espera un tiempo sin hacer nada
    jobs
    imprime los procesos de segundo plano
    kill
    elimina un proceso
    fg
    trae un proceso a primer plano
    bg
    pone en ejecución un proceso parado de segundo plano
    exit
    abandona la shell y devuelve un valor
    shift
    mueve los argumentos una posición hacia abajo
    read
    lee una línea tecleada por el usuario y la almacena en REPLY


  13. Funciones de biblioteca relacionadas.



  14. LPEs.


© 2011 Guillermo González Talaván.