Category:Técnico

Cambiar ruta de acceso por defecto de la carpeta data de mysql en ubuntu linux

Instrucciones probadas en:

  • Ubuntu 14.04, 64 bits + MySQL 5.6.19
  • Ubuntu 15.10, 64 bits + MySQL 5.6.27

Por defecto la carpeta de datos de MySQL es /var/lib/mysql. Supongamos que queremos usar /home/data:

Crea la carpeta nueva

mkdir /home/data

Cambia los permisos de la carpeta nueva para que pertenezca al usuario y grupo mysql:

chown -R mysql:mysql /home/data/*

Edita el fichero de configuración de mysql /etc/mysql/my.cnf. En Ubuntu 15 el fichero de configuración está en /etc/mysql/mysql.conf.d/mysqld.cnf

nano /etc/mysql/mysql.conf.d/mysqld.cnf

Busca la línea que dice “datadir = /var/lib/mysql” y cambia la ruta antigua por la nueva

datadir = /home/data

En Ubuntu se usa AppArmor para gestionar la seguridad, así que también tenemos que decirle a AppArmor que mysql tiene permisos sobre la nueva carpeta:

nano /etc/apparmor.d/usr.sbin.mysqld

Añade las siguientes líneas al final:

/home/mysql-data r,
/home/mysql-data/* rwk,

Reinicia AppArmor

/etc/init.d/apparmor restart

Detén el servidor

/etc/init.d/mysql stop

Copia los ficheros de la carpeta de datos antigua a la nueva. Asegúrate de no copiar los ficheros ib_arch_log_0000000000, ib_logfile0, etc.

cp -rp /var/lib/mysql/* /home/data
rm /home/data/ib*
rm /home/data/*.cnf
rm /home/data/debian*

Reinicia el servidor

/etc/init.d/mysql start

Bualá

Problema con envío de correos en Prestashop

Versión de Prestashop: 1.5.0.17 (aunque seguramente será válido para otras versiones)

Hoy después de varias horas intentando averiguar por qué no podía enviar emails a través de la última tienda Prestashop que configuré, por fin di con la solución. El problema era que a pesar de tener la configuración correcta (servidor SMTP externo con todos sus datos bien puestos), al enviar el correo de prueba la tienda me devolvía el odioso mensaje en rojo:

Error: please check your configuration
There was a problem reading line 1 of an SMTP response. The response so far was:
[]. It appears the connection has died without saying goodbye to us! Too many emails in one go perhaps? (fsockopen: #0)

Finalmente, la clave estaba en la parte «the connection has died without saying goodbye to us«, lo que podía significar que, o bien el servidor de correo estaba mal configurado (descartado), o bien el tiempo que Prestashop estaba esperando por una respuesta era insuficiente. Después de dar muchas vueltas por el backend buscando este posible valor de configuración y no encontrarlo (qué raro que no sea un valor configurable), decidí mirar el código. Encontré el problema en las líneas 170 y 274 del fichero /classes/Mail.php, que efectivamente tenían valores que estaba claro que eran insuficientes:

Línea 170 :

$connection->setTimeout(4);

Línea 274 :

$smtp->setTimeout(5);

Cambié los respectivos valores por 5 y 10, y por fin pude ver el mensaje en verde que me indicaba que mis correos se estaban enviando.

Opinión sobre el proveedor de servicios Strato

Hace poco mi empresa empezó a contratar servidores dedicados en Strato, una empresa alemana con máquinas dedicadas bastante buenas a precios muy bajos comparativamente. Fenomenal, varias máquinas después y visto que la atención era relativamente buena, decidí contratar por mi cuenta y para uso personal varios dominios en esta misma empresa, ya que los precios para este servicio también están muy bien.

Mi sorpresa fue ver que el panel de control para dominios, que no había visto hasta ese momento, era tremendamente limitado: es imposible realizar una gestión completa de DNSs de los dominios que había contratado. En concreto, no era posible añadir subdominios asociados, es decir, no podía crear una dirección «www.midominio.com», ni mucho menos «increible.midominio.com». Por supuesto, tampoco podía añadirles una webmail externa, ni asociarles las google apps. Para cualquier operación de ese tipo debía actualizar el paquete contratado asociándole un hosting ¡¿?!, o como dirían los modernos, ¡¿WTF?!. Finalmente, después de varios mails y llamadas a Strato en los que me indicaron que lo que solicitaba era imposible (muy amables, eso sí) decidí llevarme mis dominios contratados a otro sitio… dentro de 2 meses, porque la ICANN (el máximo órgano del que dependen todas las URLs mundiales) establece que no pueden pasar menos de 2 meses desde que contratas un dominio hasta que lo puedes mover a otro proveedor. Menuda gracia.

Así que mucho cuidado con dejarse seducir por los bajos precios por contratación de dominios de Strato si lo que queréis es sólo contratar dominios sin ningún otro servicio asociado.

Exportar Certificados SSL de IIS 7 a Apache

Hoy tuve que migrar de IIS7 a Apache un dominio que tenía configurado un certificado SSL. No contaba con los ficheros necesarios para configurar la conexión segura en Apache (certificado y llave privada), ya que IIS7 los guarda encriptados en un formato propio. Afortunadamente después de mucho trastear, encontré la manera de sacar la información desde el fichero exportado por IIS7 (.PFX). Se trata de utilizar el comando «openssl», que se instala con Apache en la carpeta bin, de la siguiente manera:

1. Exportar la llave privada del fichero pfx

openssl pkcs12 -in fichero_exportado_de_iis.pfx -nocerts -out llave.pem

2. Exportar el certificado del fichero pfx

openssl pkcs12 -in fichero_exportado_de_iis.pfx -clcerts -nokeys -out certificado.pem

3. Eliminar la clave que se adjunta a la clave privada, para que Apache no pregunte por la misma cuando arranca

openssl rsa -in llave.pem -out llave_lista.key

Ya podemos utilizar certificado.pem y llave_lista.key en nuestro fichero de configuración de Apache para configurar nuestro dominio con soporte para SSL.

Rails 3.0, HTTP y HTTPS conviviendo en armonía

Uno de los últimos problemas con los que me he tenido que enfrentar ha sido la labor de conseguir que convivan rutas HTTP y HTTPS en una aplicación Rails 3.0 de forma que sólo se utilice HTTPS para unas pocas acciones determinadas y el resto de la aplicación se pueda navegar sin encriptar.

Hay muchos artículos en la red explicando cómo conseguir parte de la tarea, pero en todos los casos la información me resultaba incompleta porque:

  • En muchos de los ejemplos encontrados había que convertir la aplicación completa a HTTPS (yo sólo quería aplicar la encriptación a unas pocas acciones)
  • En la mayoría de casos había que instalar un certificado para trabajar en local (yo en local quería seguir trabajando sin SSL, utilizándolo sólo en producción)
  • ¡Algunas soluciones incluso pasaban por la modificación de Webrick para poder trabajar en la máquina de desarrollo con los 2 protocolos a la vez!
  • En la mayoría de soluciones, una vez que se forzaba el uso de SSL para una ruta, el resto de rutas no volvían a ser HTTP.
  • La solución utilizando before_filters en todos los controladores para desactivar HTTPS me resultaba muy engorrosa debido a que la aplicación en la que trabajo tiene muchos controladores, además de no ceñirse nada a los principios DRY que siempre procuro tener presentes.

Después de 2 días de investigación la solución que fabriqué fue:
Read more

La odisea de pasar archivos grabados de más de 4GB de mi «Best Buy Easy Recording TDT» a mi disco duro

Versión corta:
Utiliza el comando ftpput para realizar la transferencia de tu archivo o archivos por FTP.

Versión larga:
Hace poco me tuve que enfrentar al pequeño problema de pasar un programa de televisión grabado en este dispositivo, a mi disco duro. El problema era que el fichero pesaba más de 4GB, que es el máximo tamaño soportado por el sistema de archivos FAT32, que es el formato del disco en el que el dispositivo en cuestión graba de la tele. Por lo tanto, cuando se hace la copia desde la interfaz del propio aparato (Playback > TDT > Edit > Convert to FAT32), el resultado es que en dicho disco aparecen varios ficheros de 4GB, es decir, se produce un troceado automático. En mi caso, un fichero de 6GB se convertía en 1 de 4GB y otro de 2GB. El problema de esto es que, después de dar muchas vueltas, no fui capaz de volver a unirlos satisfactoriamente con ningún editor de videos gratuito.

Mi primer intento de solución fue ver la opción de reformatear la partición de intercambio FAT32 convirtiéndola en NTFS (que permite guardar ficheros de longitudes mayores), sin embargo la interfaz del aparato no permite realizar este tipo de operación aislada: o reformateaba y reparticionaba todas las particiones, o ninguna.
Descartada esa opción, me conecté por telnet al aparato a ver qué me encontraba. Sorprendentemente conseguí conectar a la primera (nunca lo había hecho) utilizando como usuario «root», sin contraseña. Genial, se trata de un Linux básico. Después de trastear un poco, lo primero que hice fue intentar reparticionar manualmente el disco de intercambio, sin embargo el comando «fdisk» necesario viene capado de serie para impedir que se realice esta operación.

No me desanimé, lo segundo que intenté fue hacer un fichero comprimido en partes, que es fácil de descomprimir en uno solo, pero aunque el comando «tar» sí estaba disponible, no lo estaba el comando «split», que es el que permite hacer el troceado. También lo intenté con bzip y gzip, pero ninguno estaba disponible. Esto empezaba a ser un poco rollo, la versión de linux del aparato es completamente minimalista.

En ese momento no tenía ningún linux a mano, excepto un liveCD de Knoppix. Lo arranqué y le enchufé el aparato: sólo me reconocía la partición linux del sistema operativo, no las otras particiones de datos. Probé a instalarme en Windows un explorador de ext2 y ext3 y tampoco fui capaz de ver más que la partición del sistema operativo. Buscando en internet encontré gente que decía que las particiones en las que el aparato realiza las grabaciones son UDF. Busqué alguna forma de leer dichas particiones desde linux o windows, pero no encontré ninguna manera sencilla de realizarlo.

Recordé que tenía un pendrive usb de 8GB, lo formateé en NTFS, lo conecté y afortunadamente el sistema lo reconocía. Ejecuté un simple comando de copiado de archivos y la sorpresa fue que el sistema me informaba que el pendrive se había montado como sistema de ficheros de sólo lectura, no estaba permitido escribir en el mismo. Probé a remontarlo manualmente con permisos de escritura:
mount -o remount -w /tmp/usbmounts/sda1
Ningún error
cp 000008.ts /tmp/usbmounts/sda1
¡Ningún error!, dejé al sistema realizando la copia del archivo. 15 minutos después seguía copiando. 30 minutos después seguía copiando. 1 hora después seguía copiando. 2 horas después, seguía sin terminar. Detuve la transferencia, algo fallaba.

Ya casi sin recursos, revisé las carpetas bin y sbin en el sistema para ver si encontraba algún comando instalado que me pudiera ser útil. Al ver «ftpput» se me encendió la bombilla. Instalé un servidor de FTP en mi ordenador, creé un usuario y en el disco duro externo ejecuté por telnet:

ftpput -v -u [usuario] -p [contraseña] 192.168.1.2 000008.ts ./000008.ts

y el resultado fue:

Connecting to 192.168.1.2[192.168.1.2]:21
ftpput: cmd (null)(null)
ftpput: cmd USER [usuario]
ftpput: cmd PASS [contraseña]
ftpput: cmd TYPE I(null)
ftpput: cmd PASV(null)
ftpput: cmd ALLO 1271240704(null)
ftpput: cmd STOR 000008.ts
ftpput: cmd (null)(null)
ftpput: cmd QUIT(null)

Genial. Problema resuelto por los pelos, justo cuando estaba a punto de tirar la toalla. Tiempo de transferencia: 32 minutos. Tiempo que tardé en conseguirlo: 3 horas largas divididas en 2 días.

Comandos útiles:
Comando para comprobar el estado de los discos duros : df -h
Comando para comprobar las particiones existentes : fdisk -l
tar + split, inservible para este caso : tar czf – ejemplo/ | split -b 1000m – troceado.tgz.

Eliminar el borde de puntos alrededor de un enlace al que se ha hecho click en IExplorer 7 y 8

Este molesto comportamiento del navegador de Microsoft es particularmente antiestético cuando se utiliza un mapa poligonal de coordenadas que llama a funciones Ajax (por lo que no abandonamos la página que contiene el enlace clicado). Por ejemplo:

Problema de focus en iexplorer 7 y 8

Aunque a simple vista parece una tontería, la realidad es que se puede perder mucho tiempo intentando eliminar dicho borde punteado a través de CSS y luego a través de Javascript mediante complicados gestores de eventos.

Sin embargo, una vez conocido el truco, en realidad es bastante sencillo. La clave está en el hecho de que dicho borde se presenta sobre el enlace activo (el último que ha recibido el focus) por lo que lo que se debe hacer es quitar el foco de atención (focus) del objeto sobre el que hemos hecho click, en el mismo instante en el que se fija dicho foco de atención.

Los elementos clave de la solución son:

  • Método para quitar el foco de un objeto : objeto.blur();
  • Evento al que debemos estar atentos : objeto.onFocus();

Personalmente prefiero realizar el truco utilizando jQuery, que facilita la elección del elemento o elementos sobre los que deseamos actuar, por lo que el código que realiza el la magia sería algo así:

$(".elementos_sobre_los_que_actuar").focusin(function(){
	$(this).blur();
});

Si se prefiere utilizar Javascript puro, la selección del elemento o elementos sobre los que actuar debe hacerse de manera más artesanal utilizando las funciones getElementById o getElementsByTagName y bucles para recorrer los arrays devueltos, pero la idea es la misma.

Error «order creation failed» / «creación de pedido fallida» en Prestashop 1.3.1, 1.3.7 y 1.4.16

For non spanish readers, the short version:

The problem is related to your MySQL version. It fails with 5.1.x and 5.5.x versions.
Prestashop 1.3.1 : add the lines:

$order->invoice_date = '0000-00-00 00:00:00';
$order->delivery_date = '0000-00-00 00:00:00';

just before the order creation ($order->add()) in your «damaged» payment module.
Prestashop 1.4.x : modify your ps_orders table structure:

alter table ps_orders modify reference varchar(14) null;

Prestashop 1.3.7 : Presumably the error is one of both, or related with null values in that table.

Y la historia larga en castellano:

Después de varios días buscando una solución a este error y de no encontrar nada concluyente en la web, por fin he dado con ello.

El error en cuestión ocurría al intentar realizar un pago contrarreembolso (módulo cashondelivery) y también al intentar realizarlo por transferencia bancaria (módulo bankwire). El pago a través de PayPal funcionaba correctamente (por suerte).

El problema empezó a ocurrir después de realizar una migración de servidor de una máquina más antigua a una máquina más nueva.

Inicialmente pensé que el problema era una incompatibilidad entre el PHP instalado en mi nuevo servidor y el código de mi versión de Prestashop por lo que decidí actualizar la tienda a la última versión. Comprobé que el error se seguía dando en las versiones 1.3 7 y también en la 1.4.16.

Un post en http://www.prestashop.com/forums/viewthread/29422/third_party_modules/solved_order_creation_failed_with_every_payment_module_help_1_dot_2_dot_4/ me puso sobre la pista de que el problema estaba en la base de datos o en el conector a la base de datos. Después de trazar las consultas en la base de datos vi que en la versión 1.4.16 la consulta que se intentaba ejecutar :

INSERT INTO `ps_orders` (`id_address_delivery`,`id_address_invoice`,`id_c
art`,`id_currency`,`id_lang`,`id_customer`,`id_carrier`,`secure_key`,`payment`,`
module`,`conversion_rate`,`recyclable`,`gift`,`gift_message`,`shipping_number`,`
total_discounts`,`total_paid`,`total_paid_real`,`total_products`,`total_products
_wt`,`total_shipping`,`carrier_tax_rate`,`total_wrapping`,`invoice_number`,`deli
very_number`,`invoice_date`,`delivery_date`,`valid`,`date_add`,`date_upd`) VALUE
S ('15','15','690','1','3','3','15','8ebb6bdaaabe8e9daa8f15d774042747','Cash on
delivery (COD)','maofree_cashondeliveryfee','1','0','0','BLA:10','','0','91.67',
'91.67','81.67','81.67','10','0','0','0','0','0000-00-00 00:00:00','0000-00-00 0
0:00:00','0','2011-03-18 20:02:32','2011-03-18 20:02:32');

tiraba el error :

ERROR 1364 (HY000): Field 'reference' doesn't have a default value

Lo cual nos llevaba directamente a la causa del problema: en versiones anteriores de la base de datos o del conector, mysql gestionaba los nulls y/o cadenas vacías de manera diferente. Lo solucioné modificando la estructura de la base de datos permitiendo que el valor de ese campo por defecto fuese null:

alter table ps_orders modify reference varchar(14) null;

En la versión 1.3.1 el error en la consulta no venía de este campo sino de los campos invoice_date y delivery_date, a los que no se les asigna un valor por defecto. En este caso la solución podría haber sido la misma, pero preferí modificar el código PHP del módulo cashondelivery añadiendo las líneas :

$order->invoice_date = '0000-00-00 00:00:00';
$order->delivery_date = '0000-00-00 00:00:00';

en el fichero principal del módulo, en la parte en la que se crea la orden, justo antes de la instrucción $order->add() que la añade a la base de datos.

He de decir que inicialmente intenté esta misma solución por código para el caso de la versión 1.4, pero ninguna de las líneas

$order->reference = "null";
$order->reference = "";

añadidas en el sitio adecuado surtió el efecto deseado y el error persistió.

Este error está relacionado con la utilización de MySQL 5.5.x y por los reportes de error que he leído en algunos posts, también con MySQL 5.1.x.

No investigué el error exacto en Prestashop 1.3.7, pero presumiblemente es alguno de estos 2, o está relacionado con valores null en esta tabla.

Al instalar Bind : «Unable to create account for the service» en Windows 2008

For non-spanish readers the short answer:

Use a longer and more complex password, Windows password policies are preventing Bind from creating the necessary account. Works like charm 😉

Y la historia larga en castellano:

Hoy tuve que instalar el servidor de DNSs Bind en un Windows 2008 y al hacerlo me di con el mensaje de error «Unable to create account for the service». Después de dicho mensaje, el sistema no permitía hacer nada y por supuesto Bind no se instalaba.

Después de buscar en diferentes foros y encontrar muchos casos similares sin solución, encontré alguien que sugería crear la cuenta de usuario desde Windows y luego asignar dicha cuenta a Bind. Me pareció razonable, así que fui a crear un usuario con una contraseña del tipo «1234» y, oh sorpresa, Windows no me dejaba:

«The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.»

Visto lo visto supuse que era lo mismo lo que le estaba ocurriendo internamente a Bind, así que volví a ejecutar el instalador y esta vez elegí una contraseña más larga, con puntos, números y letras. Voilá, la instalación funcionó a las mil maravillas.

Instalar Ruby on Rails en Windows 7

En el momento de escribir este artículo:
Versión de Ruby : 1.9.2
Versión de RubyGems : 1.3.7
Versión de Rails : 3.0.0

Según la página de RoR la instalación es coser y cantar, sin embargo la realidad es algo diferente. La teoría, según http://rubyonrails.org/download es:
1. Descargar el instalador de Ruby y ejecutarlo.
2. Descargar RubyGems e instalarlo usando el comando «ruby setup.rb» en la carpeta que acabamos de descomprimir.
3. Instalar Rails mediante RubyGems ejecutando el comando «gem install rails».

En la práctica, el paso 1 funciona sin problemas, pero al intentar instalar RubyGems nos encontramos con el error:

«source_index.rb:68:in `installed_spec_directories’: undefined method `path’ for Gem:Module (NoMethodError)»

Después de dar muchas vueltas averigüé que el problema es que Ruby 1.9.2 ya viene con RubyGems de serie, por lo que el intento de reinstalación falla. Solución: Simplemente obviar la instalación de RubyGems. Simple, ¿no?, espero haberte ahorrado varias horas de revisión de código, lectura de foros, etc.

Bien, el siguiente paso es instalar Rails, lo cual va como la seda.

Una vez instalado, sin embargo, cuando intentemos poner en marcha nuestro primero proyecto después de crearlo y cuando ya pensábamos que estaba todo ganado, el sistema nos volverá a sorprender con otro mensaje de error:

«Could not find sqlite3-ruby-1.3.1-x86-mingw32 in any of the sources»

Este es fácil de solucionar, Ruby nos informa que sqlite no está instalado, y como es el servidor de BD por defecto, se queja. Ejecutando:

gem install sqlite3-ruby

queda solucionado. Sin embargo la impaciencia nos hará volver a intentar lanzar nuestro proyecto, así que es muy posible que obtengamos el nuevo error :

«sqlite3-ruby-1.3.1-x86-mingw32/lib/sqlite3.rb:6:in `require’: no such file to load — sqlite3/sqlite3_native (LoadError)»

Otra vez volví a dar muchas vueltas hasta que me di cuenta de que al instalar sqlite3, el sistema me había informado que las DLLs necesarias para poder ejecutar este módulo (gem) están en http://www.sqlite.org/sqlitedll-3_6_23_1.zip, es decir la instalación del módulo mediante «gem install» no es suficiente, además hay que instalar una dll manualmente. Así que descargamos ese fichero, lo descomprimimos y copiamos su contenido en la carpeta bin de nuestra instalación de Ruby, que en mi caso es c:\Ruby192\bin\. Una vez hecho esto, podremos por fin poner nuestro servidor Webrick en marcha y comenzar a trabajar simplemente ejecutando:

rails server

Espero que sea de utilidad. ¡Y happy Railing!

{ Piensa / Think }

"This is a waste of life. [...] the entire educational system in the modern day is nothing more than a cookie cutter processing plant that prepares humans for mostly predefined occupational roles. This element of human life has become so traditionally ingrained, that many falsely consider the nature of ‘having a job’ some form of human instinct. Even parents will ask their kids “What do you want to be when you grow up?” as though there was only one thing. This is disturbing and a violation of human potential." - The Zeitgeist Movement


"He aprendido que hay cosas que pueden ser comprendidas pero que nunca podrán ser explicadas con palabras sin desvirtuar su grandeza" - Andrés Pascual


"You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete." - Buckminster Fuller


"... I am the master of my fate. I am the captain of my soul." - William Ernest Henley