Se acercan al mes y medio

Ayer llevé a lo cachorritos al veterninario a desparasitar; ya se quedó a sus dos cachorros que había elegido. En principio son chicos para entregarlos, pero como estan comiendo no parecen cachorros de cinco semanas.

En este momento tengo tres: Uno se lo queda una persona del antiguo cliente principal y le puso Loki. Ese cachorrito es el mas chico de todos, pesa 1.150 kilos, la perrita que queda es la mole, de 1.600 kilos, y al otro jaspeado lo estamos llamando Thor para diferenciarlo de Loki y creo que se lo quedan la ayudante de la veterinaria donde le hicieron las placas a la mamá. Tenemos que echarnos una vuelta a ver si todavia lo va aquerer. Ese pesa 1.590 kilos.

Dice el veterinario que solo Loki de los cinco parece de un mes.

Los otros ya estan del otro lado. Solo he visto el caracter de la mole nteriormente en una maltés, pero se ve ue es buen animalito.

MI idea era hacer la prueba de caracter el 6 de octubre, así que creo que los entrego el 10. Quizá aporvecho y entrego a Loki el 6 de octubre después de comprobar el caracter que tiene.

21 de septiembre

4 .15 am

ya quiero que sea viernes.

Podría hacer una list de pendiente pero en realidad son dos.

1 ) Programnar las ultimas 200 lineas de codigo para lo de 2 proveedores
2 ) El martes despues de ver a los clientes del centro histórico quedarme de guardia en mi casa revisando si hay algun problema con la liberación de el módulo a trves de mi como proveedor.

Lo demás es lo de menos.

Cinnamon listo, Rosa en camino

Hoy tuve que despedir a un DevOps.

¿Porqué TRATAN de pasarse de listos?

Básicamente me pusieron como pretexto que estaba pasando un problema con Linux y servidores que configuré hace unos cuatro meses y en los que yo entro perfectamente desde hace varios meses. LO verifiqué y era mentira. Todo por justificar un problema de deployment de un gem ruby.

Nota 2016: Para los que no esten acostumbrados, gem en ruby viene siendo una especie de librería. Docker es un sistema de deployment relativamente reciente pero con dos fallas principales. la primera es que comparte direccion ip con «los vecinos de contenedor madre», así que puedes tener relativamente simple problemas de intentos de hackeo o abusos por programas malos vecinos alojados en ese server, y la segunda es que aplicar la guia del gobierno de USA sobre hardening de Docker y kubernetes es  necesaria pero al mismo tiempo consume demasiadas horas que nadie te va a pagar y ese era el objetivo de Docker. Te resulta mejor a veces un shared hosting o máquina Virtual en imagen ISO por velocidad de deployment.

 

Lo malo es que perdí unas siete horas reales para demostrarlo. Necesitaba una pc con Linux no emulado para tener acceso a un entorno de Eclispse , y hacer algo con wireshark.

Por casualidad y otras razones, me traje el viernes de la oficina del cliente a mi casa la computadora Brix. Uno de los pasos previos fue instalar en un USB de 4 gb un Live CD de la versión 17.2 Cinnamon de 64 bits de Linux Mint, que tiene muy buen soporte de hardware raro y que se supone que si jala la Brix. Solo que, como necesitaba hardware no emulado, era necesario borrar todo e instalarle desde el USB. Varios problemas.

Tuve que configurar la Pc para que arrancara el disco SATA en modo IDE. Instalar como tres veces. Luego bajar wireshark. Firefox. Etc.

Luego ir a la oficina donde se supone estaban justificando los tiempos extras de domingo, porque capistrano, una herramienta práctica para deployment no estaba funcionando o estaba mal automatizado.

LLego junto con el socio de esa empresa, a la zona de Polanco.

A ver, muestrame que problema tienes con Docker y con Capistrano.

Es que …

Se supone que llevas con eso una semana. Conozco lo suficiente para saber que no estas usando control de versiones y que lo que me describes es Vagrant y no capistrano.

(Explicacion larga del DEVOPS que se resume a las direcciones ip no checan, el .gem esta mal y se esta mandando lo mismo y no la actual).

Me doy cuenta que a pesar que la gem está preparada para distribuirse con Capistrano y en su caso pasarse a un contenedor Docker (a los que detesto por varias razones, entre ellas que tiene derecho de root interno y externo asi como los problemas de conflictos de ip si n o es la misma en el docker que en el desarrollo), el esta usando rubygems.org o algo que se le parece.

Es que no se puede con capistrano !!!, dice.

Le pregunto enfrente de las otras dos personas, al socio que esta terco en agarrar cosas de Ruby en lugar de .net o .php …. que hacemos ?

– Que sugieres ?

– Les parece bien que si puedo hacer yo deployment de la versión de hace ocho dias por Capistrano, revisemos que esta pasando ?

– Si , pero necesitarías una computadora.

Saco de la bolsa del super una caja pequeña, que es como se ve a terceros una computadora brix. Le digo al programnador no docker que quite el teclado y raton de la pc del problema, mientras yo desconecto un monitor.

Conecto la Brix., Selecciono correo, slecciono lugar. Abro el SSH. Cambio una linea para que sea

require ‘bundler/capistrano’

Problema demostrado. Instalo el gem de hace ocho dias, y claro que se soluciona el problema.

Voy entonces a la maquina a la que le quitamos el teclado y veo que ni suqiera estan haciendo el deployment en el docker correcto. Así que aunque cedí en el uso de docker (cosa que fue un error ya que aunque es una forma rápida y mas o menos directa de hacer deployment en Ruby tiene detalles que complican su uso ), todo el probelma fue porque alguien actualizaba en base a su vagrant y no al deploymento que yo mandaba por Capistrano.

Resultado: Doce mil pesos tirados a la basura. Lo bueno es que no lo contraté yo, que el tipo no tenía siquiera un mes, y verificar que Capistrano, al ser herramienta de ruby, es mas estable que la via de Docker / Vagrant.

La razón de correrlo NO fue desobedecer ordenes, se supone que el era mas experto que yo en Ruby. Lo tuvimos que correr porque el menso no se dió cuenta que estaba haciendo deployment de algo de su computadora y no lo que yo le mandé. Así que no se dio cuenta de la versión y tampoco estaba usando el GIT. Nos hizo perder dos semanas, y las pruebas las hacía en su docker, no en el del cliente, que pudo haber sido en un principio un sitio web. Supongo que tendremos que hablar de nuevo con el gerente de sistemas del cliente para verificar que quiere docker y no sitio web. Probablemente no está consciente de la necesidad de root, o lo marearon con las ventajas de docker.

Pero a final de cuentas es mejor para todos hacer deployment a traves de una maquina virtual , un sitio web y el camino antiguo de Ruby on Rails, que meterse con docker.

Cuando descubro que esta haciendo deployment por Vagrant y no por capistrano, me pregunto porqué alguien que no programa en Ruby (mi socio) contrata a programadores Ruby sin pasarlos primero para visto bueno.

Y perdí muchas horas. Alcancé a activar en el proyecto del martes la interfaz para proveedores y programar una de las dos, pero no terminé la segunda.

Son las once de la noche, mañana que regrese de mi viaje, tengo además que llevar los cachorros al veterinario.

Dejaré bajando Rosa, la versión 17.3 de Mint y hora de acostarse. El miércoles tendré que dejar esta lnux para trabajar, pero por lo menos geany y bluefish ya funcionan.

siete de la mañana

Y vamos de vuelta.

Lo primero que hay que hacer hoy es revisar punto por punto que se quiere hacer,

Considerando que mañana estoy todo el santo día fuera de la ciudad, creo que la proridad es preparar una interfaz para cambiar al vuelo lo que hace el sistema en cuestion de dos proveedores. Se supone que la diferencia es que en vez de salir SOLAMENTE por el proveedor actual, debería tener un switch para que sin programar pueda cambiar el destino de lo que está haciendo; la primera opción no lo es. Simplemente se trata de crear un parametro en la tabla de datos que detecte porqué proveedor salir.

En cuanto a programar por el nuevo proveedor, se supone que son unas 100 a 200 lineas de código por proveedor, en procesos que se llaman por un rénglon solitario en un solo archivo.

No va a ser un dia agradable.

Sacaré a pasar a los perros y a darle.

una de la mañana de domingo

Es poco mas de la una de la mañana de domingo.

Programé casi 14 horas seguidas. Una hora y media mas o menos para la parte inicial de los tres correos anteriores, el resto para crear un ambiente de pruebas para mi trabajo de mañana. Pero ya esta migrado y probado un sistema de 85 pantallas , LEGACY, en otro server.

Nada mal.

Trabajando con un sistema multiinstalado – III

Esto nos implica dos necesidades primordiales :

1 ) modificar installer
2 ) Crear funciones en el servidor original

EL codigo es simple pero por cuestiones tecnicas no conviene ponerlo en un gist. Lo pongo como php html entities encode, aunque hay varios htmlentities en linea, sugiero este :
https://mothereff.in/html-entities

Por cierto, por necesidades Tecnicas se recomienda no usar campos (bit) en mysql sino int . EN exportaciones de contenido se pueden crerar muchos problemas. Debe quedar claro que el código que sigue es borrador pero funcional.

Por simplicidad voy a codificar en el servidor AUTORIDAD a donde debe enviar por ftp. Hay borrador de como pasar el dato del server de cada instalación.

Installer.php en el server deseado, ojo que viene como htmlentities


<?php nocache(); echo "Installer v 0.001"; crearconfig(); require "configmysql.php"; // datos de conexion de tu sitio define ('FTPSERVER',"ftp.desiredserver.com"); define ('FTPUSER',"user"); define ('FTP_PWD',"password"); define ('PATH',"/public_html/"); define ('MAIN_REPO','http://your-auth-domain.com/shachecker.php'); echo "<h3>Checking versions of the files</h3>"; bringfile("php.ini"); bringfile("robots.txt"); bringfile("favicon.ico"); bringfile("index.php"); // you need create first the images directory bringfile("images/information_ico.png"); // you need create includes directory first bringfile("includes/javafile.js"); //bringfile(".htaccess"); // NOT UPDATE .htaccess, can create MANY problems echo "<h3>Checking data struct of the tables</h3>"; bringtable("USERS"); bringtable("OTHER_TABLE"); echo "<h3>Update is done, try to run it <a href='index.php' target='_blank'>index.php</a></h3>"; function bringfile($filename){ if (file_exists($filename)==1) $mysha=sha1_file($filename); $base64=base64_encode($filename); $theurl=MAIN_REPO ."/shachecker.php?filename=$base64"; $result=curl_download($theurl); $ex=explode("|",$result); if (sizeof($ex)<>3) die ("<li><font color='red'>$result <hr>Not valid response of $theurl, check the filename</font>"); $othersha=$ex[1]; //echo "<li>tamaño de ".sizeof($ex); //echo "<li>$result<li>$othersha"; if ($othersha==$mysha) echo "<li><font color='green'>$filename is in current version</font>"; if ($othersha<>$mysha) { echo "<li><font color='red'>$filename is not in current version</font>"; askforfile($filename); } //if ($mysha<>$othersha) } // bringfile function noCache() { header("Expires: Tue, 01 Jul 2001 06:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } function curl_download($url){ $ch = curl_init(); $timeout = 5; curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout); //curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($ch) or die ("error in curl $url"); curl_close($ch); return $data; } function askforfile($filename){ $ftpdata="&to=".base64_encode(FTPSERVER."|".FTPUSER."|".FTP_PWD."|".PATH); $theurl=MAIN_REPO ."/shachecker.php?filename=".base64_encode($filename)."&please=send$ftpdata"; //die("<li>$theurl"); $result=curl_download($theurl); die ("<li><h2>response: $result</h2><hr>Continue with f5 if not resume itself <META http-equiv='refresh' content='0;URL=installer.php'>"); } // askforfile function asktable($tablename) { $theurl=MAIN_REPO ."/shachecker.php?tablename=".base64_encode($tablename); //die("<li>$theurl"); $result=curl_download($theurl); $result64=base64_decode($result); $allok='N'; if (left($result64,2)=='||' and right($result64,2)=="||" ) $allok='Y'; if ($allok=='N') die ("Error in table struct<hr>$result"); $sql=str_replace("||","",$result64); mysql_query($sql) or die ("Error creating table $tablename :<hr>".mysql_error()); die ("<li>Table $tablename created ... continue with f5 if not resume itself in 3 seconds < META http-equiv='refresh' content='0;URL=installer.php'>"); } // ask table function crearconfig(){ if (file_exists("configmysql.php")==1) return ; $content="<?php Define ('Z_IPSERVIDOR','localhost'); Define ('Z_USUARIODB',''); Define ('Z_PASSDB',''); Define ('Z_NOMBREBASE',''); ?" .">"; file_put_contents('configmysql.php',$content); echo "<li><font color='blue'>Config created</font>"; } // crear config function checktable($tablename){ $pass="N"; mysql_connect(Z_IPSERVIDOR,Z_USUARIODB,Z_PASSDB) or die ('Cant connect : ' . mysql_error()); mysql_select_db(Z_NOMBREBASE) or die ('Cant use database : ' . mysql_error()); $result=mysql_query("SHOW TABLES LIKE '$tablename'"); $numtables = mysql_num_rows($result); if ($numtables>0) $pass ="Y"; return $pass; } // checktable function bringtable($tablename){ $result=checktable($tablename); if ($result=='Y') { echo "<li><font color='green'>$tablename already exist</font>"; return; } if ($result<>'Y') { // no existe return asktable($tablename); } // result <>' y' } // bringtable function left($str, $length) { return substr($str, 0, $length); } function right($str, $length) { return substr($str, -$length); } ?>

shachecker.php en el server AUTORIDAD , ojo que viene como htmlentities


<?php $filename=base64_decode($_GET['filename']); if ($_GET['please']=='send') deliverfile($filename); $pass="file not exist|$filename"; if (file_exists($filename)==1) { $perms=fileperms($filename); $pass= $filename."|".sha1_file($filename)."|$perms"; } die ($pass); } IF ($_GET['tablename']){ $tablename=base64_decode($_GET['tablename']); //conectar(); include "configmysql.php"; mysql_connect(Z_IPSERVIDOR,Z_USUARIODB,Z_PASSDB) or die ('Cant connect : ' . mysql_error()); mysql_select_db(Z_NOMBREBASE) or die ('Cant use database : ' . mysql_error()); list($dummy,$data) = avalues3192("show create table $tablename"); $data="||$data||"; // || for not tamper $pass=base64_encode($data); die ($pass); } function deliverfile($filename){ $ftp_server="ftp.example.com"; // your domain DESIRED //$ftp_server="93.184.216.34"; // sometimes is better put the ip directly $ftp_user_name="your user"; $ftp_user_pass="your pass"; // a safe password $source=$filename; $target="public_html/$filename"; $conn_id = ftp_connect($ftp_server); // set up a connection to ftp server // login with username and password $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); // check connection and login result if ((!$conn_id) || (!$login_result)) { echo "<li>FTP connection has encountered an error! <br />Attempted to connect to $ftp_server for user $ftp_user_name...."; exit; } else { echo "<li>Connected to $ftp_server, for user $ftp_user_name"."....."; // upload the file to the path specified $upload = ftp_put($conn_id, $target, $source, FTP_BINARY); // check the upload status if (!$upload) { echo "<li>FTP upload has encountered an error!"; } else { echo "<li>Uploaded file with name $target to $ftp_server "; } } // close the FTP connection ftp_close($conn_id); die(); } // subir archivo por ftp function aValues3192($Qx){ $rsX = mysql_query($Qx) or SQL_ERROR("Avalues 3192",$Qx); $aDataX = array(); $Campos = mysql_num_fields($rsX); while ($regX = mysql_fetch_array($rsX, MYSQL_ASSOC)) { for($iX=0; $iX<$Campos; $iX++){ $aDataX[] = $regX[ mysql_field_name($rsX,$iX) ]; } } return $aDataX; } ?>

Trabajando con un sistema multiinstalado – II

En pseudo código la respuesta es para cada proyecto individual mas o menos simple.

La necesidad real de seguridad sale a travpes de archivos que se actualizarán por FTP. La versión master no debe dar sus datos de acceso a ftp enos que sea de solo lectura, por l oque se sugiere que el ftp autoridad no maneje datos de conexion pero la receptora si puede darlos de su propio sistema.

Una vez considerado eso, Solo es necesario crear un validador de clave de sha1_file o su equivalente en el server autoridad, para revisar que sean los mismos.

Paso 1 : En el server nuevo Entrar el installer.php, que es el unico archivo existente. Ese luego actualizará inclusive el index.php
Paso 2 : Verificar quye haya conexión con el server autoridad. El dato del server autoridad incluso puede leerse de twitter. En casos extremos incluso claves de ftp temporales pueden pasarse por twitter.
Paso 3 : Revisa si existe updater.php que debería tener un nombre genérico como ePGTXbw87B96KuP77.php , pero para fines prácticos lo llamaeremos udpater.php
Paso 4 : Revisa con la autoridad (server viejo) que la versión de updater.php sea la misma en ambos servidores. Si no lo es, copiar el de la autoridad por FTP
Paso 5 : Update revisa la existencia y versión de cada archivo del poryecto, así como crear directorios para todos lo que se utilicen y checar que el chmod, por lo menos de directorios, sea el mismo.
Paso 6 : Verificar la versión de MYSQL y avisar
Paso 7 : Verificar si hay conexión con la base de datos local, y si no la hay, pedir datos para configuración
Paso 8 : Crear todas las tablas de datos sin informacion pero con llaves primarias y foráneas, si las hay (preferentemente deben estar definidas en código asi como el generador de índices tipo lo que se hacía en foxpro/clipper a mediados de los 90s)
Paso 9 : Crear / validar que ls tablas tengan los mismos campos. Probablemente un numero de versión de la estructura de base de datos, NO solamente versión del manejador de base de datos.
Paso 10 : Ideal pero para etapa posterior, crear un validador de la integridad referencial.
Paso 11 : Si todo esta ok, borrar solito el installer.php y dejar una función interna que actualice bajo demanda o automático haciendo lo mismo que hacia installer.php que a su ve el nuevo archivo debe actualizarse solo al buscar / detectar nueva versión

Una vez hecho esto, la respuesta es prueba y error obligando a que exista la información básica y creando pantallas temporales de captura o metiendo el dato default a mano.

Considerando que los nombres pueden ser unicode o extraños, el código de sha debe considerar encriptado simple y no texto llano, además es mejor si se enuentra en un archivo igual con nombre raro como JRnBxzYy272YqFPA.php pero lo llamaremos de momento verificador_de_sha.php y debe tener algo similar a :

suponiendo que base64_encode de index.php es aW5kZXgucGhw,

< ? php
IF ($_GET['filename']){
$filename=base64_decode($_GET['filename']);
$pass="file not exist|$filename";
if (file_exists($filename)==1) {
  $perms=fileperms($filename);
  $pass= $filename."|".sha1_file($filename)."|$perms";
}  
DIE ($pass);
}
? > 

y lo llamaríamos como : http://example.com/verificador_de_sha.php?filename=aW5kZXgucGhw obteniendo como respuesta un :

index.php|9bd598f9e8d4f889aa18bc733c2c95b64091a6d4|33188

Trabajando con un sistema multiinstalado – I

Sistemas como wordpress que existen en cientos , miles o millones de instalaciones, no pueden, y a veces no deben, mantenerse todos en la misma versión con un control central. Las razones van desde versione de PHP, ser de diferentes dueños las instalaciones etc. Sin embargo, el que un sistema se mantenga actualizado por si solo como los antivirus, y en ocasiones wordpress, tiene sus ventajas.

Sin embargo hay momentos donde le probelma es otro.

Ejemplo: EN el año 2010 desarrollé para un cliente , por nómina, un sistema que estaba pensado para clientes X, y y z donde los Z eran los mayores y con mas prestaciones. Deje de ver el sistema, y años espués me enteré que tenían unas 20 versiones diferentes en diferentres clientes y los sistemas no se mantenín actualizados y no podían entrar en diferentes servidores. Incluso no sabían QUE versiones tenian en cada cliente. Independientemente de que eso es un desastre como proceso, tuvimos un problema fuerte cuando solucioné algo en el código central y nunca lo pusieron en los otros. Incluso no sabian si los clientes tenian instalado que.

En tiempos modernos lo ideal sería tener instalado un repositorio CONFIABLE tipo Git. Pero que pasa cuando el código es sensible y privado ? Hace unos mesdes salió un problema en foros de sistemas por personas que pusieron sus claves de Amazon en repositorios ocultos, que visual estudio por error no hizo ocultos, y cuentas de S3 de amazon fueron hackeadas. Por lo mismo, y por los problemas de «clearing» o control de daños de posibles , ni siquiera reales contraseñas expuestas, nunca permito que se use Github como base de código sensitivo, sea por u naturaleza o porque se un cliente de pago. En todo caso prefiero instalar un fork en un server de mi empresa, y obligar a que todos los proyectos y summit sean privados.

Pero eso no resuelve el problema básico.

Vamos a ver cuatro escenarios que me estan pasando en este momento:

1 ) Hay un sistema funcional en php que maneja mas o menos 300 archivos de diversos tipos. ALrededor de la tercera parte de ellos son LEGACY además de black box. Es decir, son antiguos, no desarrollados por mí, y un desastre tal de jquery mal hecho que conviene mas no hacerles nada y dejarlos como estan en lo que se cambian por algo mejor. De momento el cliente mueve mas de cien millones de pesos y 200 toneladas de producto y no tienen problemas con mi parte del código. El Legacy se va arreglando poco a poco, pero tienen que hacer un cambio en un módulo secundario que está conctado a sistemas financieros, y que no conviene hacer en vivo por dos razones : Una que interrumpe una operación de tres millones de pesos diarios, y dos, que no hay porque hacer «reales» las pruebas. Si desconectamos el servicio oque procesa lo financiero las pruebas no pasan de eso, pero desconectar y conectar el servicio puede tener un costo potencial enorme.

2 ) Otro cliente tiene un sistema que tiene tiene actualmente solo un proveedor de un proceso crítico que se consume por Webservice. Ya desarrollé un webservice que mejora y soluciona un problema que tienen y conseguí dos proveedores alternos como plan B. Pero, como no puedo parar la operación de un sistema usado diariamente por 600 a 700 usuarios, tampoco puedo hacer pruebas porque el cliente tiene el riesgos de molestar a sus usuarios y cada usuario le da unos 2000 pesos al año.

3 ) UN cliente me pide que migre un sistema hecho por otra persona en PHP 4.4.9 con librerias de bases de datos incompatibles con la realidad actual de servers pero sus sistema ya dejó de funcionar. No es vitl pero hay un mes en promedio para arreglarlo. Lo ideal sería hacer pruebas propias COPIANDO sus datos, y que su actualización sea de archivos php previo respaldo. Así que un server debe ser autoridad en php para versiones, y otro debe ser de datos. Idealmente, al terminar las pruebas se copia un archivo en su servidor, se dice actualizar y todo su código se convierte la nueva versión con soporte para mysqli sin PEAR.

4) Hay otro sistema que tiene problemas de versiones de bases de datos, debido a que el cliente tiene dos instalaciones del software en diferentes servers, y uno se dañó. El respaldo es de hace seis meses pero no perdió información, solo que la versión actual tiene unas doce tablas mas de base de datos y unos 300 campos nuevos asi como unos 20 a 40 removidos. Se busca que el sistema autiactualice la estructura de su base de datos con un maestro, y después el código de los dos servers se actualice para que sean identicos. Preferentemente sn intervención humana.

Los cuatro problemas tienen la misma solución básica y son problemas reales a los que me estoy enfrentando en este momento. Lo que se necesita es que se actualicen contra una instalación en otro lugar, y estar seguros que no está bloqueada la dirección web base.

Además, es probable que no pueda usarse el mecanismo estáandar de «instalar y ajustar» porque solo el 2 tiene instalador. Es decir, simplemente no debería copiarse a mano a un ambiente de pruebas. Y si las bases de datos son de varios gigabytes, debe considerarse como maestro de datos al del cliente, no al revés, pro ajustar epués porque la estructura debe ajustarse, los archivos de imagen y pho deben ajustarse pero el contenido de la base de datos NO debe pasar de una instalación a otra. LO ideal sería que el ambiente de pruebas tome los archivos de producción como autoridad, y una vez que el código sea igual, invertir la autoridad. Es decir, que el de producción pueda actualizarse contra una instalación moderna que lo copió en primer lugar, en cuanto a archivos se refiere. El proceso de replicación de base de datos presenta problemas tanto por ser información confidencial, como por la no existencia de scripts uqe creen la integridad referencias con llaves foráneas. Así que, en segundo paso, debe verificarse el esquema con una herramienta diferente, que puede ser un script a la medida que vaya creando cada integridad foránea. Si consideramos que cada versión de mysql tiene sus detalles al crgar código *.sql de versiones antriores, el primer requisito es validar que la base de datos sea la misma versión. NO diferente. No se uede hacer lo mismo con la versión de php ya que rompería código u operación pero si mostrar una recomendación de actualizar la versión (y me parece que menos el problema 3 todos los otros usan por lo menos 5.3)

CInco de la mañana de sabado

Hace treinta años hubo un temblor fuerte en mexico.

Acabo de sacar a pasear a los perros. Tengo un fin de semana de programación y nada de descanso. Asi que empecemos con las entradas tecnicas.

Qué tragazón ….

Por un accidente sucedido con uno de los clientes hoy, uno de los integrantes de mi SA de CV, que no era yo, se manchó el pantalón de quien sabe que. Pero eran horas de trabajo y afortunadamente el programador iba en jeans como le dije, asi que mientras hablabamos de los cambios por hacer con los clientes del nuevo giro, nos fuimos caminando a una plaza cercana donde hay un wallmart. Compré unos jeans deducibles de impuestos por ser accidente de trabajo el maltrato, luego nos fuimos a comer los tres a un area de comida rápida, pero hubo un malentendido, asi que en lo que yo fui al baño, mi esposa, el otro programador y yo pedimos cada quien para los tres en tres lugares diferentes.

Que bueno que estamos hablando de tres empresas voy a poder facturar con cada una de las tres.

Por un lado, una arrachera buenisima que ya conozco de 85 pesos en buffet y que tiene barra de guarniciones y de postre platanos con crema. Comprado para tres.

Por otro, El programador que compró comida china porque veniamos hablando de eso, y compro tres ordenes del menu 2 de comida china.

Y yo que compré seis makis de sushi, con 9 kushiages.

Hacia mucho que no me reia tanto por un malentendido.

Comimos lo que pudimos, y el otro programador se fue a llevarles la comida china y parte de lo otro al equipo que está trabajando con el proyecto de Ruby on Rails.

Y ahi vamos mi esposa y yo de camino al almacen del cliente, repletos … y acabando de subir, me llaman de la parte de abajo.

Resulta que pasó el vendedor ambulante que vende hot dogs preparados con queso y tocino, y para no quedarle mal, me comi uno simbólico. Es raro pero cuando subi si me sentia lleno. Solo comí una arrachera y dos makis de california especial.

Lo que son las cosas, ya son las 18:00 y tengo muchisimo por hacer este fin de semana.