About José Pérez Martínez

Mi nombre es José Pérez Martínez. Soy Ingeniero Técnico en Informática de Sistemas por la Universidad de Alicante. Tengo un máster en Tecnologías de la Información (con mención de calidad) y actualmente estoy cursando mis estudio de doctorado con el grupo de investigación en CAD/CAM/CAE de la Universidad de Alicante (http://www.dtic.ua.es/unicad/). El manuscrito de mi proyecto fin de máster en scribd. La presentación del proyecto en youtube. Soy un entusiasta de Linux (mi distribución favorita es Debian). Comencé usando Mandrake (ahora Mandriva), Red Hat y también he usado (y uso) Ubuntu, pero personalmente me quedo con Debian. De mi época como estudiante me gusta mucho el estudio de los sistemas operativos, la programación en C/C++ a bajo nivel y desde que descubrí el toolkit Qt soy un firme defensor suyo. Desde el año 2007 aprox. trabajo con el lenguaje de descripción hardware VHDL, de hecho tuve el privlegio de compartir una publicación docente: Diseño de procesadores con VDHL Tengo experiencia en VHDL, Handel-C, Matlab y las herramientas de la suite de desarrollo ISE de Xilinx.

SQL Join: ¿Cual usar?

Introducción

Hace unos días tuve una conversación muy recurrente entre desarrolladores de software respecto del uso cotidiano de SQL. ¿Cómo usar JOIN? Esta duda la tienen aún desarrolladores expertos, pues bien vamos a aclarar un poco que es eso del JOIN.

Como breve resumen, decir que JOIN se usa en SQL para combinar filas de dos o más tablas. Y es una sentencia con tantas posibilidades que realmente se merece una explicación en una única entrada de este blog.

La sentencia JOIN como una expresión algebraica

Si tomamos cada tabla de la base de datos como un conjunto de datos donde cada columna posee su propio dominio definimos el operador como el JOIN para el conjunto de tuplas a relacionar (no deja de ser una composición):

De modo que R y S son dos tablas, y t y s son filas de cada tabla que se unirán si se cumple la condición dada. Y lo más fácil es ver el siguiente dibujo que representa los diferentes tipos de JOINS que existen conceptualmente (no todas los sistemas gestores de base de datos los soportan) y su representación aproximada como diagrama de Venn:

En este dibujo podemos ver gráficamente la idea de cada tipo de JOIN, filas que se relacionan en ambas tablas (conjuntos), filas que no tengan relación y estén en una tabla pero sí en la otra. O al revés, filas que no estén en la primera tabla y sí en la segundo, y en fin … todas las combinaciones que muestra el gráfico.

Por cierto, si se hace una composición de dos tablas con JOIN y la fila compuesta devuelta es resultado de una relación donde para una tabla hay datos y en la segunda tabla no existe relación, los campos de esa segunda tabla devueltos serám NULL.

Para leer más sobre algebra relacional recomiendo los apuntes de Pedro Pablo Alarcón Cavero [4], buen material docente sin duda. Pero todo esto es mejor analizarlo con un buen ejemplo.

Caso práctico

Si accedemos a la Web de W3Schools, tiene una base de datos de ejemplo donde podemos probar online difernetes sentencias SQL [Acceso a la BD en W3Schools].

Tablas de datos básicas

En este apartado primero vamos a ver una muestra de los datos que contienen las tablas, en la mayoría de casos vamos a ver una SELECT y los primeros registros que devuelve la base de datos, para mas información consultar el enlace “Acceso a la DB de W3Schools”.

Listado de Clientes

select * from Customers
CustomerID CustomerName ContactName Address City PostalCode Country
1 Alfreds Futterkiste Maria Anders Obere Str. 57 Berlin 12209 Germany
2 Ana Trujillo Emparedados y helados Ana Trujillo Avda. de la Constitución 2222 México D.F. 05021 Mexico
3 Antonio Moreno Taquería Antonio Moreno Mataderos 2312 México D.F. 05023 Mexico

(Devuelve 91 clientes)

Listado de Empleados

select * from Employees
EmployeeID LastName FirstName BirthDate Photo Notes
1 Davolio Nancy 1968-12-08 EmpID1.pic Education includes a BA in psychology from Colorado State University. She also completed (The Art of the Cold Call). Nancy is a member of ‘Toastmasters International’.
2 Fuller Andrew 1952-02-19 EmpID2.pic Andrew received his BTS commercial and a Ph.D. in international marketing from the University of Dallas. He is fluent in French and Italian and reads German. He joined the company as a sales representative, was promoted to sales manager and was then named vice president of sales. Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.

(Devuelve 10 empleados)

Listado de Transportistas

select * from Shippers
ShipperID ShipperName Phone
1 Speedy Express (503) 555-9831
2 United Package (503) 555-3199
3 Federal Shipping (503) 555-9931

(Devuelve 3 transportistas)

Listado de Pedidos

select * from Orders
OrderID CustomerID EmployeeID OrderDate ShipperID
10248 90 5 1996-07-04 3
10249 81 6 1996-07-05 1
10250 34 4 1996-07-08 2

(Devuelve 196 pedidos)

Obtener los pedidos de cada cliente

Este es el ejemplo que ofrece W3SChools:

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
OrderID CustomerName OrderDate
10248 Wilman Kala 1996-07-04
10249 Tradição Hipermercados 1996-07-05
10250 Hanari Carnes 1996-07-08
10251 Victuailles en stock 1996-07-08

(Mostramos los 4 primeros, hay 196 resultados)

Obtener los clientes que nunca han hecho un pedido

Ahora vamos a pensar en la tabla clientes y en pedidos. En pedidos se registran los pedidos y qué cliente lo realiza, pero … ¿cómo saber qué clientes no han hecho aún un pedido?

SELECT c.CustomerID AS CodigoCliente, c.CustomerName, o.CustomerID AS ClienteEnPedido
FROM Customers AS c
LEFT JOIN Orders AS o ON c.CustomerID=o.CustomerID
WHERE o.OrderID IS NULL;
CodigoCliente CustomerName ClienteEnPedido
1 Alfreds Futterkiste null
6 Blauer See Delikatessen null
12 Cactus Comidas para llevar null
22 FISSA Fabrica Inter. Salchichas S.A. null
26 France restauration null
32 Great Lakes Food Market null
40 La corne d’abondance null
42 Laughing Bacchus Wine Cellars null
43 Lazy K Kountry Store null
45 Let’s Stop N Shop null
50 Maison Dewey null
53 North/South null
57 Paris spécialités null
64 Rancho grande null
74 Spécialités du monde null
78 The Cracker Box null
82 Trail’s Head Gourmet Provisioners null

De los 91 clientes que hay, estos 17 no tiene pedidos realizados. Además podemos ver cómo la columna con el ID de cliente en pedidos obtenida con este JOIN vale NULL, con lo que sabemos que existe relación.

Obtener los empleados que no han hecho ventas

Este es otro ejemplo cómo el anterior:

SELECT e.EmployeeID, e.FirstName
FROM Employees AS e
LEFT JOIN Orders AS o ON e.EmployeeID=o.EmployeeID
WHERE o.EmployeeID IS NULL;
EmployeeID LastName FirstName BirthDate Photo Notes
10 West Adam 1928-09-19 EmpID10.pic An old chum.

Adam West es el único cliente que no ha registrado pedidos en la base de datos.

Obtener qué pedidos ha hecho Nancy

Este caso es el mismo que obtener los pedidos de cada cliente, pero añadiendo un flltro por empleado.

SELECT e.EmployeeID, e.FirstName, o.OrderID
FROM Employees AS e
INNER JOIN Orders AS o ON e.EmployeeID=o.EmployeeID
WHERE e.FirstName = 'Nancy';
EmployeeID FirstName OrderID
1 Nancy 10258
1 Nancy 10270
1 Nancy 10275
1 Nancy 10285
1 Nancy 10292

Muestro los 5 primeros pedidos, pero Nancy ha hecho 29 pedidos.

Conclusión

JOIN es una clausula para las consultas SELECT que enrique mucho el lenguaje SQL, permite realizar consultas para diferentes casos muy interesantes sin tener que recurrir a escribir consultas muy complicadas.

Ejemplos para analizar el uso de JOIN hay muchos y en Google podemos encontrar muchos, espero que este resumen sirva de ayuda.

Referencias

  1. Join en Wikipedia: http://es.wikipedia.org/wiki/Join
  2. Join en W3SChoolshttp://www.w3schools.com/sql/sql_join.asp
  3. Manual de MySQL5 – Sentencia JOIN: http://dev.mysql.com/doc/refman/5.0/es/join.html
  4. Para leer algo más sobre algebra relacional (con permiso de Pedro Pablo Alarcón Cavero ): http://www-oei.eui.upm.es/Asignaturas/BD/BD/docbd/tema/algebra.pdf

Resetear el password del root en mysql

Solución rápida

¿Qué ocurre si instalas un servidor MySQL y no recuerdas al password del usuario root? O mejor aún, ¿y si te descargas una aplicación que preinstala un WAMP o XAMP y no te indica cual es el password de root?

Bueno, es un contratiempo pero no está todo perdido, si trabajamos en un entorno Unix podemos hacer los siguiente:

1. Detener el servidor

service mysql stop  o  /etc/init.d/mysqld stop

2. Iniciar el servidor en modo seguro:

mysqld_safe --skip-grant-tables --skip_networking &
  • La primera opción sirve para deshabilitar los permisos sobre las tablas y todos los usuarios pueden acceder a todas las tablas
  • La segunda acción deshabilita el servidor sobre TCP, de modo que el servidor sólo funciona de forma local (es una forma algo segura de manejar el servidor “a prueba de fallos” evitando que nadie desde la red se encuentre manipulando tablas o bases de datos que no debería tocar.

3. Iniciar el cliente CLI (TUPASWORD es la cadena de contraseña a elegir, además ver que se debe cifrar con PASSWORD() que es la función de cifrado para contraseñas por defecto de MySQL)

$ mysql -uroot
mysql> use mysql;
mysql> update user set passoword=password('TUPASSWORD') where user='root';

4. Por último queda reinicar el servidor.

Referencias

Leer XML con namspaces fácil en PHP

Introducción

Cuando manipulamos documentos XML [1] desde PHP [2] uno de los “quebraderos” de cabeza son los namespaces. Un namespace no es nada complicado ni rocambolesco como algunos opinan; no deja de ser un enriquecimiento semántico para dotar de más información a un documento XML.

Tradicionalmente los desarrolaldores PHP no se han complicado con este concepto. Pero hoy en día con la cantidad de mensajes y documentos XML que envían mediante REST, SOAP, APIs de terceros, etc. es inevitable y totalmente recomendable conocer como manipularlos de forma sencilla en PHP.

Caso de uso: Google shopping

Por lo general cualquier documento XML generado por y para Google tendrá en namespace http://base.google.com/ns/1.0, que simplemente añade algo de información adicional al documento XML (descripciones, items, ….) [4].

Cómo ejemplo vamos a manipular un documento para el servicio Google Shopping [3].

<?xml version="1.0"?>

<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
    <channel>
        <title>El nombre de tu feed de datos</title>
        <link>http://www.example.com</link>
        <description>Una descripción de tu contenido</description>
        <item>
            <title>Suéter de lana rojo</title>
            <link> http://www.example.com/página-información-producto1.html</link>
            <description>Suéter suave y cómodo que te abrigará en las frías noches de                         
            invierno</description>
            <g:image_link>http://www.example.com/imagen1.jpg</g:image_link>
            <g:price>25</g:price>
            <g:condition>nuevo</g:condition>
            <g:id>1a</g:id>
        </item>
    </channel>
</rss>

Si leyéramos este documento directamente con SimpleXML no entendería los namespaces ni sus elementos, quedan este documento:

<?xml version="1.0"?>

<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
    <channel>
        <title>El nombre de tu feed de datos</title>
        <link>http://www.example.com</link>
        <description>Una descripción de tu contenido</description>
        <item>
            <title>Suéter de lana rojo</title>
            <link> http://www.example.com/página-información-producto1.html</link>
            <description>Suéter suave y cómodo que te abrigará en las frías noches de                         
            invierno</description>

        </item>
    </channel>
</rss>

¿Cómo solucionarlo? Un ejemplo tonto sería la siguiente función que dado un elemento de un documento XML con SimpleXML busca los elementos del namespace http://base.google.com/ns/1.0. Obtenidos los elementos de este namespace en ese nodo, sólo debemos recoger la propiedad deseada (precio).

function xml_get_price(SimpleXMLElement $item)
{
    $googleSpace  = $item->children('http://base.google.com/ns/1.0');
    return $googleSpace->price; // para el ejemplo anterior: 25
}

¡Fin! Espero que sea útil.

Referencias

  1. XML 1.0 (w3c): http://www.w3.org/TR/REC-xml/
  2. PHP SimpleXML: http://php.net//manual/es/book.simplexml.php
  3. Google Shopping: https://www.google.es/shopping
  4. Google Merchants Expecificacion RSS 2.0: https://support.google.com/merchants/answer/160589?hl=es

Compilar desde línea de comnandos en Windows (CLI) usando Visual C++

Introducción

Para mi tesis doctoral tengo que desarrollar una serie de programas escritos en C. Trabajo sobre Windows y uso el Matlab, Modelsim y Xilinx ISE. Para realizar una cosimulación hardware/software entre Matlab, Modelsim y mis programas C debo usar ciertas bibliotecas estáticas (lib) y generar biblotecas dinámicas (dll) para comunicar los distintos procesos. Como estoy en Windows debo usar Microsft Visual Studio y Visual C++ [1].

En este caso no me sirve usar un compilador tan potente como GCC sobre MinGW porqué no soportar biblotecas tipo .lib ni generar .dll.

Pero aún así soy y seré un enamorado de la consola, tanto en Windows y sobre todo en sistemas tipo Unix. Y desde luego a menos que desarrolle una gran aplicación y necesite de verdad un gran IDE (como Eclipse o Visual Studio) no me gusta compilar un programa de apenas 800 líneas usando un IDE que genera una gran cantidad de ficheros y además no me permite automatizar nada desde consola.

Por ello he decidido investigar un poco y ver cómo se compila un programa usando el compilador de C/C++ de Microsft (cl.exe) en consola (cli). Además de cómo se enlazan todos los objetos usando el enlazador (linker) de Microsoft (link.exe).

¡Ojo! Depende de la versión de Visual Studio para poder compilar en consola se deberá abrir la misma usando un enlace instalado por Visual Studio como “Visual Studio Command Prompt (2010)” sino ciertas biblotecas y variables de entorno no estarán configuradas correctamente.

Makefile de ejemplo

A continuación vemos un ejemplo de Makefile para compilar con cl.exe. Para descargar Make para windows véase el enlace [2] y para saber más sobre el funcionamiento de make [3]. Este makefile para generalizar el proceso y simplificarlo usa una regla basada en patrones (%.obj: %.c %.h):

#
# Miscrosoft Visual Studio generic Makefile
#

RM=del /q
CC=cl
CFLAGS=/02
LINKFLAGS=
LINK=link
OUTPUT=/out:programa.exe
OBJ=programa.obj lib.obj
MAIN_TARGET=programa.exe
INC_DIR=

.phony: clean edit

all: $(MAIN_TARGET)

$(MAIN_TARGET): $(OBJ)
	$(LINK) $(LINKFLAGS) $(OBJ) $(OUTPUT)

%.obj: %.c %.h
	$(CC) -c $(CFLAGS) $<

clean: 
	$(RM) $(OBJ)

Caso de ejemplo

Supongamos que tenemos los ficheros libreria.c, libreria.h y programa.h, libreria.c. La primera pareja contine algunas funciones de utileria y los dos segundos el grueso de nuestro programa.

Si ejecutamos el comando make:

C:\ejemplos>dir>make
cl -c libreria.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

libreria.c
cl -c principal.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

principal.c
link  libreria.obj principal.obj /out:programa.exe
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Generando el fichero ejecutable programa.exe, si vemos el contenido del directorio veremos los ficheros de código fuente, los objetos, el ejecutable y el Makefile:

C:\ejemplos>dir
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es: xxx-yyyy

 Directorio de C:\ejemplos>

05/04/2014  12:10              .
05/04/2014  12:10              ..
26/03/2014  17:59             1.433 libreria.c
26/03/2014  17:59               216 libreria.h
05/04/2014  12:10             1.540 libreria.obj
05/04/2014  12:10               409 Makefile
05/04/2014  11:01             8.800 principal.c
05/04/2014  10:59             1.117 principal.h
05/04/2014  12:10             9.565 principal.obj
05/04/2014  12:10            90.624 programa.exe
               8 archivos        113.704 bytes
               2 dirs  41.752.834.048 bytes libres

De este modo hemos conseguido generar un sencillo ejecutable sin necesidad de abrir el IDE completo de Visual Studio y generar toda esa cantidad de ficheros basura inccesarios que generan los proyectos y soluciones de Microsoft Viusal Studio.

Referencias

  1. Sitio oficial de Visual Studio: http://msdn.microsoft.com/en-US/vstudio
  2. Make para Windows: http://gnuwin32.sourceforge.net/packages/make.htm
  3. GNU Make: https://www.gnu.org/software/make/manual/html_node/

SQL para sistema de reservas

Introducción

En un proyecto reciente he tenido que preparar un sistema de reservas para un hotel. La idea es sencilla poder reservar recursos (en este caso habitaciones) entre unas fechas determinadas.

Pero además, como es un hotel se da una condición especial. La fecha de inicio y de fin no son cerradas, quiero decir que una reserva puede terminar el mismo día que otra empieza y viceversa. Por todos es sabido, que normalmente en un hotel la hora de salida es hasta las 12:00am y la hora de entrada es a partir de las 14:00pm.

¿Cómo resolverlo? Sencillo,veamoslo.

Solución

Primero suponemos un esquema tan sencillo como el siguiente:

CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;

CREATE TABLE IF NOT EXISTS `mydb`.`habitaciones` (
  `numero` INT(11) NOT NULL,
  `nombre` VARCHAR(45) NULL DEFAULT NULL,
  `camas` INT(11) NULL DEFAULT NULL,
  `camagrande` TINYINT(1) NULL DEFAULT NULL,
  `disponible` TINYINT(1) NULL DEFAULT NULL,
  PRIMARY KEY (`numero`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

CREATE TABLE IF NOT EXISTS `mydb`.`reservas` (
  `reserva_id` INT(11) NOT NULL AUTO_INCREMENT,
  `habitaciones_numero` INT(11) NOT NULL,
  `entrada` DATE NULL DEFAULT NULL,
  `salida` DATE NULL DEFAULT NULL,
  `nombrecliente` VARCHAR(45) NULL DEFAULT NULL,
  `telefono` VARCHAR(45) NULL DEFAULT NULL,
  PRIMARY KEY (`reserva_id`),
  INDEX `fk_reservas_habitaciones_idx` (`habitaciones_numero` ASC),
  CONSTRAINT `fk_reservas_habitaciones`
    FOREIGN KEY (`habitaciones_numero`)
    REFERENCES `mydb`.`habitaciones` (`numero`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

El siguiente paso paso sería crear algún dato. Una vez hecho esto, podemos considerar muchos casos posbles, buscando en Internet seguro que hay muchas aproximaciones pero la solución final que yo he encontrado y funciona perfectamente para mi caso es la siguiente:

set @dstart = date_add('2014-03-15', interval 1 day);
set @dend   = date_sub('2014-04-01', interval 1 day);
select id, vivienda_id, arrival_date, departure_date, date_add(@dstart, interval 1 day) firstday, date_sub(@dend, interval 1 day) lastday
from espana_reservations r
where (arrival_date between @dstart and @dend)
   or (@dstart between arrival_date and departure_date)

Espero que haya sido de ayuda!

Referencias

Parametrizar consulta en MySQL usando @variables

Introducción

Hace poco en un proyecto personal he empezado a usar variables en mis consultas SQL para probarlas en mi cliente HeidiSQL. De esto modo puedo verificar el funcionamiento de las mismas como las construye mi framewoork codeigniter.

Por poner un ejemplo, en PHP plano se escribiría algo así:

$select = 'select * from cosas where precio > ', ($miprecio + $parametro) ' and precio < ', ($miprecio * 10) ;.

Pero claro, lo ideal es poder usar en MySQL una construcción con el mismo aspecto, ¿cómo? Usando las variables que nos ofrece en SQL.

Ejemplos

Supongamos una tabla de viviendas con su id, nombre y precio de mercado como la siguiente:

select id, nombre, precio_de_venta from kaza_viviendas
id nombre precio_de_venta
12 Villa Atlas 1470000
10 Villa Chronos 1350000
11 Villa Hermes 780000
6 Villa Marfil 1300000
8 Villa Eos 850000
9 Villa Pegasus 670000

Si queremos el precio más bonito y usando otro nombre:

select id, nombre, format(precio_de_venta, 2) as precio from viviendas 
id nombre precio
12 Villa Atlas 1,470,000.00
10 Villa Chronos 1,350,000.00
11 Villa Hermes 780,000.00
6 Villa Marfil 1,300,000.00
8 Villa Eos 850,000.00
9 Villa Pegasus 670,000.00

A continuación, vamos a crear dos parámetros “horquilla” y “precio_referencia”. El primero establece un límite sobre el que buscar precio “similares” al dado por “precio_referencia”:

set @precio_referencia=1470000;
set @horquilla=25000;
select id, nombre, format(precio_de_venta, 2) as recio
from viviendas
where precio_de_venta >= (@precio_referencia - @horquilla)
  and precio_de_venta <= (@precio_referencia + @horquilla);

Como vemos sólo nos devuelve una. Pero para generar y probar una lista de viviendas similares con este u otro criterio resulta muy útil y rápido

id nombre recio
12 Villa Atlas 1,470,000.00

Estos ejemplos son muy sencillo y tontos, pero creo que ilustran a grandes rasgos lo que quiero decir, además estoy seguro que para construir consultas más complejos con mayor cantidad de cruzas y condiciones podría ser de gran ayuda.

Conclusión

En desarrollo personalmente no me gusta usar variables de MySQL, aunque con ejemplos como el anterior si que veo muy claro lo que facilita la depuración del SQL y ayuda a la hora de construir consultas muy complejas con muchos datos cruzas y poder probar diferentes casos.

Desinstalar el plugin Subeclipse (svn) de Eclipse/Aptana Studio 3

Hace unos días, instalé el pluigin subeclipse para integrar SVN en Aptana Studio. Después de probarlo quedé contrariado al detectar que tiene un problema con el sistema de claves de gnome y no hacía más que darme problemas. Decidí seguir usando svn en consola y desinstalarlo. ¿Pero cómo hacerlo definitivo?

$ cd APTANA_INSTALL_DIR/plugins
$ ls |grep org.tigris.subversion
org.tigris.subversion.clientadapter_1.6.12.jar org.tigris.subversion.subclipse.doc_1.3.0.jar org.tigris.subversion.subclipse.tools.usage_1.0.1.jar
org.tigris.subversion.clientadapter.javahl_1.6.15.jar org.tigris.subversion.subclipse.graph_1.0.9.jar org.tigris.subversion.subclipse.ui_1.6.17.jar
org.tigris.subversion.subclipse.core_1.6.17.jar org.tigris.subversion.subclipse.mylyn_3.0.0.jar
$ ls |grep org.tigris.subversion|xargs rm

Solucionada, reiniciamos Aptana Studio y todo ok.

Referencias

  • Eclipse: http://www.eclipse.org/
  • Aptana Studio: http://www.aptana.com/
  • Subeclipse: http://subclipse.tigris.org/

Desactivar Javascript en Firefox

Hace poco tuve que realizar unas pruebas en un proyecto y necesitaba desactivar el javascript para hacer unas comprobaciones. ¿Cómo hacer esto en Firefox?

Muy fácil, en la barra de direcciones escribimos “about:config”, nos preguntará el navegador si de verdad queremos acceder. Le respondemos que sí. Ahora estamos en el núcleo de la configuración de firefox, debemos llevar cuidado.

Buscamos la clave “javascript.enabled”. La ponemos a FALSE e voilá! El navegador no interpretará Javascript.

Instalar Oracle JDK en Debian/Ubuntu

Introducción

Recientemente he descargado el Android Studio y necesito el JDK oficial de Oracle para hacerlo funcionar. Para instalarlo en nuestra distribución Linux primero debemos comprobar la versión de java instalada (interprete y compilador):

$ java -version
java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1ubuntu0.12.04.4)
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)

Desintalar OpenJDK si está instalado

Si no tienes instalada el OpenJDK no necesitas seguir estos pasos, pero en mi caso voy a desinstalar los paquetes del OpenJDK.

$ sudo apt-get remove openjdk-6-jre*

Instalar Oracla JDK

A continuación, para instalar el Oracle JDK:

  1. Añadir repositorio:
    sudo add-apt-repository ppa:webupd8team/java
  2. Actualizamos los repositorios con:
    sudo apt-get update
  3. Instalar Oracle JDK:
    sudo apt-get install oracle-java7-installer

Para comprobar que la instalación ha tenido éxito, ejecuta en una terminal el comando para saber la versión de Java que utiliza tu Ubuntu:

java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) Client VM (build 24.45-b08, mixed mode)

Desintalar Oracle JDK

Si quisieramos desinstalar el Oracle JDK:

sudo apt-get remove oracle-java7-installer

Y sus repositorios:

sudo apt-get install ppa-purge
sudo ppa-purge ppa:webupd8team/java

Configurar un multihost con apache2 y en Debian/ubuntu [ACTUALIZADO]

Introducción

Como desarrollador Web en alguna ocasión he tenido que realizar algún proyecto sin disponibilidad de tener un servidor de desarrollo. Hasta este punto, existen tres opciones si queremos trabajar con un servidor de desarrollo en lugar de usar un WAMP o un XAMPP (que son cómodos pero poco profesionales).

  • Contratar un multihost a algún proveedor de servicios de hosting
  • Instalar una máquina servidor configurandola con multihost y su propio DNS, etc.
  • Instalar un servidor LAMP con multihost en el equipo de trabajo

En esta entrada me voy a decantar por esta última opción por comodidad y rapidez. Pero hay que tener en cuenta que esta solución sólo servirá para tener un entorno multihost para uno mismo, si se trabaja en grupo en un red no será un sistema válido.

Instalando apache2, php5, mysql5 … (lamp)

Lo primero, es instalar un sistema LAMP (Linux, Apache, Mysql, PHP). Esto en un sistema Debian/Ubuntu es tan sencillo cómo ejecutar en consola:

$ sudo apt-get install apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libaprutil1-dbd-sqlite3 libaprutil1-ldap libhtml-template-perl mysql-server mysql-server-5.5 mysql-server-core-5.5 apache2-mpm-prefork libapache2-mod-php5 libtidy-0.99-0 php5 php5-cli php5-common php5-curl php5-gd php5-mysql php5-odbc php5-sqlite php5-tidy php5-xdebug php5-xmlrpc libapache2-mod-auth-mysql libphp-jpgraph dbconfig-common libmcrypt4 php-doc php5-mcrypt phpmyadmin

A continuación, como sana costumbre recomiendo cambiar la clave de root de MySQL.

mysql -u root
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('yourpassword');

Y por último, si hemos instalado PHP, editar el fichero /etc/php5/apache2/php.ini y habilitar el uso de mysql, en la línea:

;extension=mysql.so

Cambiadla por: 

1extension=mysql.so

Un poco de DNS

Apache2 se configura de modo que se le indica al servidor en que interfaces de red y puertos debe funcionar. Tomemos la imagen siguiente:

Disponemos de varios nombres de dominio (reales o ficticios) y deseamos que apunten a la misma máquina, pero claro, no queremos que apache nos facilite las mismas Webs para cada uno, sino que sean proyectos diferentes (multihost), para ello debemos indicar el sistema DNS que esos nombres apuntan a la IP del servidor de trabajo.

Si estuviéramos en un entorno real y profesional, tendríamos un servidor DNS y un servidor LAMP dedicado con una IP W.X.Y.Z, e indicaríamos al servidor DNS que cada dominio apunte al servidor con IP W.X.Y.Z. Como estamos probando en un servidor “monopuesto” no necesitamos configurar ningún servidor DNS, sólo debemos editar el fichero /etc/hosts. Este fichero es una reminiscencia del origen de Internet y contiene parejas del tipo (nombre, ip).

De modo que si queremos añadir el dominio de prueba “midominio”, sólo debemos añadir al final del fichero /etc/hosts la sighuiente línea:

127.0.0.1    midominio

Una vez hecho esto, nuestro equipo sabe que la IP del dominio midominio es 127.0.0.1. Pero, sólo nuestro equipo, este fichero es local al equipo dónde lo hemos editado de ahí que este sistema sólo nos sirva para el equipo de trabajo no para trabajar en equipo.

Sistema multihost en apache2

Y por fin, vamos a ver los pasos para configurar un sistema multihost en nuestro apache2. Supongamos que los DocumentRoot de los diferentes dominios estan en la carpeta /home/usuario/www, debemos seguir estos pasos:

  1. Añadir el usuario al grupo WWW-DATA de apache2: Para que apache pueda leer/escribir sin problemas en sus carpetas (Cambiad USUARIO por vuestro usuario)
    $ sudo usermod -G www-data USUARIO
  2. Poner los permisos 775 para directorios y 664 para ficheros: Por lo mismo que en el apartado anterior ($PWD se evalúa como el directorio actual, se puede indicar el directorio correspondiente).
    $ find $PWD -type d -print -exec chmod 775 {} \;
    $ find $PWD -type f -print -exec chmod 664 {} \;
  3. Cambiar los permisos del directorio del vhost:
    $ sudo chown -R USUARIO:www-data *
  4. Edita el fichero del virtual host:
    
    <VirtualHost *:80>
    	ServerAdmin	info@miemail.com
    	Servername	midominio
    	DocumentRoot	/home/usuario/www/midominio
    	LogLevel	warn
    	ErrorLog 	${APACHE_LOG_DIR}/midominio_error.log
    	CustomLog	${APACHE_LOG_DIR}/midominio_access.log combined
    	<Directory />
    		Options FollowSymLinks
    		AllowOverride None
    	</Directory>
    	<Directory /home/usuario/www/midominio>
    		Options Indexes FollowSymLinks MultiViews
    		AllowOverride All
    		Order allow,deny
    		allow from all
    	</Directory>
    </VirtualHost>

    Debemos tener cuidado con lo siguiente, en Debian/Ubuntu la configuración inicial de apache2 desactiva el uso del fichero .htaccess. Para habilitarlo debemos ser cuidadods de poner la directiva AllowOverride All como en el ejemplo anterior.

    Novedad: En versiones recientes de apache está configuración puede no ser suficiente y debemos añadir alguna directiva adicional, para no encontrartos un error HTTP 403 Forbbiden. De modo que en la configuración del directorio con el DOCUMENT ROOT debemos a Require all granted, quedando algo así

    :

    <Directory "your directory here">
       Order allow,deny
       Allow from all
       # New directive needed in Apache 2.4.3: 
       Require all granted
    
    

    Tal y como podemos leer en Stack Overflow.

  5. Activar el mod_rewrite:
    $ sudo a2enmod rewrite
    $ sudo service apache2 restart
  6. Accede a http://midominio

Suerte con vuestros servidores LAMP!

Referencias

  1. DNS en Wikipedia: http://en.wikipedia.org/wiki/Domain_Name_System
  2. Virtual Host: http://httpd.apache.org/docs/2.2/vhosts/
  3. Ejemplos: http://httpd.apache.org/docs/2.2/vhosts/examples.html