Archivo

Entradas Etiquetadas ‘programas’

Guardando un informe en nuestros proyectos PHP

Martes, 24 de Enero de 2012 Gaspar Fernández Sin comentarios

130120125882

Muchas veces, los proyectos en PHP crecen y crecen, y pueden ocurrir múltiples errores, tanto a la hora de crearlos como cuando ya están entregados al cliente final y debemos ofrecer soporte.

Por eso es importante ser rápido localizando los errores, y, siempre que la página, o el programa no haga algo como debe, debería tomar nota de qué ha pasado, cómo ha sido y de los datos involucrados con el fin de poder solventar el problema. Tengo que decir que debemos ser inteligentes con estos criterios, ya que un usuario malintencionado puede hacernos perder todo el espacio que tengamos disponible en nuestro servidor provocando errores; por ejemplo un script que funcione en Ajax y no se le hayan entregado los parámetros necesarios, puede ser útil saberlo en tiempo de desarrollo, pero no cuando el proyecto esté funcionando en la web, puede que incluso un motor de búsqueda mal entrenado se dedique a entrar en ese script y tumbarnos el programa.

Para hacer un informe, lo más fácil es hacerlo en un fichero de texto (podemos crear un XML sin mucho esfuerzo más, aunque va a ser algo que sólo vamos a leer nosotros y como mucho los administradores de la página, en muchos casos a los administradores no les dejaremos verlo).

Para esto, yo dispongo de una clase con funciones para guardar un informe de errores:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php

  // Activa la depuración
define('__debug', true);

// Activa la visualización de los errores (sólo para modo desarrollo)
define('__debug_v', true);

class my_logger
{
  private $base_path;

  function __construct()
  {
    /** Sólo actuaremos si __debug es verdadero  */
    if (__debug)
      {
    define('__debug_file', 'my_log.log');
    define("__gf_dateformat_log", "d/m/Y H:i");

    // Si ejecutamos el programa desde consola. El directorio actual es PWD
    if (isset($_SERVER['DOCUMENT_ROOT']))
      $base_path=$_SERVER['DOCUMENT_ROOT'];
    elseif (isset($_SERVER['PWD']))
      $base_path=$_SERVER['PWD'];
    else
      $base_path='';
      }    
  }

/**
 ******************************************************************
 * @brief Escribir mensaje de error en pantalla
 *
 * To-do: Posibilidad de crear plantillas para este error desde el archivo de configuración
 *
 * @param $emsj    Mensaje de error
 *
 * @return Nada
 *
 ******************************************************************/

  private function displayerror($emsj)
  {
    return '<br /><span style="color: yellow;"'.wordwrap('DEP: '.$h->T($msj),70,"\n").'</span><br />';
  }

/**
 ******************************************************************
 * @brief Extrae el nombre de una función o un método de un array
 * de backtrace
 *
 * @param $bt_data  Array de backtrace
 * @param $index    Índice del array
 *
 * @return Array[3]={linea, Función o método (clase::metodo), fichero}
 *
 ******************************************************************/

  private function backtrace_function (&$bt_data, $index)
  {
    $bt_single=(isset($bt_data[$index]))?$bt_data[$index]:false;
    if (!$bt_single)        /* No data, no function */
      return false;

    $function=(isset($bt_single['function']))?$bt_single['function']:false;
    $class=(isset($bt_single['class']))?$bt_single['class']:false;
    $funcname=($class)?($class.'::'.$function):$function;
   
    $file=str_replace('path', '', $bt_single['file']);
    return array($bt_single['line'], $funcname, $file, $file.' ('.$funcname.', '.$bt_single['line'].')');
  }

  /**
 ******************************************************************
 * @brief Genera un fragmento de un error complejo. A menudo, esto
 *        incluye información del backtrace u otras cosas.
 *        Este método debe ser llamado desde preg_replace_callback()
 *
 * @param $data Datos enviados por preg_replace_callback()
 *
 * @return En qué se tiene que convertir la cadena enviada.
 *
 ******************************************************************/

  private function complexError($data)
  {
    if (!isset($data[1]))
      return $this->writelog('%%where%%: No se ha llamado desde preg_replace_callback(); Origen: "%%origen%%"');

    $btrace=debug_backtrace();

    switch ($data[1])
      {
      case 'where':
    $wdata=$this->backtrace_function ($btrace, 4); /* Nivel 0: complexError; Nivel 1:preg_replace_callback(); Nivel 2: writelog;  Nivel 3: wlog(); Nivel 4: El que queremos */
    return $wdata[3];
    break;
      case 'origen':
    $wdata=$this->backtrace_function ($btrace, 5); /* Nivel 3: dónde llamamos a la función */
    return $wdata[3];
    break;
      case '-origen':
    $wdata=$this->backtrace_function ($btrace, 6); /* Nivel 3: dónde llamamos a la función */
    return $wdata[3];
    break;
      case '--origen':
    $wdata=$this->backtrace_function ($btrace, 7); /* Nivel 3: dónde llamamos a la función */
    return $wdata[3];
    break;
      default:
    return $this->writelog('%%where%%: No se encuentra la palabra clave: "'.$data[1].'"');
    break;
      }
  }

/**
 ******************************************************************
 * @brief Escribimos un mensaje en el log.
 *
 * @param $error     Error a escribir
 * @param $display   Mostrar error en pantalla (sólo si __debug_v vale true)
 *
 * @return false para usarlo como return de alguna función
 *
 ******************************************************************/

  function writelog($error, $display=false)
  {
    if ((__debug) && ($error))
      {
    $errorw=preg_replace_callback('/%%(.*?)%%/', array($this, 'complexError'), $error);
    $log_f = fopen(__debug_file, "a+");
    fputs($log_f, date(__gf_dateformat_log)." - ".$errorw."\n");
    fclose($log_f);

    if ((__debug_v)&&($display))
      $this->displayerror($errorw);
      }
    return false;
  }
};

$log = new my_logger();

function wlog($error, $display=false)
{
  $GLOBALS['log']->writelog($error, $display);
}

function genera_error()
{
  wlog("Genero un error nada más empezar y digo dónde está %%where%% llamado por %%origen%%");
}

function original()
{
  genera_error();
}

original();
?>

Cada vez que encontramos un error, podemos llamar a wlog() para guardar el informe del error que se guardará en un archivo de texto.

Mientras estamos desarrollando la aplicación podemos definir __debug_v a true para visualizar algunos errores (que previamente enviaremos con wlog(”error”, true)).

Además, a la hora de enviar un error, disponemos de las palabras clave %%where%%, %%origen%%, %%-origen%% y %%–origen%% para identificar automáticamente en qué función se ha producido el error, desde qué línea se llama así como la función desde donde se llama a la que provoca el error, y la anterior…

Si utilizamos la opción para averiguar automáticamente dónde está el error (la alternativa sería escribir el nombre de la función en el texto del error) tardará un tiempo en ejecutarse, ya que estamos escrudiñando dónde se ha producido, estamos haciendo un backtrace. De hecho la función PHP que genera ese informe es debug_backtrace() y nos resultará de gran ayuda para la depuración de nuestras aplicaciones.

5 Aplicaciones que me salvan día a día

Domingo, 15 de Enero de 2012 Gaspar Fernández 3 comentarios

Son pequeñas aplicaciones sin las cuales no podría salir adelante día a día. Aunque a veces no las mime demasiado y no les haga mucho caso, deberían saber que son importantes para mí, para mi vida online y yo informático. He intentado establecer un orden, pero todas ellas son muy importantes, por lo que ocuparían todas la primera posición:

  1. Keepnote

    Es un software muy completo y ligero para tomar notas, clasificarlas y buscar dentro de ellas. De todos los que he probado es el que mejor sensación me ha dejado con respecto a su facilidad de uso, velocidad y características. Disponible en Linux, Mac y Windows

  2. KeepassX

    Es un gran programa para anotar nuestras contraseñas y anotaciones para cualquier tipo de identificación electrónica (webs, banca online, routers, etc). Puedes ordenar las contraseñas por categorías, asignarles iconos, buscarlas, etc. Es muy fácil de utilizar, y guarda la información cifrada para que nadie más que tú pueda verla. Disponible para Linux, Mac y Windows

  3. Grisbi

    Un software para organizar mi economía personal, saber cuánto dinero tengo en la cartera y en el banco, quién me debe y a quién le debo. Es muy completo y funciona en Linux, Mac y Windows.

  4. Emacs

    Llamadme friki, pero es mi editor de texto / IDE favorito para programar. Con multitud de opciones, automatizable, personalizable y todo a mano, aunque para aprender fue algo difícil en principio, una vez que sabes las cuatro cosas básicas, todo va sobre ruedas, y cada día me gusta más (excepto la opción deshacer, pero bueno, nadie es perfecto). Funciona en Linux, Mac, Windows, *BSD, Solaris y algunos más

  5. Hotot

    Un cliente para Twitter muy ligero, cómodo e intuitivo. Hay muchos clientes para microbloguear, pero con éste es con el que me siento más cómodo. Disponible para Linux, Mac, Windows y Chrome, aunque para Windows y Mac es bastante inestable aún.

En algunos de estos proyectos, y en otros más intento colaborar de diferentes formas, aunque a veces no en la medida que me gustaría, por falta de tiempo, como pasa siempre:

  • Clicks en la publicidad de sus webs oficiales
  • Perfeccionamiento de traducciones
  • Haciendo que más gente los utilice
  • Reportando bugs
  • Sugiriendo características

Y vosotros, ¿cómo colaboráis con vuestros proyectos preferidos? ¿Cuáles son esos 5 programas sin los que no podríais vivir?

¿ Por qué me pasé a Linux ?

Domingo, 7 de Noviembre de 2010 Gaspar Fernández 2 comentarios

Mis andanzas con Linux empiezan en el año 2001, en busca de un sistema operativo nuevo, por descubrimiento e investigación. Todo empezó intentando instalar una Debian en un ordenador que tenía para hacer experimentos, aunque no funcionó (aunque parezca extraño lo primero que vi fue un Kernel Panic, y por aquel entonces no tenía ni idea de por qué). Luego fui probando, e intenté instalar Red Hat, pero no me hallaba con la consola, y luego probé Mandrake, que me funcionó a la primera y con la que estuve un par de años.

La primera impresión que tuve de un GNU/Linux era la de un sistema delicado, tenía esa impresión subjetiva de que iba a tocar algo y todo se iba a fastidiar, luego pasé a tener la impresión de que me ocultaba partes del hardware, yo veía que con MSDOS y Windows accedía a las unidades C: y D: y con Mandrake no encontraba la forma de hacerlo.

Lo primero que intenté hacer, después de ver todos los juegos de KDE (KDE2, por aquel entonces), fue intentar compartir archivos con mi máquina Windows, y preguntando en algunos foros di con SAMBA, y después de una tarde entera investigando y editando smb.conf por fin pude conseguirlo; luego probé CUPS (en principio, sólo quería ver cómo irían mis necesidades básicas) y luego lo utilizaba para conectar al IRC (Internet Relay Chat, que, por aquel entonces estábamos todos muy viciados, más o menos como ahora a Facebook).

Aunque por aquel entonces no avancé demasiado, no tenía mucha idea, y a veces, al mirar los manuales no me enteraba de nada. Así que lo dejé por un tiempo.

Mientras tanto seguí un par de años más con Windows, y llegué al punto de tener que formatear y reinstalar cada tres meses. Un driver de una impresora chocaba con una actualización de Windows que necesitaba para instalar un programa; por otra parte, el ordenador se volvió demasiado lento (tengo que decir que no llegué a ser usuario de Windows XP, lo último que probé fue Windows 2000), me daba problemas con pendrives (al enchufarlos y desenchufarlos), además de llegó un punto en el que perdí información de trabajos para la Universidad por culpa de algún capricho tipo pantalla azul, lo cual me frustró profundamente (Tengo que decir que soy un usuario al que le gusta tener muchas cosas abiertas, escuchar música, navegar por Internet, tener mensajería instantánea (ahora uso más twitter, pero bueno), al mismo tiempo tenía servidor web, de base de datos y algunos programas más abiertos (habría que ver mi Firefox 1.5 con 20 pestañas abiertas)), tengo que confesar que un año antes eliminé definitivamente MS. Office, porque cada vez era más pesado y me resultaba menos útil, porque no había forma de matar al dichoso clip/perro/mago que te “ayudaba”, y porque ocupaba mucho disco duro, por aquel entonces empecé a usar StarOffice. Además, Windows empezó a transmitirme la sensación de un sistema sistema frágil, a medida que lo iba utilizando, se iba haciendo más y más lento (siempre me tomé en serio el tiempo de arranque, aunque soy más de dejar el ordenador todo el día encendido; Windows arrancaba lento y tenía que reiniciar de vez en cuando…). Por otro lado tenemos el tema de antivirus, tenía que tener tiempo para ponerlo al día, y me quitaba recursos de sistema que yo en ocasiones necesitaba…

Por eso a primeros de 2004 decidí darle otra oportunidad a Linux, y mi principal objetivo era aprender, por eso, tras probar Ubuntu y terminar con una sensación de un sistema más delicado, un arranque un poco más rápido que Windows, y la instalación de muchas cosas que no quería decidí probar Gentoo ; por aquel entonces la instalación era más complicada que ahora, e incluso siguiendo el manual, tal vez a la primera no se instalara bien, en dos o tres semanas aprendí muchas cosas sobre el kernel, los componentes del sistema y algunos problemas de optimizar tanto al compilar (puede que a veces el programa no funcione exactamente como se espera), aunque tardé dos semanas, conseguí tener un entorno gráfico listo para empezar a trabajar. Lo más importante: arrancaba en menos de la mitad de tiempo que un Windows recién instalado, las aplicaciones iban mucho más rápido, aprendí a medio-defenderme y lo demás fue buscar aplicaciones que reemplazaran las que yo más utilizaba (o probar con wine a ver si pitaba la flauta).

Como suite ofimática estaba OpenOffice (era muy parecida al StarOffice, de hecho fue precursor; tenía Firefox, y Thunderbird para el correo (lo cambié porque antiguamente utilizando Outlook, porque parece que cada vez que actualizan ese programa dan menos información al usuario); necesité un visor de fotos y encontré gqview y una vez que tenía lo necesario para trabajar encontré una amplia gama de programas para hacer mi experiencia de usuario mucho más llevadera (kontact, xpad, aMSN, xmms, mplayer, y muchos más).
Sólo quedaba un editor de texto, ya que una de mis aficiones preferidas era la programación, y aunque estuve con Kate un tiempo, la que realmente me convenció (aunque fui advertido, de que el camino no sería fácil) fue EMACS (y llevaba un par de años buscando un editor de texto para Windows, aunque sin éxito).

Lo único que echaba de menos son programas para edición de vídeo, y de hecho me he tirado unos cuantos años sin hacer ningún montaje grande por esto mismo (con muchos de los programas existentes se puede montar vídeo, pero no se consigue mucha estabilidad), para mí la balanza no tiraba tanto en ese sentido. Aunque parece ser que ahora con Openshot hay una esperanza.

Tras mi experiencia he de decir que las curvas de aprendizaje de Windows y GNU/Linux son muy diferentes, mientras que en Windows llega un punto en el que te estancas (aunque aprendes algo, pero ya sea por poco interés, por no querer indagar más, pereza, etc, ya no aprendes demasiado), en GNU/Linux nunca dejas de aprender cosas todos los días; aunque lo más importante es que lo considero un sistema altamente productivo: hago más cosas en menos tiempo y además no tengo estrés añadido (como cuando llevaba 3 días con Windows sin reiniciar, ahora mismo tengo un uptime (tiempo encendido) de 25 días y no hay pérdida de rendimiento), es un sistema seguro (en 6 años, sólo he tenido un problema de seguridad en uno de mis equipos directamente conectados a Internet (sin router) y fue por no instalar una actualización crítica del núcleo; en cambio con Windows no era la primera vez que malgastaba una tarde entera (o varios días) en intentar limpiar un virus que acababa de salir a la luz, el antivirus no se había enterado y se iba a comer mis datos; o trabajar durante un día para averiguar qué le pasa a un programa que ha dejado de funcionar de un día para otro y terminar formateando.

Es un sistema que me hace sentir más cómodo trabajando, y en mi tiempo de ocio, apenas hay sorpresas (ojo, que a veces se cuelga, y tiene sus pataletas, pero en mucha menor medida, y el 80% de las veces, en mi experiencia, ha sido problema de hardware; como curiosidad, la última vez que me pasó fue problema de un cable de corriente suelto en un disco duro SATA)

Terminal transparente para visualizar logs

Jueves, 5 de Agosto de 2010 Gaspar Fernández Sin comentarios

screenshot-01-08-2010-140805Es muy de 2002/2003, aunque todavía a muchos les gusta tener un pequeño terminal transparente en el fondo para ejecutar comandos o mostrar logs u otra información importante.

Aquí comentaré algunas soluciones que he encontrado y cómo obtenerlas.

xrootconsole

Es muy ligero y rápido. Y vale para mostrar logs en xroot; el fondo es supuestamente transparente, aunque si cambiamos el fondo veremos que no, ya que en la ventana de xrootconsole se mantendrá el fondo anterior. Está bien para hacer el apaño, pero no lo recomiendo. La forma de ejecutar xrootconsole es:

$ xrootconsole [fichero]

donde fichero es el que vamos a vigilar, la visualización se actualiza automáticamente con cada cambio que se observa en el archivo. Es ideal para ver /var/log/messages.

aterm

Muestra un terminal transparente, con muchas opciones, y que podemos ejecutar de la siguiente manera para mostrar las últimas líneas de dmesg en el escritorio:

$ aterm -fg black -geometry 100×10+0+0 -e watch –no-title -n10 -d ‘dmesg | tail’

donde:

-fg Indica el color de las letras
-geometry Indica la posición y dimensiones de la ventana: ancho x alto + x + y
-e Ejecuta el comando que especificamos a continuación (La referencia del comando watch la incluyo al final del post

Por supuesto podemos sustituir el comando que esta en negrita por lo que queramos mostrar.
Aún así, de esta forma aterm nos muestra decoración de ventana, barra de scroll y no es transparente. Esto lo podemos solucionar ejecutando aterm de la siguiente manera:

$ aterm -tr -bl -sb -fg black -geometry 100×10+0+0 -e watch –no-title -n10 -d ‘dmesg | tail’

-tr Ventana transparente
-bl Ventana sin borde
-sb Ventana sin barra de desplazamiento (scrollbar)

O, editando el archivo $HOME/.Xdefaults y añadiendo estas líneas

aterm*transparent:true
aterm*borderLess:true
aterm*scrollBar:false

El problema de aterm es que no admite sombra en las letras, por lo que la lectura sobre algunos fondos es algo complicada.

Eterm

Este emulador de terminal es el más completo y tiene más opciones, y por lo menos es el que soporta poner sombra en las letras, lo que proporciona una mejor visibilidad, y es el que aparece en la captura de pantalla que hay arriba. Para ello, lo podemos ejecutar de la siguiente forma:

Eterm –buttonbar 0 –scrollbar off -f white -n dmessenger -g 211×10+0+0 -O -0 -e watch –no-title -n10 -d ‘dmesg | tail’

–buttonbar 0 Elimina la barra de menú y botones superior
–scrollbar off Elimina la barra de desplazamiento.
-f white Especifica el color de las letras (blanco en este caso)
-n dmessenger Especificamos el nombre de la aplicación, la llamamos dmessenger. Será útil más adelante.
–O (letra o) Hace la ventana transparente
-0 (cero) Activa algunas optimizaciones de transparencia (sobre todo para ventanas que no se moverán demasiado), desactivar esta opción si no funciona correctamente o hay fallos en la ventana.
-x La pondré más adelante, elimina la decoración de la ventana y oculta el terminal de la barra de aplicaciones.
-g Indica la posición y dimensiones de la ventana: ancho x alto + x + y
-e Ejecuta el comando que especificamos a continuación (La referencia del comando watch la incluyo al final del post

Aunque veremos un problema, la decoración de la ventana, para ello hay varias soluciones, dependiendo del sistema en el que trabajemos, para muchos, la solución será incluir el parámetro -x:

$ Eterm -x –buttonbar 0 –scrollbar off -f white -n dmessenger -g 211×10+0+0 -O -0 -e watch –no-title -n10 -d ‘dmesg | tail’

(en negrita aparece el comando, en cursiva un comando opcional), aunque a veces el entorno de ventanas, entre ellos Fluxbox, el que uso actualmente, no se lleva muy bien con ese modo sin decoración de ventanas, y aunque se muestra bien, la ventana aparece sobre todas las demás (on top).
Para solucionar eso, nos vamos a complicar un poco la vida. Para ello, editamos el archivo $HOME/.fluxbox/apps y añadimos las siguientes líneas:

[app] (name=dmessenger)
[Deco] {NONE}
[Sticky] {yes}
[Layer] {10}
[end]

Y a la hora de ejecutar Eterm lo hacemos de la siguiente manera:

Eterm –buttonbar 0 –scrollbar off -f white -n dmessenger -g 211×10+0+0 -O -0 -e watch –no-title -n10 -d ‘dmesg | tail’ & sleep 2 && wmctrl -r dmessenger -b add,skip_taskbar

donde ejecutamos Eterm en segundo plano (al terminar el comando con &) y ejecutamos un sleep 2 (para esperar 2 segundos antes de ejecutar el siguiente comando), a continuación ejecutamos wmctrl donde,

-r dmessenger Especificamos el nombre de la ventana a ocultar; en este caso dmessenger
-b add,skip_taskbar Eliminamos la aplicación Eterm de la barra de aplicaciones, si queremos que la ventana aparezca también por debajo de las demás ventanas, podemos añadir la opción below de la siguiente forma: -b add,skip_taskbar,below

dmesg

En el ejemplo estamos ejecutando dmesg de la siguiente forma (con la ayuda de watch):

watch –no-title -n10 -d ‘dmesg | tail’

donde,

–no-title watch introduce un título donde indica el periodo de actualización, con este modificador lo eliminamos.
-n10 dmesg no está cambiando continuamente, por lo que escogemos un periodo de actualización de 10segundos (podemos modificar este parámetro como queramos)
-d ‘dmesg | tail’ Obtenemos los últimos 10 mensajes del kernel, podemos incluir un modificador -n4 a tail para obtener sólo las últimas 4.

Descargar automáticamente todos los programas de Redes

Domingo, 9 de Mayo de 2010 Gaspar Fernández Sin comentarios

neuron
Apenas veo la televisión, pero hay ciertos programas que son interesantes y merecen la pena como Redes. Y tampoco me gusta verlos desde la web ya que Flash es muy lento, y me gusta tener lo que veo echar hacia atrás y hacia alante (como hace mplayer) y verlo cómodamente.

Para ello, lo más cómodo es descargarlos, pero cómo descargarlos si tengo que bajarlos uno a uno (y son muchos), y tengo que mirar dónde está el archivo de vídeo (lo primero que nos podemos bajar a mano es una archivo de metadatos que nos dirá dónde está el vídeo), es una tarea muy lenta para hacerla a mano. ¿ Por qué no automatizar el proceso ?

Vemos que desde la web de Redes para la Ciencia nos podemos descargar los programas desde 2008 (lástima que los anteriores no estén disponibles en vídeo desde esta web), y éstos están alojados en Smartplanet (blip.tv). Con estos datos, he confeccionado este script (aún en beta, no es muy estable, ni está optimizado, pero nos hace el apaño).

Si observamos los pasos intermedios de este script, y vemos el fichero de metadatos por dentro, veremos cómo podemos ver más información, descargar el archivo en mov o mp4 (a gusto del consumidor), también encontramos un resumen del programa; os invito a hacer pruebas y comentarlas en este post.

Una posible mejora a corto plazo, sería poner en orden la variable get_years y que, si descubre que varios capítulos han sido descargados, no intente bajar más (a la hora de descargar el último capítulo también con el script), o incluso almacenar en un archivo el número del último capítulo descargado, para así buscar el siguiente en la siguiente ejecución… todo se andará; por ahora, os dejo el script así, que con un poco de cuidado funciona bien.

Y otra cosa más, con un poco de suerte, para el año que viene, sólo tendremos que añadir a la variable get_years el link del blog con los enlaces a los capítulos del año 2011.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#/bin/bash

get_years="http://www.redesparalaciencia.com/programas-2009 http://www.redesparalaciencia.com/programas-de-2008 http://www.redesparalaciencia.com/programas-2010"

for i in $get_years
do
    echo Descargando $i ...
    wget -q -O /tmp/listado_year $i
    echo Descargado
    # Hay algunas URLS que salen con ../
    caps_year=`cat /tmp/listado_year | grep 'href' | grep '>Redes [0-9]' | sed -e 's/\.\.\//http:\/\/www\.redesparalaciencia\.com\//g' -n -e 's/\(.*\)href=\"\([^\"]*\)\"\(.*\)/\2/p'`
#   caps_year=`cat /tmp/listado_year | grep 'href' | grep '>Redes [0-9]' | grep -o '"http://[a-zA-Z0-9.\/\-]*"' | cut -d\" -f2`
    for j in $caps_year
    do
        echo Descargando metadatos del episodio...
        wget -q -O /tmp/episodio $j
        episodio=`grep -o 'http://blip.tv/rss/flash/[0-9]*' /tmp/episodio`
        wget -O /tmp/metadatos $episodio
        echo Metadatos descargados
        video=`awk -F "\"" '/media\:content/ {print $2}' /tmp/metadatos | grep flv`
        titulo=`sed -n 's/<media:title>\(.*\)<\/media:title>/\1/p' /tmp/metadatos`
        if [ -r "$titulo.avi" ] || [ -r "$titulo.flv" ]
            then
            echo "Episodio $titulo ya existe. Descartando."
        else
            echo "Descargando episodio... $titulo"
# Podemos quitar el -q para ver cómo va la descarga.
            wget -q -O "$titulo.flv" $video
            echo "Recomprimiendo episodio..."
            ffmpeg -i "$titulo.flv" -vcodec msmpeg4v2 -b 1200k -acodec mp2 -ab 128k "$titulo.avi"
        fi
    done
done

Requerimientos: wget, sed, awk, ffmpeg (si queréis recomprimir los programas) y algunos gigas libres de disco duro (unos 20 o así si queremos recomprimir).

Notas:

  • La compresión no está muy optimizada, tal vez comprimamos con más bitrate del que debemos, pero bueno. Si no queremos comprimir, basta con comentar la línea de ffmpeg, aunque si queremos verlo en algún reproductor debemos dejarla. El codec de audio (acodec), es mp2, ya que el mp3 no me funcionaba bien, libmp3lame debe estar instalado y ffmpeg compilado con soporte para él, aún así, probad antes).
  • Soy consciente de que hay demasiado sed, awk y scripts de sobra, pero fue un script rápido y tampoco importa mucho el tiempo que pasemos parseando los metadatos.
  • No hay control de errores, si falla algo y el script se vuelve loco… yo no garantizo nada :)
  • Por ahora, si un archivo no se baja del todo, debemos eliminarlo para que se baje de nuevo por completo.

Espero que disfrutéis del programa.

Foto: MikaNet (Flickr)

Tuberías con nombre para comunicación entre procesos

Domingo, 19 de Julio de 2009 blakeyed 2 comentarios

Las tuberías con nombre son un método de comunicación FIFO entre procesos (también se les llama fifos). FIFO son las siglas de First In First Out, es decir, el primero que llega es que primero que se marcha, como en una cola, el primero que llega es el que antes termina.

Observad lo que hacen las macros depura_int y depura_string, nos darán el número de línea y el archivo donde están, así como el nombre de la variable y el valor que tiene en ese momento.

Normalmente las tuberías son anónimas, aunque el hecho de tenerlas con un nombre en nuestro sistema de ficheros puede sernos de gran utilidad. Como ejemplo, podemos verlo en funcionamiento en la siguiente imagen:

Cómo hacer una pipe con nombre en 1 minuto

Cómo hacer una pipe con nombre en 1 minuto

Primero vemos el terminal de abajo, en el que se ejecuta lo siguiente:

1
2
$ mkfifo prueba
$ cat prueba

Seguidamente en el otro terminal se escribe lo siguiente:

1
$ echo "Esto es una prueba" > prueba

Automáticamente el texto “Esto es una prueba” aparece en el primer terminal. ¡Hemos logrado enviar un mensaje!

De la misma forma podemos programar aplicaciones que utilicen estas características de forma muy fácil en casi cualquier lenguaje de programación, para los ejemplos utilizaré C. Debemos hacer dos programas, uno que escriba en la tubería (pipe) y otro que lea de ella. Empezamos por pipewrite.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
  FILE *mipipe;
  char buffer[128];
  int i=0;

  if (mkfifo("pipetest", S_IWUSR |  /* El usuario puede escribir */
                 S_IRUSR |  /* El usuario puede leer */
                 S_IRGRP |  /* El grupo puede leer */
                     S_IROTH    /* Otros pueden leer */
         )!=0)
    printf ("Hubo un problema al crear la pipe\n");

  mipipe=fopen("pipetest", "w"); /* Lo abrimos como un fichero normal y corriente */

  /* Con esta línea leemos hasta que se cierre la tubería por el otro */

  while (i<10)
    {
      sprintf(buffer, "CADENA ENVIADA Número: %i\n", i+1);
      fputs(buffer, mipipe);
      i++;
    }

  fclose(mipipe);       /* Cerramos la tubería por aquí también */

Y ahora pipecilla.c (o el programa que leerá la pipe):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
  FILE *mipipe;
  char buffer[128];
  if (mkfifo("pipetest", S_IWUSR |  /* El usuario puede escribir */
                 S_IRUSR |  /* El usuario puede leer */
                 S_IRGRP |  /* El grupo puede leer */
                     S_IROTH    /* Otros pueden leer */
         )!=0)
    printf ("Hubo un problema al crear la pipe\n");

  mipipe=fopen("pipetest", "r"); /* Lo abrimos como un fichero normal y corriente */

  /* Con esta línea leemos hasta que se cierre la tubería por el otro */
  while (!feof(mipipe))      
    {
      if (fgets(buffer, 128, mipipe))
      printf ("RECIBIDO: %s", buffer);
    }

  fclose(mipipe);       /* Cerramos la tubería por aquí también */
}

Ahora compilamos y ejecutamos en terminales diferentes de nuevo:
Probando pipes
En el terminal de pipewrite.c, al ejecutar el programa da un mensaje de error, es porque la pipe ya existe (se creó en el programa anterior).

Esta forma de comunicación es unidireccional, puede ser últil por ejemplo para publicar el estado de un programa (un reproductor de audio podría publicar la canción que está sonando como en xmms-infopipe), o para modificar el comportamiento de un software mientras éste está en ejecución. Pero si queremos que nuestras aplicaciones dialoguen (en full-duplex), debemos tener dos pipes simultáneas, en ese caso, la aplicación 1, por ejemplo deberá leer en la tubería 1 y escribir en la tubería 2; y la aplicación 2, deberá escribir en la tubería 1 y leer en la tubería 2.

Visita otras webs de la red