Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas
Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas

Pruebas unitarias en Python: unittest

unittest, también conocido como PyUnit, pertenece a ese grupo de herramientas conocido como zUnit. Un conjunto de frameworks con base en SUnit para Smalltalk, de Kent Beck.
El uso de unittest es sencillo, cuando menos al tener práctica. Para cada uno de los grupos de pruebas, debemos de crear una clase que herede de unittest.TestCase, y desde ahí, ir creando métodos que comiencen con test. Cada uno de estos métodos será cada una de las pruebas que realizaremos. El resultado de cada una puede ser:
  • OK, prueba exitosa.
  • FAIL, la prueba ha fallado y se lanza una excepción AssertionError.
  • ERROR, la prueba ha fallado, pero se lanza una excepción distinta de AssertionError.
Aunque como en programación Python, se puede hacer uso de clausulas if, o emplear try/except, la clase TestCase tiene ya implementados una serie de métodos que facilitan las comprobaciones.

Métodos de comprobación

  • assertAlmostEqual(first, second, places=7, msg=None)
    Comprueba que los objetos pasados sean iguales hasta el decimal pasado como parámetro.
  • assertEqual(first, second, msg=None)
    Comprueba que los objetos pasados como parámetros sean iguales.
  • assertFalse(expr, msg=None)
    Comprueba que la expresión sea falsa.
  • assertNotAlmostEqual(first, second, places=7, msg=None)
    Comprueba que los objetos pasados como parámetros no sean iguales hasta el decimal pasado como parámetro.
  • assertNotEqual(first, second, msg=None)
    Comprueba que los objetos pasados como parámetros no sean iguales.
  • assertRaises(excClass, callableObj, *args, **kwargs)
    Comprueba que al llamar al objeto callableObj con los parámetros definidos en *args y **kwargs se lanza una excepción de tipo excClass.
  • assertTrue(expr, msg=None)
    Comprueba que la expresión sea cierta.
  • assert_(expr, msg=None)
    Comprueba que la expresión sea cierta.
  • fail(msg=None)
    Falla inmediatamente.
  • failIf(expr, msg=aquí ponemos lo que queramos desplegar)
    Falla si la expresión es cierta.
  • failIfAlmostEqual(first, second, places=7, msg=None)
    Falla si los objetos pasados como parámetros son iguales hasta el decimal pasado como parámetro.
  • failIfEqual(first, second, msg=None)
    Falla si los objetos pasados como parámetros son iguales.
  • failUnless(expr, msg=None)
    Falla a menos que la expresión sea cierta.
  • failUnlessAlmostEqual(first, second, places=7, msg=None)
    Falla a menos que los objetos pasados como parámetros sean iguales hasta el decimal pasado como parámetro.
  • failUnlessEqual(first, second, msg=None)
    Falla a menos que los objetos pasados como parámetros sean iguales.
  • failUnlessRaises(excClass, callableObj, *args, **kwargs)
    Falla a menos que al llamar al objeto callableObj con los parámetros definidos por *args y **kwargs se lance una excepción de tipo excClass.

Referencias

Leer más

android-sdk-linux emulator: error=2

Hoy estaba haciendo unas mejoras en una de las APPs que tengo disponibles para Android y tras instalar todo el sistema Eclipse + Android SDK en mi nuevo equipo, creo una nueva máquina. En este caso, y para dar soporte a las mejoras que trae de pantalla, creé un dispositivo de tipo Nexus 5. Tras crearlo, decido iniciarlo para ver cómo se comporta la APP y obtengo el siguiente error,

Starting emulator for AVD 'Nexus_5'
Failed to start emulator: Cannot run program "/home/javier/Eclipse/android-sdk-linux/tools/emulator": error=2, No existe el archivo o el directorio
El error no tiene nada que ver con la versión de Android instalada ni de la API, sino con un fallo de librerías en sistemas de 64 bits. Tras investigar un poco, obtengo la solución,
shell> apt-get install libncurses5:i386 \
                       libstdc++6:i386 \
                       zlib1g:i386
Tras instalar los nuevos paquetes, las máquinas Android emuladas ya arrancan sin problemas.
Leer más

Instalación de SonarQube en GNU/Linux

Hace unos días un compañero y amigo, +Celso Conde Pérez, me preguntó si conocía SonarQube.
Para los que no lo sepáis, SonarQube es una plataforma centralizada de evaluación de código. Es software libre, lo cual está genial, y permite la evaluación estática de código según patrones preestablecidos. El objetivo es garantizar la calidad del código escrito. En El Mundo en Bits hablamos hace tiempo de una herramienta similar, rats, y puedes leer el artículo aquí. Digo similar, ya que Sonar cubre muchos más aspectos.
Puesto que últimamente estoy enfrascado en algunas tareas de desarrollo de scripts y código, decidí probar esta herramienta, ya que trae soporte para multitud de lenguajes de programación (python, php, java, etc.). Así que lo primero fue levantar una máquina virtual para poder instalar el servidor web. Con la máquina levantada simplemente seguí las instrucciones de instalación paso a paso.
  1. Instalación de la base de datos
    Aunque Sonar trae por defecto una base de datos embebida, tengo más experiencia y me gusta manejar los datos desde un MySQL. En este caso empleé para la máquina un sistema CentOS, así que,
    shell> yum install mysql-server
    
    Finalizada la instalación arrancamos el servicio,
    shell> service mysqld start
    
    Y creamos la base de datos que vamos a emplear en sonar, así como un usuario con permisos,
    mysql> CREATE DATABASE sonar;
    mysql> CREATE USER 'sonar' IDENTIFIED BY 'sonar';
    mysql> GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar';
    
  2. Instalar el servidor SonarQube
    Lo primero que tenemos que hacer es descargar la última versión del servidor. Para ello, desde la página oficial, sección descarga lo tenemos (la versión actual la puedes descargar desde aquí).
    shell> cd /tmp
    shell> wget dist.sonar.codehaus.org/sonarqube-4.5.1.zip
    
    A continuación lo descomprimimos,
    shell> unzip sonarqube-4.5.1.zip
    
    Y lo movemos a /etc, como dice en la guía de instalación.
    shell> mv /tmp/sonarqube-4.5.1 /etc/sonarqube
    
    Con esto ya tenemos el sistema SonarQube instalado y listo para poder usarse, aunque antes, debemos de configurar el acceso a base de datos. Para ello, editamos el fichero de propiedades de sonar, /etc/sonarqube/conf/sonar.properties y establecemos los parámetros de acceso a base de datos. El resto de la configuración nos sirve por defecto.
    ...
    #sonar.embeddedDatabase.port=9092
    ...
    sonar.jdbc.username=sonar
    sonar.jdbc.password=sonar
    sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
    ...
    sonar.web.host=0.0.0.0
    sonar.web.port=9000
    ...
    
  3. Arrancar el sistema
    Con todo listo y configurado ya podemos arrancar el servidor Sonar.
    shell> /etc/sonarqube/bin/linux-x86-64/sonar.sh start
    
    La carpeta dentro de bin a la que tendréis que acceder depende directamente del sistema sobre el que esté montando. En mi caso, es un sistema de 64 bits, por lo tanto empleo el script de 64bits.
    Tener presente que en el primer arranque hace un despliegue completo de toda la base de datos y esto, según el ordenador, podrá llevar más o menos tiempo. En mi caso, llevó algo más de 2 minutos, por lo que ser pacientes. El progreso de arranque lo podéis observar en el fichero de log (/etc/sonarqube/logs/sonar.log).
SonarQube está escrito en java, lo que hace necesario, para que todo funcione, tener instalado java en el sistema. Si no lo tenéis ya, habrá que ir a la web de Oracle y descargar la versión que corresponda del jdk e instalarlo. Por ejemplo, para la máquina en cuestión, descargué el jdk-8u25-linux-x64.rpm y tras su instalación el sistema Sonar ya pudo arrancar perfectamente.

Con la instalación del servidor Sonar, únicamente tenemos la parte centralizada de evaluación y análisis de código, pero tenemos pendiente todavía la configuración de los plugins de soporte de diversos lenguajes y también el cliente (sonar-runner), que analizará y enviará el código al servidor. Estas partes ocuparan las próximas entradas.
Leer más

If corto en python

Hoy es uno de esos días en los que estoy programando y me interesa simplificar el código, pero necesito igualmente condicionales. Desde la época de C, una de las formas de realizar asignaciones condicionales sencillas era con un 'if corto', o lo que es lo mismo, pasar de algo tal que esto,
...
country = ''
if(lang == 'es') {
    country = 'ES'
} else {
    country = 'EN'
}
...
A algo como esto,
...
country = (lang == 'es' ? 'ES' : 'EN')
...
Este tipo de sentencias se aplican en muchos, por no decir todo tipo de lenguajes de programación, no sólo C. Por ejemplo en PHP,
...
$value = ($userid == $user['userid'] ? 'yes' : null);
...
Sin embargo, cuando quiero aplicar esta misma fórmula en Python, no me funciona. Esto no significa que Python no tenga un 'if acortado', sino que lo implementó de otra forma,
...
host = {
   'name': (tmp['dns'] if tmp.has_key('dns') else tmp['name'])
}
...
Como podéis observar en vez de usar el tradicional (a==B ? x : y), lo que hace es la asignación y luego al comprobación: (x if a==b else y) y suprime a la vez los operadores reducidos ? y :
Tenerlo presente si vais a programar en Python ;-)
Leer más

Cómo crear un daemon en python

Una de los grandes problemas que suelen presentarse a nivel de programación de sistemas es la creación, de forma correcta, de un daemon o servicio que se ejecute en segundo plano y que haga el trabajo correctamente.
La forma más cutre que existe de hacer esto es ejecutando el comando y pasarlo luego a segundo plano, dejando así el software en cuestión trabajando, pero no en forma de daemon.
Hoy vamos a ver cómo programar un daemon en Python.
Para ello, lo primero que necesitamos es asegurarnos de que las librerías de Python necesarias están instaladas y en caso contrario, instalarlas. Una vez instaladas, ya podemos comenzar a programar el servicio de forma sencilla y eficiente.

shell> apt-get install python-daemon python-lockfile
En este caso, lo que vamos a realizar es un programa trivial y sin lógica, pero que nos servirá de ejemplo. A continuación os dejo el código.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import time
from daemon import runner

class App():
   def __init__(self):
      self.stdin_path      = '/dev/null'
      self.stdout_path     = '/dev/tty'
      self.stderr_path     = '/dev/tty'
      self.pidfile_path    =  '/var/run/test.pid'
      self.pidfile_timeout = 5

   def run(self):
      i = 0
      while True:
         logger.info("message %s" %i++)
         i += 1
         time.sleep(1)

if __name__ == '__main__':
   app = App()
   logger = logging.getLogger("testlog")
   logger.setLevel(logging.INFO)
   formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s")
   handler = logging.FileHandler("/var/log/test.log")
   handler.setFormatter(formatter)
   logger.addHandler(handler)

   serv = runner.DaemonRunner(app)
   serv.daemon_context.files_preserve=[handler.stream]
   serv.do_action()
Como veis, el código es sencillo y con él ya creamos un pequeño servicio que se ejecutará en segundo plano y que se encargará de escribir cada segundo un mensaje en el log (fichero /var/log/test.log). A mayores también controla perfectamente que sólo haya una instancia del servicio ejecutándose al mismo tiempo (fichero de bloqueo /var/run/test.pid). Y como era de esperar, están incluidos por defecto aquellos métodos de arranque y parada de servicio (start, stop y restart). Para probar el funcionamiento del daemon, podemos hacerlo tal que así,
shell> python /usr/local/bin/test.py
usage: test.py start|stop|restart

shell> python /usr/local/bin/test.py start
started with pid 32547

shell> tail -f /var/log/test.log
2014-04-04 10:00:17,342 - testlog - Info message 3
2014-04-04 10:00:18,343 - testlog - Info message 4
2014-04-04 10:00:19,344 - testlog - Info message 5
2014-04-04 10:00:20,346 - testlog - Info message 6
2014-04-04 10:00:21,347 - testlog - Info message 7

shell> python /usr/local/bin/test.py stop
Terminating on signal 15
Por supuesto, para dejarlo listo y poder tenerlo instalado como un servicio en nuestro sistema, lo único que no falta es un fichero de arranque (/etc/init.d/test). Para ello, creamos uno muy sencillo.
#!/bin/bash

# /etc/init.d/test

### BEGIN INIT INFO
...
### END INIT INFO

case "$1" in
   start)
      echo "Starting server"
      python /usr/local/bin/test.py start 
      ;;

   stop)
      echo "Stopping server"
      python /usr/local/bin/test.py stop
      ;;

   restart)
      echo "Restarting server"
      python /usr/local/bin/test.py restart
      ;;

   *)
      echo "Usage: /etc/init.d/demonioprueba.sh {start|stop|restart}"
      exit 1
      ;;
esac
exit 0
Y ya podemos levantar nuestro servicio cuando sea necesario. Lógicamente, dentro del método run, de la clase App habrá que meter el código necesario para que el servicio tenga sentido, pero eso ya es cosa de cada uno. Aquí la idea era enseñar a levantar un servicio escrito en Python.
Leer más

Cómo ejecutar comandos externos desde Perl

Si empleas GNU/Linux para trabajar, saber Perl y Python suele ser interesante ya que te permite crear pequeños script que interaccione muy directamente con el sistema. Además de todo eso, Perl es un gran lenguaje de programación, permite realizar numerosas tareas en pocas líneas y por lo general es simple de manejar y comprender.
Hoy tuve la necesidad, en un script perl de procesamiento de correos, de ejecutar comandos externos y tocó realizar una búsqueda en Google de cómo realizar lo que me interesaba. Yo necesitaba ejecutar un comando y obtener la salida del mismo en una variable. Finalmente lo realicé con backticks, pero aproveché para recordar otros métodos de ejecución de comandos que voy a continuación a compartir con vosotros.
  • system
    Se emplea para ejecutar comandos del sistema en los que no interesa capturar la salida del mismo.
    system acepta el paso de un comando con argumentos directamente, así como el paso de variables como argumentos a la hora de ejecución. Aunque no captura la salida del comando, sí permite saber si éste se ejecutó correctamente o no (variable $?) y en caso de fallo, saber el error devuelto (variable $!).
    ...
    system($command, @args);
    if ($?) {
       print "command failed: $!\n";
    }
    ...
    
  • exec
    Ejecuta el comando especificado, pero a diferencia de system, exec nunca devuelve al programa de llamada, excepto que la llamada falle por que el comando no exista.
    Al igual que system, los argumentos pueden ser un array.
    ...
    if (($pid = fork()) == 0) {
       exec($command, @args);
    }
    waitpid($pid, 0);
    ...
    
  • open
    Se emplea si quieres que tu script importe o exporte datos externos mediante un pipe. Existen dos formas de ejecutarlo,
    • open("command | ")
      Para capturar datos desde la ejecución de un comando.
    • open(" | command")
      Para enviar datos a un programa externo desde Perl.
    ...
    open (DST, '-|', $pdftk, @pdf, 'cat', 'output', $final);
    close DST;
    ...
    
  • backticks
    Hay que emplear este método en caso de que deseemos capturar a una variable la ejecución de un comando del sistema. En método de funcionamiento es similar al mismo empleo en bash. Al igual en systema, $? almacena el estado de salida del comando.
    ...
    $random = `< /dev/urandom tr -dc A-Za-z0-9_.,@ | head -c12; echo n`;
    ...
    
Leer más

rats, auditando código fuente

rats es una de esas utilidades que no se suelen emplear y que puedan dar muy buenos resultados en poco tiempo a la hora de programar. La verdad es que yo no conocía este tipo de herramientas (debe ser por la falta de costumbre de programar), pero son muy útiles, ya que permiten detectar fallos triviales en el código, de forma automática. Los típicos con las variables no inicializadas, cast's entre tipos de datos diferentes sin límites, etc.
rats tiene soporte para 5 lenguajes de programación, c, perl, ruby, python y php, con una amplia base de datos de fallos comunes, especialmente c, con 334 entradas. La forma de funcionar típica, es indicarle el tipo de lenguaje de programación (sino lo autodetecta) y los ficheros de entrada. También se le puede decir que saque la salida en formato xml o html. Por defecto, los fallos si no se indica nada, los saca desde la consola.
Al termina de analizar, ofrece unos resultados y el tiempo que tardó en procesar todos los ficheros. Los resultados los agrupo por el tipo de vulnerabilidad que tiene (alta, medio o baja), indicando las líneas en las que se encuentra el fallo, así como información de mismo.
Un ejemplo de ejecución puede ser el que sigue, con sus correspondientes resultados.
shell> rats --language c --input *.c --html > salida.html
Y los resultados obtenidos (copiado del formato html),
------------
Entries in perl database: 33
Entries in ruby database: 46
Entries in python database: 62
Entries in c database: 334
Entries in php database: 55

Analyzing checks_agent.c
Analyzing checks_aggregate.c
Analyzing checks_calculated.c
Analyzing checks_db.c
Analyzing checks_external.c
Analyzing checks_internal.c
Analyzing checks_ipmi.c
Analyzing checks_simple.c
Analyzing checks_snmp.c
Analyzing checks_ssh.c
Analyzing checks_telnet.c
Analyzing poller.c

RATS results

Severity: High
Issue: fixed size global buffer
Extra care should be taken to ensure that character arrays that are allocated on the stack are used safely. They are prime targets for buffer overflow attacks.
    File: checks_agent.c
    Lines: 49
    File: checks_aggregate.c
    Lines: 297
    File: checks_calculated.c
    Lines: 311
    File: checks_internal.c
    Lines: 46 47
    File: checks_ipmi.c
    Lines: 772 862
    File: checks_simple.c
    Lines: 28 29 30 31
    File: checks_snmp.c
    Lines: 248 468 838 839 840 841 842 843
    File: checks_ssh.c
    Lines: 86 343
    File: checks_telnet.c
    Lines: 319 394 516
    File: poller.c
    Lines: 347 447
Severity: Medium
Issue: read
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
    File: checks_telnet.c
    Lines: 72

Inputs detected at the following points

Total lines analyzed: 5449
Total time 0.007437 seconds
732687 lines per second
------------
La verdad es que es una herramienta interesante si el lenguaje de programación está soportado para controlar los tipos de fallos más comúnmente conocidos y poder corregirlos. Sin duda, ayudará a mejorar la seguridad del código final. Por supuesto, al ser código libre, las bases de datos de vulnerabilidades se pueden seguir mejorando, así como emplear otras conocidas y compatibles (opción --database).
Leer más

acovea, flag's de optimización

¿Programas en C/C++? Pues esto te puede interesar.
Todo el mundo sabe la importación de optimizar el código. La optimización de código se consigue desde la primera a la última línea del mismo, sin embargo si lo que necesitas es todavía más optimización, el compilar gcc/g++ tiene una serie de flag's muy interesantes que permiten optimizar todavía más el código. Gracias a estos flag's, se puede aumentar el tamaño del binario final incluyendo librerías dinámicas o sacar una opcimización mayor para un tipo de procesador concreto. El problema suele ser siempre el mismo: ¿qué flag's empleo?
Hay un artículo maravilloso en Debian Administration que explican cómo emplear acovea, un potente analizador de código que te indica de forma simple cuales son las mejoras de optimización que puedes pasarle a tu código para mejorar su rendimiento.
Vamos a partir del mismo código del ejemplo y explicar paso a paso cómo optimizar los flag's de gcc para obtener un mayor rendimiento, incluso en códigos muy sencillos.
#include<stdio.h>

int main (int argc, char *argv[]) {
int i = 1, num;
int j, k;

for (num = 2; num < 32768; num++) {
   while (i <= num) {
      k = 0;
      if (num % i == 0) {
         j = 1;
         while (j <= i) {
            if (i % j == 0)
               k++;
            j++;
         }
      if (k == 2)
         printf ("%d is prime\n", i);
   }
   i++;
   }
}
return 0;
}
Primero vamos a ver qué sucede ejecutándose con una compilación normal.
shell> gcc -o ejemplo ejemplo.c
shell> time ./ejemplo
...
real 0m3.718s
user 0m3.700s
sys 0m0.008s
Y ahora que ya tenemos unos tiempos de referencia, vamos a emplear la herramienta acovea para ver cómo poder optimizar el código para nuestro procesador.
Primeramente la instalamos.
shell> apt-get install acovea
Luego, nos vamos al directorio /usr/share/libacovea/config que es donde están almacenados todos los perfiles de acovea con los que puede optimizar los flag's según la versión de nuestro procesador. En mi caso, voy a emplear gcc34_intel.acovea, con lo que lanzamos acovea tal que así,
shell> runacovea -config gcc34_intel.acovea -input ejemplo.c
Esta ejecución tardará un poco en terminar, ya que internamente está empleando muchas iteraciones y compilaciones de 'ejemplo.c' para ver cómo poder optimizarlo. Al finalizar obtendremos una salida similar a la siguiente,
Acovea completed its analysis at 2012 Oct 26 19:55:09

Optimistic options:
     -fno-cprop-registers  (1.951)
 -foptimize-sibling-calls  (1.951)
         -frerun-loop-opt  (1.537)
            -falign-loops  (1.537)
       -finline-functions  (1.951)
   -minline-all-stringops  (1.537)

Pessimistic options:
             -fforce-mem  (-1.769)
     -fmove-all-movables  (-1.769)
       -freduce-all-givs  (-1.769)
            -mfpmath=387  (-1.769)
             -march=i386  (-1.769)
             -march=i586  (-1.769)
         -march=pentium4  (-1.769)

Acovea's Best-of-the-Best:
gcc -lrt -lm -std=gnu99 -O1 -fno-merge-constants -fno-thread-jumps -fno-delayed-branch -fno-crossjumping -foptimize-sibling-calls -fcse-follow-jumps -frerun-loop-opt -fcaller-saves -fschedule-insns2 -fsched-spec -freorder-functions -falign-loops -falign-labels -falign-functions -finline-functions -frename-registers -funroll-loops -mno-push-args -maccumulate-outgoing-args -minline-all-stringops -D__NO_MATH_INLINES -mfpmath=sse -D__NO_MATH_INLINES -fno-math-errno -funsafe-math-optimizations -ffinite-math-only -finline-limit=600 -o /tmp/ACOVEA0F868709 file.c 

Acovea's Common Options:
gcc -lrt -lm -std=gnu99 -O1 -foptimize-sibling-calls -finline-functions -minline-all-stringops -o /tmp/ACOVEA61909725 file.c 

-O1:
gcc -lrt -lm -std=gnu99 -O1 -march=pentium4 -o /tmp/B013 file.c 

-O2:
gcc -lrt -lm -std=gnu99 -O2 -march=pentium4 -o /tmp/F7E6 file.c 

-O3:
gcc -lrt -lm -std=gnu99 -O3 -march=pentium4 -o /tmp/AFFD file.c 

-O3 -ffast-math:
gcc -lrt -lm -std=gnu99 -O3 -march=pentium4 -ffast-math -o /tmp/D6AA file.c

-Os:
gcc -lrt -lm -std=gnu99 -Os -march=pentium4 -o /tmp/F596 file.c 


A relative graph of fitnesses:

 Acovea's Best-of-the-Best: **************************         (179)
 Acovea's Common Options:   **************************         (181)
  -O1:                      *****************************      (191)
  -O2:                      *****************************      (193)
  -O3:                      ******************************     (197)
  -O3 -ffast-math:          *******************************    (199)
  -Os:                      ********************************** (211)

Acovea is done.
Leer más

Arrays asociativos en bash

Como todos sabréis, bash tiene su propio lenguaje de programación con un intérprete debajo que permite ejecutar pequeños scripts o programas de mayor o menor complejidad y emplearlo así como un verdadero lenguaje de programación. bash está 100% integrado en el núcleo del sistema GNU/Linux por lo que permite una perfecta integración con todo el sistema.
Una de las cosas que descubrí recientemente programando scripts fue la forma de emplear arrays asociativos, así que la voy a compartir.
#!/bin/bash
declare -A array

#Array asociativo de pareja (clave, valor).
array[192.168.1.1]="host1"
array[192.168.1.2]="host2"
array[192.168.1.3]="host3"
array[192.168.1.4]="host4"

echo "Para la IP $1, le corresponde el equipo ${array[$1]}"
Tras esto, al ejecutarlo obtenemos la siguiente salida,
shell> array.bash 192.168.1.2
Para la IP 192.168.1.2, le corresponde el equipo host2
Y también podemos conseguir que se nos imprimar todas las parejas, clave-valor que hay,
#!/bin/bash
declare -A array

array[192.168.1.1]="host1"
array[192.168.1.2]="host2"
array[192.168.1.3]="host3"
array[192.168.1.4]="host4"

for hostname in "${array[@]}"
do
   echo $hostname
done
Leer más

Listado de followers/friends en twitter

Twitter es una red social que sirve para compartir pequeñas noticias o enlaces y además sirve para otras muchas cosas, como aprender de relaciones sociales y obtener cierta información sobre 'amistades' de tu contactos o de otros contactos. Una de las cosas que está más de moda hoy en día son las gráficos de relaciones y poder saber a cuantos 'amigos' estás de otra persona. Twitter y linkedin sirven para hacer éste tipo de 'experimentos sociales'.
A continuación os dejo un pequeño trozo de código, escrito en perl, empelando la librería "Net::Twitter", disponible desde repositorios debian, para poder acceder a la lista de personas que te siguen o a las que sigues, pero también de otras cuentas.
#!/usr/bin/perl

use Net::Twitter;

unless($ARGV[0]){
  print "Usage: $0 {user}\n";
  exit 1;
}

my $myuser = $ARGV[0];

my $CONSUMER_KEY = 'XXXX';
my $CONSUMER_SECRET = 'XXXX';
my $ACCESS_KEY = 'XXXX';
my $ACCESS_SECRET = 'XXXX';

my $nt = Net::Twitter->new(
  traits              => [qw/OAuth API::REST/],
  consumer_key        => $CONSUMER_KEY,
  consumer_secret     => $CONSUMER_SECRET,
  access_token        => $ACCESS_KEY,
  access_token_secret => $ACCESS_SECRET,
);

print "List of followers:\n";

for (my $cursor = -1, my $r; $cursor; $cursor = $r->{next_cursor}){
  $r = $nt->followers({ screen_name=>$ARGV[0],cursor => $cursor });
  push @followers, @{ $r->{users} };

  for my $user (@followers){
    print "\t@".$user->{'screen_name'}." (".$user->{'name'}.")\n";
  }
}

print "\nList of friends:\n";

for(my $cursor = -1, my $r; $cursor; $cursor = $r->{next_cursor}){
  $r = $nt->friends({screen_name=>$ARGV[0],cursor=>$cursor});
  push @friends, @{ $r->{users} };

  for my $user (@friends){
    print "\t@".$user->{'screen_name'}." (".$user->{'name'}.")\n";
  }
}
El método de empleo es muy simple, tras configurar la autenticación OAuth sólo queda pasarle el nombre del usuario de Twitter del que deseas averiguar la lista de amigos y seguidores que tiene. Tras una breve espera, los tendrás.
shell> listado j_tlopez
List of followers:
 @fribadas (Francisco J. Ribadas)
 @trasno0 (Alex Pereiro)
 @iSepti (ivan)
 @pepellou (José Doval)
 ...

List of friends:
 @Snort (Snort)
 @googlereader (Google Reader)
 @Linux (Linux)
 @climagic (Command Line Magic)
 @googlecalendar (Google Calendar)
 ...
Qué hacer con esos datos y cómo explotarlos, de momento es cosa tuya ;-)
Leer más

Acceso a MySQL desde código C++

Una de los problemas más complicados a la hora de crear código, según el lenguaje de programación, es la unión de un servicio con una base de datos que provea los datos. En un post anterior, se vio cómo realizarlo muy fácilmente con Ruby, en esta ocasión veremos cómo hacerlo también de forma sencilla con C++, usando librerías del propio sistema, para así poder trasladar el servicio a otros equipos, con la simple instalación de dichas librerías.
En el equipo de compilación será necesaria la instalación de la librería de desarrollo libmysql++-dev, mientras que en los restantes cliente que usen el código final, únicamente la librería. En sistemas debian/ubuntu, la instalación será,
shell> apt-get install libmysql++-dev
shell> apt-get install libmysql++3
Y para usar dichas funciones en nuestro programa, únicamente habrá que realizar el include correspondiente.
#include <mysql++/mysql++.h>

Un ejemplo de código simple que establece una conexión, obtiene la columna email de la tabla usuarios y cierra la conexión antes de terminar, es el que sigue.
/*Cliente MySQL C++*/
#define MYSQLPP_MYSQL_HEADERS_BURIED
#include <mysql++/mysql++.h>
#include <syslog.h>

int main (){
   mysqlpp::Connection conn(false);
   char db[]     = "DB";
   char server[] = "localhost";
   char user[]   = "USER";
   char pass[]   = "PASSWD";

   if (conn.connect(db, server, user, pass))
   {
      string consulta = "select email from users";
      mysqlpp::Query query = conn.query(consulta);
      if (mysqlpp::StoreQueryResult res = query.store())
      {
         if (res.num_rows() > 0)
            printf ("%s\n", (string)res[0][0]);
         syslog (LOG_DEBUG, "Failed to get list: %s", query.error());
      }
      conn.close();
   }
   else
      printf("Fallo al conectarse a la BD: %s\n", conn.error());
}
Y para compilarlo, partiendo de un Makefile,
CC = g++ <>
CFLAGS = -Wall -O2 -lmysqlpp
PROJ = prueba_mysql

all: prueba.cpp
 $(CC) $(CFLAGS) -o $(PROJ) prueba.cpp
Leer más

FizzBuzz en C

FizzBuzz es un pequeño problema de programación que suele ser muy simple de enunciar y en algunas ocasiones complicado de obtener la solución eficaz si no se tienen los conceptos claros.
Antes de mostrar el código, vamos a aclarar las premisas, para que aquellos que lo querráis intentar lo podáis hacer tranquilamente. El juego del FizzBuzz se basa en una secuencia de números en la que las únicas cosas a tener en cuenta son,
  1. Si el número es múltiplo de 3, se escribe Fizz
  2. Si el número es múltiplo de 5, se escribe Buzz
  3. Si el número es múltiplo de 3 y de 5 a la vez, se escribe FizzBuzz
  4. En cualquier otro caso, se escribe el número
Como se puede observar, bastante simple, así que ya sin más, os dejo aquí mi código,
#include "stdio.h"

int main(int argc, char** argv){
   int i;

   for (i = 1; i < 200; i++){
      if( !(i % 3) )
         printf("Fizz");
      if( !(i % 5) )
         printf("Buzz");
      if( (i % 3) * (i % 5) )
         printf("%d", i);
      printf("\n");
   }
}
Y a continuación la salida del mismo,
shell> gcc FizzBuzz.c -o FizzBuzz
shell> ./FizzBuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
...
Leer más

Ruby: consulta a BD multithread

Con todo lo aprendido hasta ahora relacionado con ruby y la apertura de socket's y manejo de bases de datos, vamos a unirlo todo en un pequeño programa ejemplo, que ilustrará la simpleza de código ruby.
Partimos de la siguiente tabla de la base de datos.
mysql> show create table users;
+-------+-----------------------------------------------+
| Table | Create Table                                  |
+-------+-----------------------------------------------+
| users | CREATE TABLE `users` (                        |
|       | `id` int(5) unsigned NOT NULL AUTO_INCREMENT, |
|       | `nombre` text NOT NULL,                       |
|       | `login` varchar(15) NOT NULL,                 |
|       | `passwd` varchar(33) NOT NULL,                |
|       | `is_admin` smallint(1) DEFAULT '0',           |
|       | `email` varchar(100) DEFAULT NULL,            |
|       | PRIMARY KEY (`id`) ) ENGINE=InnoDB            |
+-------+-----------------------------------------------+
1 row in set (0.00 sec)

Con el siguiente código nos conectamos a una base de datos y dejamos un servicio multithread a la escucha, que le devuelve a los clientes el resultado de una query. Aunque es sencillo, el código es muy simple y permitiría montar fácilmente un web service multithread rápidamente.
Leer más

Descubriendo virtualhosts bajo una IP

Recientemente descubrí las opciones avanzadas de búsqueda de bing y la verdad es que vi algo sorprendente y que, desde mi punto de vista, hace bien respecto a Google, que es almacenar la IP del site que indexa. bing permite lanzar búsquedas estilo "ip: 32.59.65.0" y también búsquedas filtrando los sitios, tipo "site: www.pepe.com" o "-site:www.pepe.com", que mostrará todos los resultados de la web pepe.com y todos los que no sean pepe.com, respectivamente.

Yo llevaba un tiempo buscando una forma de poder averiguar el número de virtualhost que hay detrás de una misma IP y la verdad es que no conseguía una herramienta simple y que lo hiciera de forma rápida, así que... aprovechando estas facilitys de bing, opté por investigar un poco más en ese sentido. Pues bien, resulta que hay una librería escrita en python que permite realizar búsquedas de forma rápida y simple usando bing, así que únicamente habría que probarla y escribir un pequeño script que realizase tal tarea. Mucho más fácil que usar curl o lynx! así que, manos a la obra.
  • Descargamos la librería pybing para poder usarla, tal como se indica en la página oficial.
    shell> mkdir pybing
    shell> export PYTHONPATH=~/pybing/
    shell> cd pybing
    shell> svn checkout http://pybing.googlecode.com/svn/trunk/ ~/pybing
    
  • Instalamos la librería httplib de python. Si usamos debian/ubuntu,
    shell> apt-get install python-httplib2
  • Obtenemos un ID válido de microsoft para usar la API de bing.
    Para ello vamos a la web oficial y pedimos un nuevo ID de desarrollador. Es necesario tener una cuenta hotmail/msn con la que asociarlo.
  • Finalmente, copiamos el script y sustituimos el ID de la API donde se indica.
Leer más

Ruby: Acceso a MySQL

Ruby tiene conectores para diversas bases de datos, entre ellas, como no,  MySQL. En sistemas debian/ubuntu, el driver a instalar para conectase es libdbd-mysql-ruby.
shell> apt-get install libdbd-mysql-ruby

Y el código para permitir accesos a base de datos, sería:
#!/usr/bin/ruby -w

require 'mysql'

begin
   dbh = Mysql.real_connect("localhost", "USER", "PASSWD", "DB")
   puts "Server version: " + dbh.get_server_info
   query = dbh.query("SELECT login, email FROM users")
   query.each_hash do |row|
      row["login"] = "NULL" if row["login"].nil?
      row["email"] = "NULL" if row["email"].nil?
      printf "%s, %s\n", row["login"], row["email"]
   end
   puts "Number of rows returned: #{query.num_rows}"
   query.free
   rescue Mysql::Error => e
      puts "Error code: #{e.errno}"
      puts "Error message: #{e.error}"
   ensure
   dbh.close if dbh
end
Leer más

Ruby: abrir un socket mulithread

En un post anterior, vimos como abrir un socket para una única conexión entrante. Es interesante poder enviar datos y recibirlos de un equipo, pero mucho más interesante es poder hacer un servidor en condiciones que permita escuchar y responder a varias conexiones al mismo tiempo.
Continúa leyendo para ver el código de un servidor multihilo.
Leer más

Ruby: abrir un socket

Hoy voy a comenzar un una seria de post's sobre programación en ruby. En su día aprendí un poco este lenguaje y ahora, poco a poco hay que ir avanzando en él, para así poder hacer cosas más complejas y útiles.
El siguiente código muestra cómo abrir un socket tcp en un servidor a la escucha de una única conexión entrante.
/usr/bin/ruby -w

require 'socket'

server = TCPServer.open(4096)
loop {
     client = server.accept
     client.puts "Conexion abierta"
     print(client, " aceptado\n") 
     client.write(Time.now.ctime) 
     sleep 3
     client.write("\nCerrando la conexion\n")
     client.close
     print(client, " cerrado\n")
}

Y a continuación el código del cliente para conectarse con el servidor. Este código es también ruby, pero el socket escucha cualquier tipo de cliente.
/usr/bin/ruby -w

require 'socket'

host = '192.168.1.33'
port = 4096
server = TCPSocket.open(host, port)

while line = server.gets
  puts line.chop
end
server.close

Tras el salto, cómo se usa.
Leer más

Formulario de contacto

Nombre

Correo electrónico *

Mensaje *

Últimos comentarios