PRÁCTICAS DE SISTEMAS OPERATIVOS I

TERCERA SESIÓN


  1. Redirección de salida

    La salida de una orden de UNIX suele ir a la pantalla. Esto no debería suponer una gran noticia pues nuestra orden emblemática, el entrañable ls no cesa de mostrarnos por la pantala información de más y más ficheros.

    Este comportamiento por defecto se puede cambiar. Podemos pedir a una orden, o a un programa en general, que nos escriba en un fichero lo que, de otro modo, sacaría por la pantalla. Se hace con el símbolo de mayor que (>):
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls -l
    total 2382
    drwxr-xr-x   2 gyermo   profes       512 ago 22 20:01 ARGUMENTOS
    -rwx------   1 gyermo   profes        99 abr 17  2002 backup
    drwxr-xr-x   2 gyermo   profes       512 abr 14  2010 bin
    drwxr-xr-x  12 gyermo   profes       512 ago 22 17:30 CAJAFUERTE
    drwxr-xr-x   2 gyermo   profes       512 ago 21 13:31 CARTAS
    -rw-r--r--   1 gyermo   profes        50 feb  4  2009 chgrp.2
    -rw-------   1 gyermo   profes   1191936 abr  1  2005 gyermo-encina-2005-03.tar.gz
    drwx------   2 gyermo   profes       512 dic 23  2003 mail
    drwxr-xr-x   2 gyermo   profes      2048 feb 27  2002 MANTEJO
    drwx------  21 gyermo   profes      1024 ago 18 19:12 PRIVADO
    d---r-xrwx   2 gyermo   profes       512 ago 18 02:24 PRUEBA
    drwxr-xr-x   3 gyermo   profes       512 jul  3  2006 public_html
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION3
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION6
    drwx------   3 gyermo   profes       512 mar  2  2010 TEMP
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls -l > salida
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls -l salida
    -rw-r--r--   1 gyermo   profes      1020 ago 23 18:24 salida
    
    Como vemos, en la segundo ejecución de ls, hemos desviado la salida por la pantalla al fichero salida y, consecuentemente, tenemos ese fichero nuevo. Para ver su contenido, necesitamos una orden que muestre el contenido de un fichero. Si el hombre (man) nos ayuda con la documentación de las órdenes, el gato (cat, de concatenate) nos muestra el contenido de los ficheros:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ cat salida
    total 2382
    drwxr-xr-x   2 gyermo   profes       512 ago 22 20:01 ARGUMENTOS
    -rwx------   1 gyermo   profes        99 abr 17  2002 backup
    drwxr-xr-x   2 gyermo   profes       512 abr 14  2010 bin
    drwxr-xr-x  12 gyermo   profes       512 ago 22 17:30 CAJAFUERTE
    drwxr-xr-x   2 gyermo   profes       512 ago 21 13:31 CARTAS
    -rw-r--r--   1 gyermo   profes        50 feb  4  2009 chgrp.2
    -rw-------   1 gyermo   profes   1191936 abr  1  2005 gyermo-encina-2005-03.tar.gz
    drwx------   2 gyermo   profes       512 dic 23  2003 mail
    drwxr-xr-x   2 gyermo   profes      2048 feb 27  2002 MANTEJO
    drwx------  21 gyermo   profes      1024 ago 18 19:12 PRIVADO
    d---r-xrwx   2 gyermo   profes       512 ago 18 02:24 PRUEBA
    drwxr-xr-x   3 gyermo   profes       512 jul  3  2006 public_html
    -rw-r--r--   1 gyermo   profes         0 ago 23 18:24 salida
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION3
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION6
    drwx------   3 gyermo   profes       512 mar  2  2010 TEMP
    
    Si peferís verlo con vuestro editor favorito, pues también podéis. Si sois observadores notaréis que hemos pillado al fichero salida in fraganti. Cuando ls le ha echado la foto, estaba ya creado, porque se crea antes de dar el control a ls, pero aún no tenía su contenido.

    Si lo que queremos es que la orden desvíe la salida de la pantalla a un fichero, pero que la añada al final sin destruir lo que en el fichero hubiera, debemos doblar el carácter de mayor que (>>). Vamos a añadir la fecha y la hora en que hemos hecho el listado al fichero salida. ¿Os atrevéis a hacerlo sin mirar la solución que se os pone a continuación?
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo "Listado realizado el 23 de agosto, a las siete" >> salida  
    <gyermo@ENCINA>/usuarios/profes/gyermo$ cat salida
    total 2382
    drwxr-xr-x   2 gyermo   profes       512 ago 22 20:01 ARGUMENTOS
    -rwx------   1 gyermo   profes        99 abr 17  2002 backup
    drwxr-xr-x   2 gyermo   profes       512 abr 14  2010 bin
    drwxr-xr-x  12 gyermo   profes       512 ago 22 17:30 CAJAFUERTE
    drwxr-xr-x   2 gyermo   profes       512 ago 21 13:31 CARTAS
    -rw-r--r--   1 gyermo   profes        50 feb  4  2009 chgrp.2
    -rw-------   1 gyermo   profes   1191936 abr  1  2005 gyermo-encina-2005-03.tar.gz
    drwx------   2 gyermo   profes       512 dic 23  2003 mail
    drwxr-xr-x   2 gyermo   profes      2048 feb 27  2002 MANTEJO
    drwx------  21 gyermo   profes      1024 ago 18 19:12 PRIVADO
    d---r-xrwx   2 gyermo   profes       512 ago 18 02:24 PRUEBA
    drwxr-xr-x   3 gyermo   profes       512 jul  3  2006 public_html
    -rw-r--r--   1 gyermo   profes         0 ago 23 18:24 salida
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION3
    drwxr-xr-x   2 gyermo   profes       512 mar 19  2002 SESION6
    drwx------   3 gyermo   profes       512 mar  2  2010 TEMP
    Listado realizado el 23 de agosto, a las siete
    
  2. Redirección de errores

    Sabéis de las asignaturas de programación que un programa en C tiene, desde su nacimiento, tres ficheros abiertos: la entrada estándar (stdin), la salida estándar (stdout) y el canal de errores estándar (stderr).

    El primero está conectado por defecto al teclado del terminal. Los dos últimos vierten, por defecto, su salida a la pantalla. Escribamos un pequeño programa en C que use la salida estándar y el canal de errores estándar:
    #include <stdio.h>
    
    int main(void)
     {printf("Esto va a la salida estándar.\n");
      fprintf(stdout, "Esto también va a la salida estándar.\n");
      fprintf(stderr, "Esto va al canal de errores.\n");
      return 0;}
    
    Si lo ejecutamos, vemos los tres mensajes y, por lo visto en el apartado anterior, si redirigimos la salida a un fichero, solo vemos los mensajes de error:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ gcc errores.c -o errores
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores 
    Esto va a la salida estándar.
    Esto también va a la salida estándar.
    Esto va al canal de errores.
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores > salida
    Esto va al canal de errores.
    
    Podemos, también, redirigir el canal de errores. Para ello, usamos los mismos símbolos que para la salida estándar, pero anteponiendo un 2:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores 2> salida
    Esto va a la salida estándar.
    Esto también va a la salida estándar.
    
    Podemos, por supuesto, redirigir la salida estándar a un fichero y el canal de errores a otro. Pero, si queremos, que ambos canales vayan al mismo fichero, hay que tener cuidado. La primera forma que se nos puede ocurrir, no va a funcionar:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores > salida 2> salida
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ cat salida
    Esto va a la salida estándar.
    Esto también va a la salida estándar.
    
    El ordenador, al abrir el fichero de salida dos veces, machaca el contenido y no funciona. Debemos decirle algo como: manda el canal de errores a donde he mandado la salida estándar. Esto se hace con la siguiente sintaxis:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores > salida 2>&1
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ cat salida
    Esto va al canal de errores.
    Esto va a la salida estándar.
    Esto también va a la salida estándar.
    
  3. Fichero nulo

    Existe un fichero especial en UNIX que, todo lo que se envía a él, desaparece. Es como un agujero negro, pero en lugar de succionar materia, succiona datos. Su nombre es /dev/null

    Si, por ejemplo, queremos que el ordenador no nos moleste con los mensajes de errores, podemos redireccionar el canal de errores a /dev/null:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores 2>/dev/null
    Esto va a la salida estándar.
    Esto también va a la salida estándar.
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ cat /dev/null
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ 
    
    Como podéis comprobar con el cat, /dev/null engulle y engulle, y no queda nada.

    A veces, no queremos que una orden o programa nos moleste en absoluto, ni con su salida, ni con sus mensajes de error. En ese caso, redirigimos ambos canales a /dev/null:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ errores 2>/dev/null >&2
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ cat /dev/null
    <gyermo@ENCINA>/usuarios/profes/gyermo/ERRORES$ 
    
  4. Redirección de entrada

    La orden cat es la más sencilla de una serie de órdenes que vamos a tratar en esta sesión. Para que este aspecto de cat salga a la luz, hay que invocarla sin argumentos. Hacedlo. Teclead, a continuación algo y ved lo que pasa:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ cat
    Hola
    Hola
    ¿Qué pasa aquí?
    ¿Qué pasa aquí?
    eco, eco, eco...
    eco, eco, eco...
    ^C<gyermo@ENCINA>/usuarios/profes/gyermo$ 
    
    Cuando cat se invoca sin argumentos, la orden toma todo lo que le llega por la entrada estándar y lo vuelca tal cual por la salida estándar. El efecto neto es esa especie de eco que observáis. Para que el ordenador interrumpa esta orden (u otras que no quieran parar o que estén colgadas), podéis pulsar CTRL-C (presionáis la tecla Ctrl y, sin soltarla, presionáis la tecla C).

    Podemos usar la orden cat como un rudimentario editor para crear un nuevo fichero de texto, sin más que redireccionar su salida estándar. Vamos a probarlo dentro de un nuevo directorio de nombre SEMANA, donde vamos a crear un fichero llamado semana.txt, con el nombre de los siete días de la semana:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat > semana.txt
    lunes
    martes
    miércoles
    jueves
    viernes
    sábado
    domingo
    [[Pulsad aquí CTRL-D]]
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat semana.txt
    lunes
    martes
    miércoles
    jueves
    viernes
    sábado
    domingo
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ 
    
    Debéis pulsar el carácter de CTRL-D en lugar del de CTRL-C, porque este último se usa para abortar una orden. Sin embargo, CTRL-D significa fin de fichero o fin de transmisión, sin que el ordenador interprete que ha ocurrido un error o una parada anormal.

    Diagrama de filtro


    Como se ha comentado antes, cat pertenece a una familia de órdenes de UNIX conocida como filtros. Consisten en que aceptan datos por la entrada estándar, hacen algo con ellos y producen una salida por la salida estándar. El caso de cat es el más simple porque no hace nada con los datos. Pero veamos otro ejemplo más útil: la orden sort.

    sort es suerte en catalán, así que, como homenaje, tecleemos la orden y el nombre de las provincias catalanas para ver qué sucede:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ sort
    Barcelona
    Tarragona
    Lérida
    Gerona
    [[Pulsad aquí CTRL-D]]
    Barcelona
    Gerona
    Lérida
    Tarragona
    
    Ejemplo con sort


    Nadie quita que la orden nos dé buena suerte, pero más bien su nombre viene del inglés. Esta orden ordena las líneas que le lleguen por la entrada estándar y las imprime ya ordenadas por la salida estándar.

    Pero este apartado, en realidad, trata de la redirección de la entrada de una orden. Después de esta introducción, estamos en condiciones de abordarla. Consiste en poder cambiar el comportamiento por defecto de una orden para que, en lugar de leer sus datos de la entrada estándar, lo haga del fichero cuyo nombre le proporcionemos. El mecanismo es muy sencillo. Lo vamos a probar ordenando la lista de los días de la semana que elaboramos al principio de este apartado:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ sort < semana.txt
    domingo
    jueves
    lunes
    martes
    miércoles
    sábado
    viernes
    
  5. El filtro grep

    Quizá uno de los filtros que más se usen sea grep. Además, es el que más hace honor al nombre de filtro. Su cometido es dejar pasar todo aquello que case con el primer argumento y retener (filtrar) todo lo demás. Lo mejor es verlo en funcionamiento en un ejemplo. Veamos qué días de la semana tienen al menos una 's' en su nombre:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep "s" < semana.txt
    lunes
    martes
    miércoles
    jueves
    viernes
    sábado
    
    En realidad, el primer argumento no deja de ser una expresión regular, solo que de otro tipo de las ya vistas. También tienen caracteres especiales. Por ejemplo, para ver qué días de la semana acaban en 's' y cuáles, empiezan con 's', usamos:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep "s$" < semana.txt
    lunes
    martes
    miércoles
    jueves
    viernes
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep "^s" < semana.txt
    sábado
    
    También valen las expresiones con corchetes que vimos en las otras expresiones regulares y algunas otras más, más o menos estandarizadas. La orden grep admite como opción -v. En ese caso, el filtro lo realiza al revés: filtra lo que coincida y deja pasar lo que no coincida. Por ejemplo, pidamos a grep que nos diga qué días de la semana no tienen vocales débiles:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep -v "[iu]" < semana.txt
    martes
    sábado
    
    Lo que no es igual que esto otro:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep "[^iu]" < semana.txt
    lunes
    martes
    miércoles
    jueves
    viernes
    sábado
    domingo
    
    En este caso, lo que le pedimos a grep es aquellos días de la semana que contengan al menos una letra que no sea una vocal débil.
  6. Filtros cut, paste y uniq

    Estos filtros sirven para quedarse con parte de la información o reformatearla. El primero, nos sirve para quedarnos con una parte de la información que aparezca en cada línea. Imaginemos que queremos quedarnos con los tres primeros caracteres de los nombres de los días de la semana, para usarlos luego como abreviatura:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cut -c 1-3 < semana.txt
    lun
    mar
    mié
    jue
    vie
    sáb
    dom
    
    También se puede cortar no por caracteres exactos, sino por campos, separados por espacio. Por ejemplo, si queremos que se imprima por la pantalla la fecha de hoy, podemos cortar por campos, basándonos en la orden date:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ date > hoy.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat hoy.txt
    jueves 25 de agosto de 2011 01H40'59" CEST
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cut -f 2-6 -d " " < hoy.txt
    25 de agosto de 2011
    
    Con la opción -f seleccionamos los campos que queremos y con la opción -d decimos cuál es el separador de los campos.

    Como complemento a la orden cut existe la orden paste. Toma una línea de cada uno de los ficheros que pongamos como argumentos y las combina en una única línea en la salida. Y así, con todas. Usémoslo para anteponer un número a cada día de la semana, separado por un guion:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat > numeros.txt
    1
    2
    3
    4
    5
    6
    7
    [[Pulsad aquí CTRL-D]]
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ paste -d "-" numeros.txt semana.txt 
    1-lunes
    2-martes
    3-miércoles
    4-jueves
    5-viernes
    6-sábado
    7-domingo
    
    De nuevo, el separador entre los ficheros se indica con la opción -d.

    La última de las órdenes, es muy sencilla. Elimina las líneas repetidas que vayan seguidas de la entrada antes de pasarlas a la salida:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat > salida.txt
    una
    una
    una
    otra
    otra
    una
    una
    [[Pulsad aquí CTRL-D]]
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ uniq < salida.txt
    una
    otra
    una
    
  7. Ejercicio

    Usando las órdenes que hemos visto hasta ahora y con la ayuda de ficheros intermedios, decir cuáles son los usuarios que poseen ficheros en el directorio /usr/bin
  8. Otros filtros útiles

    Los siguientes filtros también se usan habitualmente:
  9. Encadenamiento de filtros

    Todos los filtros que hemos visto se pueden encadenar. Consiste esto en que la salida de un filtro sirve como entrada para el siguiente. Se usa para indicar el encadenamiento el carácter de tubería (|). Esta función permite ahorrarnos cantidad de ficheros intermedios para hacer una operación. Por ejemplo, para imprimir la fecha de hoy, sin necesidad de usar un fichero auxiliar, como hicimos más arriba, podemos poner:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ date | cut -f 2-6 -d " "
    25 de agosto de 2011
    
    Ejemplo de tubería
    Cuando montamos una cadena larga, se dispone de la orden tee (su significado es la letra T, pues tiene la forma de un desvío), para desviar un resultado intermedio a un fichero. Por ejemplo, deseamos obtener un listado de las iniciales de los días de la semana cuyo nombre contiene solamente letras de la 'e' a la 'z'. Deseamos que quede una copia de los nombres completos de los días que cumplen esa condición en el fichero salida.txt:
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ grep -v "[a-dá]" < semana.txt | sort | tee salida.txt | cut -c 1
    j
    l
    v
    <gyermo@ENCINA>/usuarios/profes/gyermo/SEMANA$ cat salida.txt
    jueves
    lunes
    viernes
    
    Ejemplo de tubería
  10. Ejercicio

    Repetir el ejercicio anterior con una serie de órdenes dadas en una única línea y sin la ayuda de ficheros intermedios.
  11. Ejercicio

    La orden cal nos imprime el calendario del mes actual. Construir una línea que nos dé en qué cae el cuarto sábado del mes actual.
  12. Ejercicio

    En un concurso nocturno de la tele nos piden adivinar el nombre de un animal que se pueda formar con las letras siguientes:

    CEBS
    LOPT
    MARD
    JUNV


    Tenemos la esperanza de que el nombre se encuentre en el fichero situado en /usuarios/profes/gyermo/bin/animales.txt. Responde, con ayuda del ordenador, a las siguientes preguntas:
    1. ¿Cuántos nombres de animales tiene el fichero?
    2. ¿Cuántas veces tengo que lograr pasar a directo para estar seguro de acertar el animal?
    3. Ya cerca del final del programa, nos dan una pista: el nombre del animal acaba en A. Si el animal está en nuestra lista, ¿cuántas posibilidades hay ahora de acertarlo?
  13. Tuberías con nombre

    Unix tiene la posibilidad de crear ficheros especiales conocidos como tuberías con nombre (en inglés, named pipes). Estos ficheros se denominan así porque actúan como las tuberías reales. Se puede añadir agua a la tubería (escribir) o sacar agua de ella (leer). Además, el agua que se saca es la primera que se metió (disciplina FIFO).

    Vamos a crear una tubería con nombre:
    <T>/usuarios/gyermo/PRIVADO/SO/PRACTS/TUBOS$ /sbin/mknod tubo1 p
    <T>/usuarios/gyermo/PRIVADO/SO/PRACTS/TUBOS$ ls -l
    total 0
    prw-r--r--   1 gyermo     profes           0 Mar 20 13:23 tubo1
    Hay que especificar la ruta completa de la orden mknod porque se encuentra en un directorio de herramientas de administración del sistema que no está en la variable de entorno PATH de los usuarios normales.

    <ENCINA>/home/gyermo/PRIVADO/TUBOS$ mknod tubo1 p
    <ENCINA>/home/gyermo/PRIVADO/TUBOS$ ls -l
    total 0
    prw-r--r--   1 gyermo   profes         0 mar 19 23:34 tubo1
    En este caso, mknod sí se encuentra en el PATH.

    Como veis, hay que dar la orden especial mknod para crear la tubería. Su página de manual se encuentra en la sección 1m (donde están las órdenes de administración del sistema). Depués de crear la tubería con mknod, aparece en el directorio como un fichero más sólo que ls -l indica mediante una p que se trata de una tubería. Se llama tubería con nombre por eso, porque precisamente tenemos que darle un nombre para que aparezca en el directorio.

    Vamos a usar la tubería para comunicarnos. Abrid otra ventana de terminal e id al mismo directorio donde creasteis la tubería. En una de las ventanas teclead:
    cat < tubo1 
    En la otra:
    cat > tubo1 
    A partir de esos momentos, todo lo que tecleéis en la segunda ventana aparecerá en la primera. Para acabar, podéis teclear en la segunda ventana el carácter de fin de fichero (CTRL+D). Por lo tanto, para usar una tubería con nombre, lo único que hay que hacer es que un proceso la abra para lectura, otro la abra para escritura y que se comuniquen mediante las funciones de lectura y escritura en los ficheros.
  14. Ejercicio

    Podéis intentar hacer como en el ejemplo del apartado anterior pero que la comunicación sea bidireccional. Crearéis así un rudimentario talk. Si desesperáis y no lo conseguís, podéis ver cómo hacerlo aquí.
  15. Órdenes de la shell relacionadas.

    cat
    muestra el contenido de ficheros
    sort
    filtro de ordenación
    grep
    filtro para seleccionar líneas
    cut
    filtro para seleccionar columnas
    paste
    pega varios ficheros en columnas
    uniq
    filtro que elimina líneas repetidas seguidas
    more
    saca el contenido página a página
    head
    filtro que muestra las primeras líneas de un fichero
    tail
    filtro que muestra las últimas líneas de un fichero
    wc
    filtro que cuenta líneas, palabras y caracteres
    date
    muestra la fecha y hora actuales
    tee
    filtro que desvía una copia de los datos a un fichero
    cal
    imprime un calendario del mes actual
    mknod
    crea ficheros especiales, entre ellos, tuberías con nombre


  16. Funciones de biblioteca relacionadas.



  17. LPEs.


© 2013 Guillermo González Talaván.