Programación del Shell LinuxAquí tenemos un libro libre y completo sobre ShellLa sed del "conocimiento libre" es muy bienvenida. |
Comandos Shell Script |
![]() |
|
Home |
Artículos ![]() ![]() |
Comprar el libroChangelogs |
|
Conversación de Bar - Parte XI- Ei!, como va amigo, todo bien?
- Más o menos.. te acuerdas que me pediste que hiciera un programa que cuando el tamaño de la pantalla variase, en el centro apareciese dinamicamente y en vídeo inverso, la cantidad de líneas y columnas, de la misma forma que el Linux hace normalmente?. Bueno, lo hice, pero la apariencia no quedó igual.
- No estoy preocupado por la apariencia, lo que yo quería es que ejercitases lo que aprendimos. Déjame ver lo que hiciste. $ cat tamtela.sh
#!/bin/bash
#
# Colocar en el centro de la pantalla, con vídeo inverso,
# una cantidad de columnas y lineas
# cuando el tamaño de la pantalla es alterado.
#
trap Muda 28 # 28 = señal generada por el cambio de tamaño
# de la pantalla y Muda es la función que hace eso.
Bold=$(tput bold) # Negrita, modo de énfasis Rev=$(tput rev) # Modo de vídeo inverso Norm=$(tput sgr0) # Restaura la pantalla al valor por defecto Muda () { clear Cols=$(tput cols) Lins=$(tput lines) tput cup $(($Lins / 2)) $(((Cols - 7) / 2)) # Centro de la pantalla echo $Bold$Rev$Cols X $Lins$Norm } clear read -n1 -p "Cambie el tamaño de la pantalla o teclee algo para terminar"
- Perfecto!, que se joda la apariencia, después te enseño otras formas de mejorarlo, lo que vale es el programa, está funcionando y esta todo optimizado.
- Pero perdí la mayor parte del tiempo intentando descubrir como aumentar el tamaño de la fuente.- ...
- Deja eso para otro día, hoy vamos a ver unas cosas bastante interesantes y útiles.. Named PipesOtro tipo de pipes es el "named pipes", que también es llamado porFIFO . FIFO es un acrónimo de First In First Out, que se refiere a la propiedad de que los bytes salen con el mismo orden que entran. El "name" en named pipe es en verdad el nombre de un archivo. Los archivos tipo named pipe son mostrados por el comando "ls" como cualquier otro, con pocas diferencias, mira:
$ ls -l pipe1
prw-r-r-- 1 julio dipao 0 Jan 22 23:11 pipe1|
La
En los sistemas mas antiguos, los
En los sistemas mas modernos, la misma tarea es hecha por $ mkfifo pipe1
Como siempre la mejor forma de mostrar que algo funciona es dando ejemplos. Suponga que hayamos creado el $ ls -l > pipe1
en la otra haz: $ cat < pipe1
Voilá! La salida del comando ejecutado en la primera consola fue mostrada en la segunda. Fíjate que el orden en que los comandos ocurrieron no importa.
Si prestaste atención, viste que el primer comando ejecutado parecía estar "colgado". Esto sucede por que la otra punta del pipe todavía no estaba conectada, y entonces el sistema operativo suspendió el primer proceso hasta que el segundo proceso "abriera" el pipe. Para que un proceso que usa el _pipe no quede en modo wait, es necesario que en una punta del pipe tenga un proceso "que habla" y en el otro un proceso " que escucha" y en el ejemplo que dimos , el
Una aplicación muy útil de los Viste que el uso de esta herramienta es ideal para sincronizar los procesos y para bloquear archivos y poder evitar así perdida o corrupción de información debido a actualizaciones simultáneas (concurrencia). Veamos ejemplos para ilustrar estos casos. Sincronización de procesos.Imagina que lanzas paralelamente dos programas (procesos), los diagramas de bloque de sus rutinas son como muestra la siguiente figura:
Los dos procesos son lanzados en paralelo y en el
for Arq in BigFile1 BigFile2 BigFile3 do if sort $Arq then Manda=va else Manda=pare break fi done echo $Manda > pipe1 [ $Manda = pare ] && { echo Error durante la clasificación de los archivos exit 1 } ...
De esta forma, el comando
Mientras el
El fragmento del código del OK=`cat pipe1` if [ $OK = va ] then ... Rutina de impresión ... else # Recibí "pare" en OK exit 1 fi
Después de la ejecución del primer bloque , el Bloqueo de archivosSupón que escribes una CGI (Common Gateway Interface) en Shell para contar cuantos hits recibe una determinada URL y la rutina del contador es la siguiente:Hits="$(cat page.hits 2> /dev/null)" || Hits=0 echo $((Hits=Hits++)) > page.hits
De esa forma si la página recibe dos o mas accesos concurrentes, uno o mas podrá(n) perderse, basta que el segundo acceso sea hecho después de una lectura del archivo $ cat contahits.sh
#!/bin/bash
PIPE="/tmp/pipe_contador" # archivo llamado pipe # dir donde serán colocados los archivos contadores de cada pagina DIR="/var/www/contador" [ -p "$PIPE" ] || mkfifo "$PIPE" while : do for URL in $(cat < $PIPE) do FILE="$DIR/$(echo $URL | sed 's,.*/,,')" # OBS1: en el sed arriba, como precisaba buscar # una barra,usamos coma como separador. # OBS2: cuando rodar como daemon comente la próxima línea echo "arquivo = $FILE" n="$(cat $FILE 2> /dev/null)" || n=0 echo $((n=n+1)) > "$FILE" done done Como solamente este script modifica los archivos, no existe problema de concurrencia Este script será un daemon, esto es, correrá en background. Cuando una página sufre un acceso, el script escribirá su URL en el archivo del pipe. Para probarlo, ejecuta este comando: echo "test_pagina.html" > /tmp/pipe_contador Para evitar errores, en cada página que quisiéramos agregar el contador añadiriamos la siguiente linea: <!--#exec cmd="echo $REQUEST_URI > /tmp/pipe_contador"-->
Observa que la variable
Aja! Pensaste que el asunto sobre los Substitución de procesos
Acabo de mostrarte un montón de recetas sobre los $ cat <(ls -l)
Resultará que el comando Como podremos constatar esto? Fácil .. Mira el siguiente comando: $ ls -l >(cat)
l-wx------ 1 jneves jneves 64 Aug 27 12:26 /dev/fd/63 -> pipe:[7050]
Y... Realmente es un
Debes estar pensando que esto es una locura nerd , no? Entonces supongamos que tenes 2 directorios:
$ cmp <(cat dir/*) <(cat dir.bkp/*) || echo backup desactualizado!
o, mejor todavía: $ cmp <(cat dir/*) <(cat dir.bkp/*) >/dev/null || echo backup desactualizado!
De la última forma, la comparación fue efectuada en todas las líneas de todos los archivos de ambos directorios. Para acelerar el proceso, podríamos comparar solamente el listado largo de ambos en los directorios, pues cualquier modificación que un archivo sufra, es mostrado como alteración de la fecha/hora y/o del tamaño del archivo. Mira como quedaría: $ cmp <(ls -l dir) <(ls -l dir.bkp) >/dev/null || echo backup desactualizado!
Este es un ejemplo meramente didáctico, pues son tantos los comando que producen mas de una línea de salida que sirve como guia para otros. Quiero generar una lista de mis archivos, numerados y al final dar el total de archivos del directorio actual: while read arq do ((i++)) # así no es necesario inicializar i echo "$i: $arq" done < <(ls) echo "En el directório corriente (`pwd`) existen $i archivos"
Está bien, yo sé que existen otras formas de ejecutar la misma tarea. Usando el comando ls | while read arq do ((i++)) # así no es necesario inicializar i echo "$i: $arq" done echo "En el directório corriente (`pwd`) existen $i archivos"
Cuando ejecutase el script, parecería que esta todo ok, sin embargo en el comando #!/bin/bash LIST="" # Creada en el shell principal ls | while read FILE # Inicio del subshell do LIST="$FILE $LIST" # Alterada dentro del subshell done # Fin del subshell echo :$LIST:
Al final de la ejecución vas a ver que aparecerán apenas dos puntos ( $ ls | ln
o entonces, usando la propia substitución de procesos: $ cat -n <(ls)
Un último ejemlo: tu deseas comparar $ comm <(sort arq1) <(sort arq2)
Esta forma evita que tengas que hacer las siguientes operaciones: $ sort arq1 > /tmp/sort1
$ sort arq2 > /tmp/sort2
$ comm /tmp/sort1 /tmp/sort2
$ rm -f /tmp/sort1 /tmp/sort2
Gente.. nuesta Convesación llegó a su fin, De cualquier forma, en caso de que no consigamos sensibilizar la dirección de la revista, me despido de todos mandando un abrazo a los barbudos y besos a las chicas y agradezco a los mas de 100 mails que recibí (todos elogiosos) y todos debidamente respondidos. A la salud de todos nosotros: Chin, chin -Chico, cierra la cuenta que voy a cambiar de bar. Y no te olvides, cualquer duda o falta de compañia para tomar una cerveza o hasta para hablar mal de los políticos lo único que tienes que hacer es mandarme un e-mail para julio.neves@gmail.com. Voy aprovechar tambiém para mandar mi aviso publicitario: puedes decirle a los amigos que quien quiera hacer un curso nota diez de programación en Shell que mande un e-mail para julio.neves@uniriotec.br para informarse. Gracias y hasta la próxima!
-- DanielRefosco - 3 Jan 2007 |
Licencia Creative Commons - Reconocimiento y no comercial (CC) 2009 Por Visitantes del Bar de Júlio Neves. Todo el contenido de esta página puede ser usada de acuerdo a la Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença. |