<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dr. Danguer y Mr. Daniel &#187; Trabajo</title>
	<atom:link href="http://vida.danguer.com/category/trabajo/feed/" rel="self" type="application/rss+xml" />
	<link>http://vida.danguer.com</link>
	<description>Un blog más de un freelancer</description>
	<lastBuildDate>Sun, 31 Jan 2010 00:14:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Cuidado al usar Zend_Date</title>
		<link>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/</link>
		<comments>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 00:14:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Fechas]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Date]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=96</guid>
		<description><![CDATA[<p>En un proyecto, estaba utilizando Zend_Date para manejo de horas en diferentes zonas horarias, cuando lo estaba desarrollando empecé a tener un error porque olvidé que la fecha se actualiza cuando cambias un parámetro y el problema surge cuando cambias el mes o día y se encuentra con una fecha inexistente aunque en el código parezca correcta, por ejemplo, supongamos que estamos en el mes de febrero y queremos crear una fecha de marzo (asignaré la fecha para reproducir el error, aunque el error es cuando se utiliza la fecha actual)</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&#62;setDay(31);
$fecha-&#62;setMonth(3);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Uno esperaría que el resultado fuera: <strong>31/03/2010</strong></p>
<p>Pero en su lugar mostrará <strong>03/03/2010</strong></p>
<p>Esto es porque al hacer <code>$fecha-&#62;setDay(31)</code> el sistema intenta crear la fecha: <strong>31/02/2010</strong> que no existe, por lo que &#8220;recorre&#8221; los días restantes para quedar en <strong>03/03/2010</strong>, al asignar el mes, no tiene efecto.</p>
<p>La solución es simplemente hacerlo en orden inverso:</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&#62;setMonth(3);
$fecha-&#62;setDay(31);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Eso parecería la solución ideal (y es la recomendada por la documentación), pero no es totalmente cierta, si por ejemplo estamos en enero 31 del 2010 e intentamos asignar una fecha de febrero, siempre obtendremos una fecha de marzo:</p>
<pre name="code" class="php">include_once 'Zend/Date.php';
$fecha_enero = mktime(0, 0, 0, 1, 31, 2010);
$fecha = new Zend_Date($fecha_enero);
$fecha-&#62;setMonth(2);
$fecha-&#62;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Uno esperaría que mostrara la fecha:<br />
<strong>10/02/2010</strong></p>
<p>Pero en realidad muestra<br />
<strong>10/03/2010</strong></p>
<p>Esto porque cuando asignamos el mes, el sistema intenta crear la fecha 31/03/2010 que una vez más es incorrecta, por lo que crea la fecha 03/03/2010, pero al asignar la fecha, el resultado es un error en el mes.</p>
<p>Aunque esto no es un error, es muy peligroso porque uno puede suponer que la fecha es correcta porque&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>En un proyecto, estaba utilizando Zend_Date para manejo de horas en diferentes zonas horarias, cuando lo estaba desarrollando empecé a tener un error porque olvidé que la fecha se actualiza cuando cambias un parámetro y el problema surge cuando cambias el mes o día y se encuentra con una fecha inexistente aunque en el código parezca correcta, por ejemplo, supongamos que estamos en el mes de febrero y queremos crear una fecha de marzo (asignaré la fecha para reproducir el error, aunque el error es cuando se utiliza la fecha actual)</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&gt;setDay(31);
$fecha-&gt;setMonth(3);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Uno esperaría que el resultado fuera: <strong>31/03/2010</strong></p>
<p>Pero en su lugar mostrará <strong>03/03/2010</strong></p>
<p>Esto es porque al hacer <code>$fecha-&gt;setDay(31)</code> el sistema intenta crear la fecha: <strong>31/02/2010</strong> que no existe, por lo que &#8220;recorre&#8221; los días restantes para quedar en <strong>03/03/2010</strong>, al asignar el mes, no tiene efecto.</p>
<p>La solución es simplemente hacerlo en orden inverso:</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&gt;setMonth(3);
$fecha-&gt;setDay(31);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Eso parecería la solución ideal (y es la recomendada por la documentación), pero no es totalmente cierta, si por ejemplo estamos en enero 31 del 2010 e intentamos asignar una fecha de febrero, siempre obtendremos una fecha de marzo:</p>
<pre name="code" class="php">include_once 'Zend/Date.php';
$fecha_enero = mktime(0, 0, 0, 1, 31, 2010);
$fecha = new Zend_Date($fecha_enero);
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Uno esperaría que mostrara la fecha:<br />
<strong>10/02/2010</strong></p>
<p>Pero en realidad muestra<br />
<strong>10/03/2010</strong></p>
<p>Esto porque cuando asignamos el mes, el sistema intenta crear la fecha 31/03/2010 que una vez más es incorrecta, por lo que crea la fecha 03/03/2010, pero al asignar la fecha, el resultado es un error en el mes.</p>
<p>Aunque esto no es un error, es muy peligroso porque uno puede suponer que la fecha es correcta porque en el código lo parece, la solución sin embargo es trivial, asignar el primer día de un mes que tenga 31 días y asignar los valores en orden inverso (primero año, luego mes y por último día), así el código sin error sería:</p>
<pre name="code" class="php">
include_once 'Zend/Date.php';
$fecha = new Zend_Date(0, 0, 0, 1, 1, date('Y'));
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());
</pre>
<p>Resultado (el esperado)<br />
<strong>10/02/2010</strong></p>
<p>Esto funciona en la mayoría de los casos; aunque si van a manejar diferentes zonas horarias mediante <code>setTimezone()</code> el código anterior tendrá el mismo error en los casos que la zona horaria sea menor a la zona horaria del servidor, por lo que hay que hacer algo más elaborado:</p>
<pre name="code" class="php">
include_once 'Zend/Date.php';
$fecha = new Zend_Date();
//eliminar "errores"
$fecha-&gt;setTimezone('mi_codigo_zona_horaria');
$fecha-&gt;setDay(1);
$fecha-&gt;setMonth(1);

//nuestro código
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());
</pre>
<p>Lo peligroso del comportamiento de Zend_Date es que funcionará con errores durante algunos días/meses dependiendo de la manera en como se programe y es un poco difícil de diagnosticar por su misma naturaleza, con esto se elimina cualquier tipo de errores.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Una hora perdida</title>
		<link>http://vida.danguer.com/2009/11/25/una-hora-perdida/</link>
		<comments>http://vida.danguer.com/2009/11/25/una-hora-perdida/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 07:12:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[strtotime]]></category>
		<category><![CDATA[Tiempo]]></category>
		<category><![CDATA[Zona Horaria]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=95</guid>
		<description><![CDATA[<p>Mientras estaba haciendo un pequeño calendario que mostrara fechas con ligas a otras parte del sitio, pensé que la manera más fácil era evitar llamar a <code><a href="http://www.php.net/strtotime">strototime</a></code>:</p>
<pre class="code">strtotime("+1 days", $time)</pre>
<p>y en su lugar utilizar directamente la suma de <code>86,400</code> segundos que es un día:</p>
<pre>60 * 60 segundos = 3600 segundos (1 hora) * 24 = 86400</pre>
<p>El calendario no tenía ningún problema hasta que noté que tenía repetido dos veces el día 1º de noviembre, los tiempos eran los siguientes (tiempo Unix):</p>
<pre>1257051600: 2009-11-01 00:00:00
1257138000: 2009-11-01 23:00:00</pre>
<p>Si hacen la suma, observarán que se sumó <code>86,400</code> segundos a una fecha y otra; pero el tiempo regresado por PHP (de hecho por el sistema Linux) es de 23 horas y no 24 horas.</p>
<p>Hice algunas pruebas en otros servidores y solo uno imprimió la fecha que esperaba (<code>2009-11-02 00:00:00</code>), la primera idea (por el cansancio) fue que era un error de PHP/Linux. Buscando un posible error, encontré algunas preguntas que como yo habían tenido un problema similar, pero mencionaban algo de la zona horaria, eso me recordó que el 1º de Noviembre en México atrasamos el reloj una hora por lo que en realidad el cálculo era correcto desde la perspectiva de Linux ya que estaba olvidando esa &#8220;hora perdida&#8221; en mis cálculos, el servidor que regresó bien la fecha estaba en otra zona horaria por lo que no compartían nuestro cambio de horario.</p>
<p>El tiempo Unix correcto es: <code>1257141600</code> no es otra cosa que es el día (<code>86400</code>) más la hora &#8220;perdida&#8221; (<code>3600</code>), este tiempo lo obtuve llamando a <code><a href="http://www.php.net/strtotime">strtotime</a></code> en PHP en lugar de calcularlo por mi cuenta.</p>
<p><strong>Moraleja</strong>: Manipular el tiempo Unix de forma directa agregando valores puede ser muy rápido y simplifica la implementación, pero si quieres hacer algo que no tenga errores utiliza siempre las funciones de tiempo de PHP/Linux.</p>
&#8230;]]></description>
			<content:encoded><![CDATA[<p>Mientras estaba haciendo un pequeño calendario que mostrara fechas con ligas a otras parte del sitio, pensé que la manera más fácil era evitar llamar a <code><a href="http://www.php.net/strtotime">strototime</a></code>:</p>
<pre class="code">strtotime("+1 days", $time)</pre>
<p>y en su lugar utilizar directamente la suma de <code>86,400</code> segundos que es un día:</p>
<pre>60 * 60 segundos = 3600 segundos (1 hora) * 24 = 86400</pre>
<p>El calendario no tenía ningún problema hasta que noté que tenía repetido dos veces el día 1º de noviembre, los tiempos eran los siguientes (tiempo Unix):</p>
<pre>1257051600: 2009-11-01 00:00:00
1257138000: 2009-11-01 23:00:00</pre>
<p>Si hacen la suma, observarán que se sumó <code>86,400</code> segundos a una fecha y otra; pero el tiempo regresado por PHP (de hecho por el sistema Linux) es de 23 horas y no 24 horas.</p>
<p>Hice algunas pruebas en otros servidores y solo uno imprimió la fecha que esperaba (<code>2009-11-02 00:00:00</code>), la primera idea (por el cansancio) fue que era un error de PHP/Linux. Buscando un posible error, encontré algunas preguntas que como yo habían tenido un problema similar, pero mencionaban algo de la zona horaria, eso me recordó que el 1º de Noviembre en México atrasamos el reloj una hora por lo que en realidad el cálculo era correcto desde la perspectiva de Linux ya que estaba olvidando esa &#8220;hora perdida&#8221; en mis cálculos, el servidor que regresó bien la fecha estaba en otra zona horaria por lo que no compartían nuestro cambio de horario.</p>
<p>El tiempo Unix correcto es: <code>1257141600</code> no es otra cosa que es el día (<code>86400</code>) más la hora &#8220;perdida&#8221; (<code>3600</code>), este tiempo lo obtuve llamando a <code><a href="http://www.php.net/strtotime">strtotime</a></code> en PHP en lugar de calcularlo por mi cuenta.</p>
<p><strong>Moraleja</strong>: Manipular el tiempo Unix de forma directa agregando valores puede ser muy rápido y simplifica la implementación, pero si quieres hacer algo que no tenga errores utiliza siempre las funciones de tiempo de PHP/Linux.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2009/11/25/una-hora-perdida/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dumpear todas las bases de datos</title>
		<link>http://vida.danguer.com/2009/02/19/dumpear-todas-las-bases-de-datos/</link>
		<comments>http://vida.danguer.com/2009/02/19/dumpear-todas-las-bases-de-datos/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 01:25:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[respaldo]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=91</guid>
		<description><![CDATA[<p>Recientemente tuve que &#8220;dumpear&#8221; todas las bases de datos de un servidor por lo que utilice un script muy simple para hacerlo:</p>
<pre name="code" class="php">
USER=root;PASS=mi_pass;for database in `echo "SHOW DATABASES" &#124; mysql --user=$USER --password=$PASS &#124; sed '1d'`; do mysqldump --user=$USER --password=$PASS $database > $database.sql; tar jcvf $database.tar.bz2 $database.sql; rm $database.sql; done
</pre>
<p>Un poco más leible:</p>
<pre name="code" class="php">
USER=root
PASS=mi_pass
for database in `echo "SHOW DATABASES" &#124; mysql --user=$USER --password=$PASS &#124; sed '1d'`
do
    mysqldump --user=$USER --password=$PASS $database > $database.sql
    tar jcvf $database.tar.bz2 $database.sql
    rm $database.sql
done
</pre>
<p>Básicamente manda todas las bases de datos y quita la linea inicial (que siempre es Databases) y por cada base de datos invoca mysqldump y por último lo comprime con bunzip2 para obtener un archivo muy pequeño y por supuesto elimina las &#8220;fuentes&#8221; de sql.</p>
]]></description>
			<content:encoded><![CDATA[<p>Recientemente tuve que &#8220;dumpear&#8221; todas las bases de datos de un servidor por lo que utilice un script muy simple para hacerlo:</p>
<pre name="code" class="php">
USER=root;PASS=mi_pass;for database in `echo "SHOW DATABASES" | mysql --user=$USER --password=$PASS | sed '1d'`; do mysqldump --user=$USER --password=$PASS $database > $database.sql; tar jcvf $database.tar.bz2 $database.sql; rm $database.sql; done
</pre>
<p>Un poco más leible:</p>
<pre name="code" class="php">
USER=root
PASS=mi_pass
for database in `echo "SHOW DATABASES" | mysql --user=$USER --password=$PASS | sed '1d'`
do
    mysqldump --user=$USER --password=$PASS $database > $database.sql
    tar jcvf $database.tar.bz2 $database.sql
    rm $database.sql
done
</pre>
<p>Básicamente manda todas las bases de datos y quita la linea inicial (que siempre es Databases) y por cada base de datos invoca mysqldump y por último lo comprime con bunzip2 para obtener un archivo muy pequeño y por supuesto elimina las &#8220;fuentes&#8221; de sql.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2009/02/19/dumpear-todas-las-bases-de-datos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Auto inicio de dominios en Xen</title>
		<link>http://vida.danguer.com/2009/01/09/auto-inicio-de-dominios-en-xen/</link>
		<comments>http://vida.danguer.com/2009/01/09/auto-inicio-de-dominios-en-xen/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 22:47:06 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Xen]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=90</guid>
		<description><![CDATA[<p>Algo muy útil es iniciar/apagar automáticamente dominios XEN cuando se reinicia o apaga el anfitrión (<code>dom0</code>), cuando se instala XEN, por defecto deberemos ver creado un directorio llamado <code>/etc/xen/auto</code></p>
<p>En este directorio el script <code>/etc/init.d/xendomains</code> buscará las configuraciones de las máquinas virtuales a iniciar/detener estos pueden ser vínculos simbólicos a las verdaderas configuraciones.</p>
<p>Para que todo esto suceda en primer lugar debes de tener el script <code>/etc/init.d/xendomains</code> que se instala junto con <code>/etc/init.d/xend</code></p>
<p>También debes haber habilitado el inicio de este script con el siguiente comando:</p>
<pre name="code" class="php">
update-rc.d xendomains defaults 21 20
</pre>
<p> <br />
El script <code>/etc/init.d/xendomains</code> necesita del archivo de configuración: <code>/etc/sysconfig/xendomains</code></p>
<p>En este verás una línea que contiene:</p>
<pre name="code" class="php">
XENDOMAINS_AUTO=/etc/xen/auto
</pre>
<p>Con esto definimos el directorio donde se buscarán los dominios que se auto iniciarán</p>
]]></description>
			<content:encoded><![CDATA[<p>Algo muy útil es iniciar/apagar automáticamente dominios XEN cuando se reinicia o apaga el anfitrión (<code>dom0</code>), cuando se instala XEN, por defecto deberemos ver creado un directorio llamado <code>/etc/xen/auto</code></p>
<p>En este directorio el script <code>/etc/init.d/xendomains</code> buscará las configuraciones de las máquinas virtuales a iniciar/detener estos pueden ser vínculos simbólicos a las verdaderas configuraciones.</p>
<p>Para que todo esto suceda en primer lugar debes de tener el script <code>/etc/init.d/xendomains</code> que se instala junto con <code>/etc/init.d/xend</code></p>
<p>También debes haber habilitado el inicio de este script con el siguiente comando:</p>
<pre name="code" class="php">
update-rc.d xendomains defaults 21 20
</pre>
<p> <br />
El script <code>/etc/init.d/xendomains</code> necesita del archivo de configuración: <code>/etc/sysconfig/xendomains</code></p>
<p>En este verás una línea que contiene:</p>
<pre name="code" class="php">
XENDOMAINS_AUTO=/etc/xen/auto
</pre>
<p>Con esto definimos el directorio donde se buscarán los dominios que se auto iniciarán</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2009/01/09/auto-inicio-de-dominios-en-xen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip: Usando rsync para transferencias rápidas entre linux</title>
		<link>http://vida.danguer.com/2008/11/26/tip-usando-rsync-para-transferencias-rapidas-entre-linux/</link>
		<comments>http://vida.danguer.com/2008/11/26/tip-usando-rsync-para-transferencias-rapidas-entre-linux/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 07:37:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[replica]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=87</guid>
		<description><![CDATA[<p>Usualmente uso el famosímo <code>scp</code> para transferir archivos, el problema es que al parecer <code>scp</code> es muy lento cuando se trata de muchos archivos pequeños. </p>
<p><code>rsync</code> es un comando para hacer réplicas de un directorio a otro lugar, lo que hace es checar el comparar los directorios y copiar todos los archivos que hayan sido modificados, que sean nuevos o incluso que hayan sido elminados para hacer una copia exacta.</p>
<p>La gran ventaja de <code>rsync</code> es que aparte de crear una réplica, es sorprendentemente rápido, en especial con archivos pequeños.</p>
<p>El uso es muy simple:</p>
<pre>rsync -az -e ssh FUENTE usuario@servidor:DESTINO</pre>
<p>Eso es todo, para que funcione ambos servidores deben tener el programa <code>rsync</code> instalado, <code>FUENTE</code> es el directorio local a copiar (o puede ser un archivo), <code>DESTINO</code> es el directorio del servidor remoto a donde se copiará.</p>
<p>La opción <code>-az</code> envia la información compresa y <code>-e ssh</code> indica que hay que usar el programa <code>ssh</code> para transferir los archivos (con esto se puede enviar también mediante <code>ftp</code>, etc)</p>
<p>Otra opción que uso mucho es <code>--delete</code>, de esta manera <code>rsync</code> también borrará los archivos &#8220;extra&#8221; para que la copia sea exacta. Hay que tener cuidado, porque en algo descuidado se pueden borrar los archivos locales (inversión de parámetros)&#8230; algo que me pasó una vez, pero tenía respaldo =).</p>
<p> </p>
<p> </p>
]]></description>
			<content:encoded><![CDATA[<p>Usualmente uso el famosímo <code>scp</code> para transferir archivos, el problema es que al parecer <code>scp</code> es muy lento cuando se trata de muchos archivos pequeños. </p>
<p><code>rsync</code> es un comando para hacer réplicas de un directorio a otro lugar, lo que hace es checar el comparar los directorios y copiar todos los archivos que hayan sido modificados, que sean nuevos o incluso que hayan sido elminados para hacer una copia exacta.</p>
<p>La gran ventaja de <code>rsync</code> es que aparte de crear una réplica, es sorprendentemente rápido, en especial con archivos pequeños.</p>
<p>El uso es muy simple:</p>
<pre>rsync -az -e ssh FUENTE usuario@servidor:DESTINO</pre>
<p>Eso es todo, para que funcione ambos servidores deben tener el programa <code>rsync</code> instalado, <code>FUENTE</code> es el directorio local a copiar (o puede ser un archivo), <code>DESTINO</code> es el directorio del servidor remoto a donde se copiará.</p>
<p>La opción <code>-az</code> envia la información compresa y <code>-e ssh</code> indica que hay que usar el programa <code>ssh</code> para transferir los archivos (con esto se puede enviar también mediante <code>ftp</code>, etc)</p>
<p>Otra opción que uso mucho es <code>--delete</code>, de esta manera <code>rsync</code> también borrará los archivos &#8220;extra&#8221; para que la copia sea exacta. Hay que tener cuidado, porque en algo descuidado se pueden borrar los archivos locales (inversión de parámetros)&#8230; algo que me pasó una vez, pero tenía respaldo =).</p>
<p> </p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/11/26/tip-usando-rsync-para-transferencias-rapidas-entre-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solución a &#8220;Failed to find an unused loop device&#8221;</title>
		<link>http://vida.danguer.com/2008/11/10/solucion-a-failed-to-find-an-unused-loop-device/</link>
		<comments>http://vida.danguer.com/2008/11/10/solucion-a-failed-to-find-an-unused-loop-device/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 16:06:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Loop]]></category>
		<category><![CDATA[Xen]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=82</guid>
		<description><![CDATA[<p>En Xen, si no configuras de antemano linux verás que después de iniciar varios servidores virtuales te marcará un error que dice: &#8220;<code>Failed to find an unused loop device</code>&#8221;</p>
<p>Esto significa que linux ya no tiene &#8220;lugar&#8221; para montar más dispositivos <code>loop </code>(montar tu disco duro virtual o <code>swap</code>), por defecto tienes ochos dispositivos <code>loop</code> permitidos, que son para cuatro máquinas virtuales (debido a que utilizan al menos dos imágnes, una para el <code>swap</code> y otra para el disco duro)</p>
<p>Para aumentar este límite es muy fácil, primero detienes las instancias virtuales de Xen:</p>
<pre name="code" class="php">
/etc/init.d/xendomains stop
</pre>
<p>Agregas al archivo <code>/etc/modprobe.d/local-loop</code> lo siguiente (o crealo si no existe):</p>
<pre name="code" class="php">
options loop max_loop=64
</pre>
<p>Después vuelves a cargar el módulo</p>
<pre name="code" class="php">
rmmod loop
modprobe loop
</pre>
<p>Por último inicias las instancias virtuales</p>
<pre name="code" class="php">
/etc/init.d/xendomains start
</pre>
<p>Con esto puede tener hasta 32 instancias de Xen sin problemas.</p>
]]></description>
			<content:encoded><![CDATA[<p>En Xen, si no configuras de antemano linux verás que después de iniciar varios servidores virtuales te marcará un error que dice: &#8220;<code>Failed to find an unused loop device</code>&#8221;</p>
<p>Esto significa que linux ya no tiene &#8220;lugar&#8221; para montar más dispositivos <code>loop </code>(montar tu disco duro virtual o <code>swap</code>), por defecto tienes ochos dispositivos <code>loop</code> permitidos, que son para cuatro máquinas virtuales (debido a que utilizan al menos dos imágnes, una para el <code>swap</code> y otra para el disco duro)</p>
<p>Para aumentar este límite es muy fácil, primero detienes las instancias virtuales de Xen:</p>
<pre name="code" class="php">
/etc/init.d/xendomains stop
</pre>
<p>Agregas al archivo <code>/etc/modprobe.d/local-loop</code> lo siguiente (o crealo si no existe):</p>
<pre name="code" class="php">
options loop max_loop=64
</pre>
<p>Después vuelves a cargar el módulo</p>
<pre name="code" class="php">
rmmod loop
modprobe loop
</pre>
<p>Por último inicias las instancias virtuales</p>
<pre name="code" class="php">
/etc/init.d/xendomains start
</pre>
<p>Con esto puede tener hasta 32 instancias de Xen sin problemas.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/11/10/solucion-a-failed-to-find-an-unused-loop-device/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruteo en Xen</title>
		<link>http://vida.danguer.com/2008/11/10/ruteo-en-xen/</link>
		<comments>http://vida.danguer.com/2008/11/10/ruteo-en-xen/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 15:56:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Virtualizacion]]></category>
		<category><![CDATA[Xen]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=81</guid>
		<description><![CDATA[<p>Hace poco instalé un servidor Xen, después para terminar de configurarlo solicitamos IP&#8217;s adicionales para que cada servidor virtual tuviera su IP dedicada.</p>
<p>Lamentablemente nos dieron IPs en otra subred, esto puede ocasionar algunos problemas pero aqui está una solución =)</p>
<p>Vamos a suponer que nuestro servidor Xen tiene ip <code>192.168.1.90</code> y que nuestras nuevas ips a asignar son <code>192.168.247.130</code> y <code>192.168.247.131</code>, y que el gateway de nuestra máquina anfitrión es <code>192.168.1.1</code></p>
<p> </p>
<p><strong>Configuración de Xen</strong></p>
<p>Debido a que en mi caso necesitaba rutear los datos entre mi máquina anfitrión (<code>dom0</code>) y mis máquinas virtuales (<code>domU</code>) habilité lo siguiente en xen:</p>
<pre name="code" class="php">(network-script network-route)
(vif-script vif-route)</pre>
<p>Tanto <code>network-script</code>  y <code>vif-script</code> deben ser las únicas configuraciones disponibles (esto es comentar todos los otro <code>network-script</code> y <code>vif-script</code>)</p>
<p> </p>
<p>Reiniciamos el servidor Xen:</p>
<pre name="code" class="php">/etc/init.d/xend restart
/etc/init.d/xendomains restart </pre>
<p>Es muy importante que verifiques si te marca un error, ya que a mi me mandaba un error por un script que no reconocía la interfaz que ibamos a utilizar, así que hice el siguiente cambio en el archivo: <code>/etc/xen/scripts/network-route</code></p>
<pre name="code" class="php">dir=$(dirname "$0")

. "$dir/xen-script-common.sh"

evalVariables "$@"

 

#netdev=${netdev:-eth${vifnum}}

netdev=eth0 #definir por defecto la interfaz a utilizar

echo 1 &#62;/proc/sys/net/ipv4/ip_forward
echo 1 &#62;/proc/sys/net/ipv4/conf/${netdev}/proxy_arp</pre>
<p> </p>
<p>Básicamente lo que hace el script de Xen es habilitar el ruteo en linux y crear unas reglas de <code>iptables</code> (que tu puedes configurar si quieres personalizar el rendimiento o seguridad de tus máquinas virtuales por medio del anfitrión)</p>
<p>Ya por último debes borrar el puente que hace Xen en la configuración por defecto de <code>bridge</code> (usando el comando <code>brctl</code>)</p>
<p> </p>
<p><strong>Configuración de la Imagen</strong></p>
<p>Al crear la imagen. proporciona la IP, el gateway de tu máquina anfitrión (<code>dom0</code>) y la máscara de red correspondiente, en nuestro ejemplo <code>255.255.0.0</code>, ejemplo:</p>
<pre name="code" class="php">xen-create-image --hostname=misitio.com --ip=192.168.247.130 --netmask=255.255.0.0 --gateway=192.168.1.1 --passwd</pre>
<p> </p>
<p>Con esto tus máquinas clientes podrán ser vistas y accesar a internet sin problemas.</p>
&#8230;]]></description>
			<content:encoded><![CDATA[<p>Hace poco instalé un servidor Xen, después para terminar de configurarlo solicitamos IP&#8217;s adicionales para que cada servidor virtual tuviera su IP dedicada.</p>
<p>Lamentablemente nos dieron IPs en otra subred, esto puede ocasionar algunos problemas pero aqui está una solución =)</p>
<p>Vamos a suponer que nuestro servidor Xen tiene ip <code>192.168.1.90</code> y que nuestras nuevas ips a asignar son <code>192.168.247.130</code> y <code>192.168.247.131</code>, y que el gateway de nuestra máquina anfitrión es <code>192.168.1.1</code></p>
<p> </p>
<p><strong>Configuración de Xen</strong></p>
<p>Debido a que en mi caso necesitaba rutear los datos entre mi máquina anfitrión (<code>dom0</code>) y mis máquinas virtuales (<code>domU</code>) habilité lo siguiente en xen:</p>
<pre name="code" class="php">(network-script network-route)
(vif-script vif-route)</pre>
<p>Tanto <code>network-script</code>  y <code>vif-script</code> deben ser las únicas configuraciones disponibles (esto es comentar todos los otro <code>network-script</code> y <code>vif-script</code>)</p>
<p> </p>
<p>Reiniciamos el servidor Xen:</p>
<pre name="code" class="php">/etc/init.d/xend restart
/etc/init.d/xendomains restart </pre>
<p>Es muy importante que verifiques si te marca un error, ya que a mi me mandaba un error por un script que no reconocía la interfaz que ibamos a utilizar, así que hice el siguiente cambio en el archivo: <code>/etc/xen/scripts/network-route</code></p>
<pre name="code" class="php">dir=$(dirname "$0")

. "$dir/xen-script-common.sh"

evalVariables "$@"

 

#netdev=${netdev:-eth${vifnum}}

netdev=eth0 #definir por defecto la interfaz a utilizar

echo 1 &gt;/proc/sys/net/ipv4/ip_forward
echo 1 &gt;/proc/sys/net/ipv4/conf/${netdev}/proxy_arp</pre>
<p> </p>
<p>Básicamente lo que hace el script de Xen es habilitar el ruteo en linux y crear unas reglas de <code>iptables</code> (que tu puedes configurar si quieres personalizar el rendimiento o seguridad de tus máquinas virtuales por medio del anfitrión)</p>
<p>Ya por último debes borrar el puente que hace Xen en la configuración por defecto de <code>bridge</code> (usando el comando <code>brctl</code>)</p>
<p> </p>
<p><strong>Configuración de la Imagen</strong></p>
<p>Al crear la imagen. proporciona la IP, el gateway de tu máquina anfitrión (<code>dom0</code>) y la máscara de red correspondiente, en nuestro ejemplo <code>255.255.0.0</code>, ejemplo:</p>
<pre name="code" class="php">xen-create-image --hostname=misitio.com --ip=192.168.247.130 --netmask=255.255.0.0 --gateway=192.168.1.1 --passwd</pre>
<p> </p>
<p>Con esto tus máquinas clientes podrán ser vistas y accesar a internet sin problemas.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/11/10/ruteo-en-xen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Xen 3.3 y Debian Etch</title>
		<link>http://vida.danguer.com/2008/10/26/xen-33-y-debian-etch/</link>
		<comments>http://vida.danguer.com/2008/10/26/xen-33-y-debian-etch/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 23:34:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Virtualizacion]]></category>
		<category><![CDATA[Xen]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=79</guid>
		<description><![CDATA[<p>Recientemente me tocó configurar un servidor para tener máquinas virtuales mediante <a title="Xen - Virtualizacion" href="http://xen.org" target="_blank">XEN</a>. Anteriormente sólo había trabajado con un poco con <a title="VMWare ESXi - Virtualizacion" href="http://www.vmware.com/products/esxi/" target="_blank">VMWare ESXi</a> y <a title="XenServer - Virtualizacion" href="http://www.xenserver5.com/" target="_blank">XenServer</a> (la versión &#8220;comercial&#8221; de XEN), el problema es que se tenía que instalar en un servidor remoto que solo se tiene acceso mediante ssh.</p>
<p>Con algo de trabajo y pruebas (y con las buenas herramientas de <a title="ServerBeach - Hosting Recomendable" href="http://serverbeach.com/" target="_blank">ServerBeach</a>, que sólo le faltan una vista a la consola para diagnosticar kernel panics) por fin pude instalarlo.</p>
<p>Debian tiene una versión de Xen, pero es la 3.0.3 que para mi gusto es demasiado vieja (se liberó en 2006) y la versión <a title="Debian Lenny" href="http://www.debian.org/devel/debian-installer/" target="_blank">Lenny</a> (testing) tiene la versión 3.2, pero también algo &#8220;inestable&#8221; a mi gusto para un servidor de batalla.</p>
<p>Como dije después de hacer varias pruebas logré instalar la versión Xen 3.3 utilizando el kernel que viene en Debian preparado para Xen.</p>
<p>Una breve descripción de Xen, es que está separado en varias partes, en primer lugar Xen tiene un kernel modificado para llevar a cabo la virtualización, la ventaja es que la versión 3.3 utiliza la versión 2.6.18 que es la que viene con Debian.</p>
<p>Después la parte &#8220;fuerte&#8221; de Xen es el denominado hypervisor que es un servidor que se encarga de hacer la virtualización propiamente dicha. Después vienen las máquinas virtuales que utilizan por lo general otro kernel que se denomina domU (y el kernel de la máquina base se denomina dom0).</p>
<p>Pues bien, para lograr esto simplemente primero instalé la imagen del kernel apropiado y compilar solamente el hypervisor de Xen 3.3</p>
<p>En pasos simples:</p>
<pre name="code" class="php">
#Instalar la imagen del kernel con parche para xen
apt-get install linux-image-2.6.18-6-xen-amd64

#Descargar el código fuente de xen
wget http://bits.xensource.com/oss-xen/release/3.3.0/xen-3.3.0.tar.gz
tar zxvf xen-3.3.0.tar.gz
cd xen-3.3.0

#Compilar solamente el hypervisor
make xen
﻿make install-xen

#Compilar los archivos ejecutables como xm y herramientas de red
make tools
make install-tools

#Hacer que Debian cree&#8230;</pre>]]></description>
			<content:encoded><![CDATA[<p>Recientemente me tocó configurar un servidor para tener máquinas virtuales mediante <a title="Xen - Virtualizacion" href="http://xen.org" target="_blank">XEN</a>. Anteriormente sólo había trabajado con un poco con <a title="VMWare ESXi - Virtualizacion" href="http://www.vmware.com/products/esxi/" target="_blank">VMWare ESXi</a> y <a title="XenServer - Virtualizacion" href="http://www.xenserver5.com/" target="_blank">XenServer</a> (la versión &#8220;comercial&#8221; de XEN), el problema es que se tenía que instalar en un servidor remoto que solo se tiene acceso mediante ssh.</p>
<p>Con algo de trabajo y pruebas (y con las buenas herramientas de <a title="ServerBeach - Hosting Recomendable" href="http://serverbeach.com/" target="_blank">ServerBeach</a>, que sólo le faltan una vista a la consola para diagnosticar kernel panics) por fin pude instalarlo.</p>
<p>Debian tiene una versión de Xen, pero es la 3.0.3 que para mi gusto es demasiado vieja (se liberó en 2006) y la versión <a title="Debian Lenny" href="http://www.debian.org/devel/debian-installer/" target="_blank">Lenny</a> (testing) tiene la versión 3.2, pero también algo &#8220;inestable&#8221; a mi gusto para un servidor de batalla.</p>
<p>Como dije después de hacer varias pruebas logré instalar la versión Xen 3.3 utilizando el kernel que viene en Debian preparado para Xen.</p>
<p>Una breve descripción de Xen, es que está separado en varias partes, en primer lugar Xen tiene un kernel modificado para llevar a cabo la virtualización, la ventaja es que la versión 3.3 utiliza la versión 2.6.18 que es la que viene con Debian.</p>
<p>Después la parte &#8220;fuerte&#8221; de Xen es el denominado hypervisor que es un servidor que se encarga de hacer la virtualización propiamente dicha. Después vienen las máquinas virtuales que utilizan por lo general otro kernel que se denomina domU (y el kernel de la máquina base se denomina dom0).</p>
<p>Pues bien, para lograr esto simplemente primero instalé la imagen del kernel apropiado y compilar solamente el hypervisor de Xen 3.3</p>
<p>En pasos simples:</p>
<pre name="code" class="php">
#Instalar la imagen del kernel con parche para xen
apt-get install linux-image-2.6.18-6-xen-amd64

#Descargar el código fuente de xen
wget http://bits.xensource.com/oss-xen/release/3.3.0/xen-3.3.0.tar.gz
tar zxvf xen-3.3.0.tar.gz
cd xen-3.3.0

#Compilar solamente el hypervisor
make xen
﻿make install-xen

#Compilar los archivos ejecutables como xm y herramientas de red
make tools
make install-tools

#Hacer que Debian cree las entradas correspondientes en los rc.X
#para que cuando el servidor se inicie ejecute los servidores de Xen
update-rc.d xend defaults 20 21
update-rc.d xendomains defaults 21 20

#Hacer que grub reconozca el nuevo kernel con la configuración de Xen 3.3.0
update-grub
</pre>
<p>Con eso deberían de ver una entrada en el grub como:</p>
<pre name="code" class="php">
title           Xen 3.3.0 / Debian GNU/Linux, kernel 2.6.18-6-xen-amd64
root            (hd0,0)
kernel          /xen-3.3.0.gz
module          /vmlinuz-2.6.18-6-xen-amd64 root=/dev/sda6 ro console=tty0
module          /initrd.img-2.6.18-6-xen-amd64
savedefault
</pre>
<p>Que debería de bootear con el hypervisor 3.3</p>
<p>Incluyo algunas ligas de sitios (en inglés) que me ayudaron muchísimo para entender algo más de Xen <img src='http://vida.danguer.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<ul>
<li><a href="http://www.howtoforge.com/debian_etch_xen_3.1_p5">http://www.howtoforge.com/debian_etch_xen_3.1_p5</a> (muy buen documento)</li>
<li><a href="http://27smiles.com/2008/08/08/setting-up-xen-on-debian-etch-64bit/">http://27smiles.com/2008/08/08/setting-up-xen-on-debian-etch-64bit/</a> (para instalar Xen con las versiones estables de Debian)</li>
<li><a href="http://www.nabble.com/Xen-3.3-install-from-source-on-centos-5.2-td19761354.html">http://www.nabble.com/Xen-3.3-install-from-source-on-centos-5.2-td19761354.html</a> (Otra versión de como compilar Xen, incluye copiar la configuración actual, en el ejemplo de CentOS pero puede ser de Debian, algo que no solucionó mi problema, pero es buena idea)</li>
<li><a href="http://xen-tools.org/software/xen-tools/releases.html">http://xen-tools.org/software/xen-tools/releases.html</a> (Herramientas de ayuda para Xen, descárguenla, ya que la versión estable de Debian es vieja y no necesita muchas cosas, si les pide algo chequen la primera liga)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/10/26/xen-33-y-debian-etch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Certificación en Zend Framework</title>
		<link>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/</link>
		<comments>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 15:24:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=76</guid>
		<description><![CDATA[<p>Hace poco Zend publicó la certificación de Zend Framework:<br />
<a href="http://www.zend.com/en/services/certification/framework/">http://www.zend.com/en/services/certification/framework/</a></p>
<p>Estoy algo divergente entre si es una buena opción o no</p>
<p>Buena opción:</p>
<ul>
<li>El Framework está muy bien hecho como para que valga una certificación</li>
<li>Tiene tantos componentes que es una buena medida para destacar entre los que han utilizado solamente brevemente el Framework</li>
</ul>
<p> </p>
<p>Mala opción</p>
<ul>
<li>Cuesta más que la certificación en PHP ($160 dolares en contra de $125 para la certificación de PHP)</li>
<li>Lamentablemente la certificación es en la versión 1.5 y la versión estable es la versión 1.6, si bien la versión 1.5 ya tenía muy estandarizado el modelo del Framework, a menos que tengan un periodo largo de liberar versiones (lo cual puede ser malo ya que ahora hay mucho movimiento) en menos de un año seguramente saldran al menos un par de versiones por lo que ¿se va a certificar en cada version? =P</li>
</ul>
<div>Tampoco hay guia oficial, solamente está la opción de curso.</div>
<div></div>
<div>Creo que el Zend Framework debe crecer un poco más para estabilizarse en cuestión de características generales y de ahi ya es una opción muy válida de certificación; ya que en el momento hay mucho movimiento en cuestión de nuevas características, por ejemplo la versión 1.6 la principal mejora fue la introducción de Dojo.</div>
<p> </p>
]]></description>
			<content:encoded><![CDATA[<p>Hace poco Zend publicó la certificación de Zend Framework:<br />
<a href="http://www.zend.com/en/services/certification/framework/">http://www.zend.com/en/services/certification/framework/</a></p>
<p>Estoy algo divergente entre si es una buena opción o no</p>
<p>Buena opción:</p>
<ul>
<li>El Framework está muy bien hecho como para que valga una certificación</li>
<li>Tiene tantos componentes que es una buena medida para destacar entre los que han utilizado solamente brevemente el Framework</li>
</ul>
<p> </p>
<p>Mala opción</p>
<ul>
<li>Cuesta más que la certificación en PHP ($160 dolares en contra de $125 para la certificación de PHP)</li>
<li>Lamentablemente la certificación es en la versión 1.5 y la versión estable es la versión 1.6, si bien la versión 1.5 ya tenía muy estandarizado el modelo del Framework, a menos que tengan un periodo largo de liberar versiones (lo cual puede ser malo ya que ahora hay mucho movimiento) en menos de un año seguramente saldran al menos un par de versiones por lo que ¿se va a certificar en cada version? =P</li>
</ul>
<div>Tampoco hay guia oficial, solamente está la opción de curso.</div>
<div></div>
<div>Creo que el Zend Framework debe crecer un poco más para estabilizarse en cuestión de características generales y de ahi ya es una opción muy válida de certificación; ya que en el momento hay mucho movimiento en cuestión de nuevas características, por ejemplo la versión 1.6 la principal mejora fue la introducción de Dojo.</div>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como programar (decente) en PHP</title>
		<link>http://vida.danguer.com/2008/10/05/como-programar-decente-en-php/</link>
		<comments>http://vida.danguer.com/2008/10/05/como-programar-decente-en-php/#comments</comments>
		<pubDate>Sun, 05 Oct 2008 07:23:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=74</guid>
		<description><![CDATA[<p>El viernes un cliente me pidió un favor de ayudarle a terminar de instalar un script de un amigo en su servidor. </p>
<p>Todo parecía ser un simple problema con la importación de MySQL por los acentos, aunque eso solucionó parcialmente aún tenía un error en la parte medular del sistema, en cuanto abri el archivo que estaba dando el error me arrepentí de hacerlo y mi mente se volcó a recordar hace cinco años o tal vez seis cuando se programaba de esa manera =)</p>
<p>Con ese ejemplo me vino a la mente una frase célebre de mi buen amigo <a href="http://www.developarts.com" target="_blank">Nexus</a> en esas épocas cuando estaba aprendiendo a programar en PHP, mi geek interno terco siguió programando con las antiquísimas <code>$HTTP_POST_VARS</code> a pesar de que se habían desalentado utilizar esas variables y se reemplazó por las variables tipo: <code>$_POST</code> ó <code>$_GET</code></p>
<p>Recuerdo que cuando Nexus vio un código mio que tenía el <code>$HTTP_POST_VARS</code> me dijo en un chat con (me parece Carlos Cortez): &#8220;Programas a la manera viejita jajajaja&#8221;. Claro por orgullo después de eso nunca volví a tocar <code>$HTTP_POST_VARS</code></p>
<p>Aqui tengo unos consejos para que no solamente sea fácil programar, depurar y para otros leer tu código. También para evitar que PHP siga siendo visto como un lenguaje de &#8220;bajo presupuesto&#8221; (por aquello que muchos prefieren Java por lo &#8216;empresarial&#8217;)</p>
<p> </p>
<p><strong>Tip: PHP dejó de ser un lenguaje de Script hace años</strong></p>
<p>Lo digo en completo tono sarcástico, si bien PHP no se puede compilar no hay razón para meter todo dentro de un solo archivo como print&#8217;s con funciones, prácticamente se debe separar de preferencia en un modelo <strong>MVC</strong> si no puedes hacerlo, entonces al menos hazlo en <strong>VE</strong> (Vista-Espaguetti donde vas a meter tanto modelo como controlador)</p>
<p> </p>
<p><strong>Tip: <code>register_globals</code> está muerto</strong></p>
<p>Por eso me dio miedo abrir el archivo, necesitaba <code>register_globals</code>. Para el que no sepa que es <code>register_globals</code> es simplemente que cuando mandamos parámetros&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>El viernes un cliente me pidió un favor de ayudarle a terminar de instalar un script de un amigo en su servidor. </p>
<p>Todo parecía ser un simple problema con la importación de MySQL por los acentos, aunque eso solucionó parcialmente aún tenía un error en la parte medular del sistema, en cuanto abri el archivo que estaba dando el error me arrepentí de hacerlo y mi mente se volcó a recordar hace cinco años o tal vez seis cuando se programaba de esa manera =)</p>
<p>Con ese ejemplo me vino a la mente una frase célebre de mi buen amigo <a href="http://www.developarts.com" target="_blank">Nexus</a> en esas épocas cuando estaba aprendiendo a programar en PHP, mi geek interno terco siguió programando con las antiquísimas <code>$HTTP_POST_VARS</code> a pesar de que se habían desalentado utilizar esas variables y se reemplazó por las variables tipo: <code>$_POST</code> ó <code>$_GET</code></p>
<p>Recuerdo que cuando Nexus vio un código mio que tenía el <code>$HTTP_POST_VARS</code> me dijo en un chat con (me parece Carlos Cortez): &#8220;Programas a la manera viejita jajajaja&#8221;. Claro por orgullo después de eso nunca volví a tocar <code>$HTTP_POST_VARS</code></p>
<p>Aqui tengo unos consejos para que no solamente sea fácil programar, depurar y para otros leer tu código. También para evitar que PHP siga siendo visto como un lenguaje de &#8220;bajo presupuesto&#8221; (por aquello que muchos prefieren Java por lo &#8216;empresarial&#8217;)</p>
<p> </p>
<p><strong>Tip: PHP dejó de ser un lenguaje de Script hace años</strong></p>
<p>Lo digo en completo tono sarcástico, si bien PHP no se puede compilar no hay razón para meter todo dentro de un solo archivo como print&#8217;s con funciones, prácticamente se debe separar de preferencia en un modelo <strong>MVC</strong> si no puedes hacerlo, entonces al menos hazlo en <strong>VE</strong> (Vista-Espaguetti donde vas a meter tanto modelo como controlador)</p>
<p> </p>
<p><strong>Tip: <code>register_globals</code> está muerto</strong></p>
<p>Por eso me dio miedo abrir el archivo, necesitaba <code>register_globals</code>. Para el que no sepa que es <code>register_globals</code> es simplemente que cuando mandamos parámetros a un script como por ejemplo: <code>prueba.php?variable1=hola&amp;variable2=mundo</code> PHP convierte automáticamente esas dos variables en <code>$variable1</code> y <code>$variable2</code> con su respectivo contenido.</p>
<p>Qué fácil, ¿No?. Pues en realidad no, cuando el mundo no se percataba del error fatal de hacer esto, parecía que PHP era tan fácil de programar, vaya no necesitabas ni siquiera  vincular los parámetros.</p>
<p>Poco después un balde de agua fria cayó sobre todos nosotros&#8230; el problema es que cualquier tipo con algo de sesos puede simplemente pasar variables y asignar valores de la aplicación. En el caso de una aplicación que no inicializara las variables (el 99% para ser sinceros) podía sufrir porque era fácilmente &#8220;hackeada&#8221; sin necesidad de hacer mucho.</p>
<p>Por eso rápidamente se eliminó <code>register_globals</code> y se dejó como un parámetro opcional, pero muy opcional. Tanto que en PHP 6 va a desaparecer definitivamente. </p>
<p><code>register_globals</code> no ayuda, no hace más rápido el desarrollo; simplemente destruye todo lo bueno que podría tener una aplicación, porque en primer lugar es difícil saber cuales variables son parámetros del usuario y cuales son variables internas. También hace fácil explotar un sistema (creo que ya lo había dicho <img src='http://vida.danguer.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>
<p>La solución para esto&#8230; reescribe tu aplicación.</p>
<p> </p>
<p><strong>Tip: <code>die()</code> está muerto</strong></p>
<p>¿Alguien se ha preguntado porqué existe esta construcción del lenguaje de PHP?, supongo que es un legado de los viejos días cuando PHP era un lenguaje de script.</p>
<p><code>die()</code> permite simplemente eso: hace que el script muera. Muchos lo hacían para verificar una situación intolerable como al abrir una conexión a una base de datos y que no se pudiera conectar; como no se pueden mostrar datos entonces simplemente le decimos al usuario: &#8220;perdon pero aqui nos detenemos&#8221; un ejemplo es el siguiente:</p>
<pre name="code" class="php">&lt;?php
    mysql_connect($host, $usuario, $password) or die('No pude conectarme a la base de datos');
?&gt;</pre>
<p>¿Cuál es el problema?, muy simple la función die funciona tan perfectamente que el script se muere ahi. Por lo que el usuario simplemente verá una pantalla blanca con un texto críptico. En el peor de los casos mostrará una parte de la página y la &#8220;cortará&#8221; donde se haya ejecutado esta instrucción.</p>
<p>No seas perezoso, utiliza construcciones de <code>if()</code> para separar bloques de instrucciones en vez de suicidarte.<br />
Si aún así quieres hacer un <code>die()</code> o un <code>exit()</code> al menos manda a llamar a una plantilla especial que muestre el error con la mayor parte del mismo estilo de la página que vas a mostrar, te lo agradecerá el usuario.</p>
<p> </p>
<p> </p>
<p><strong>Tip: <code>include</code> y <code>require</code> es un arma de dos filos</strong></p>
<p>También un legado de aquellos días es que un script luzca como:</p>
<pre name="code" class="php">&lt;?php include 'cabecera.php'; ?&gt;
&lt;?php print "Hola mundo 'plantilla'; ?&gt;
&lt;?php include 'pie_pagina.php'; ?&gt;</pre>
<p>En aquellos días estas eran nuestras plantillas, <code>cabecera.php</code> mostraba el código inicial de HTML y <code>pie_pagina.php</code> cerraba ese código HTML, qué facil, ¿verdad?</p>
<p>Pues no, el problema de este método es que en primer lugar las variables son globales y compartidas, por lo que si haces el código espaguetti anterior es un total NO.</p>
<p>Por ejemplo es fácil sobreescribir variables dentro de un archivo &#8220;plantilla&#8221; y el error se propaga a las otras &#8220;plantillas&#8221;.</p>
<p>Otro problema es que hacen difícil seguir un flujo real de plantillas (si no quieres una parte tienes que reescribir todo en lugar de simplemente cambiar por ejemplo la distribución de los objetos en una plantilla general. También es fácil de romper todo el HTML por una etiqueta fuera de lugar</p>
<p>Una vez más, no seas perezoso y utiliza un manejador de plantillas como <a href="http://www.smarty.net/">Smarty</a></p>
<p>Ahora bien del lado de programación un <code>include()</code> por lo regular es utilizado para incluir pedazos de código tales como funciones, clases, etc. Pero lamentablemente también es utilizado para incluir pedazos de código que tienen el mismo uso que funciones!!</p>
<p>Eso es algo totalmente prohibido, no se porque no utilizas funciones o mejor aún una clase.</p>
<p> </p>
<p><strong>Tip: <code>mysql_connect</code> y sus vicios</strong></p>
<p>Un legado también de aquellos días es que se programaba de la siguiente manera:</p>
<pre name="code" class="php">&lt;?php
include 'configuracion_db.php';
mysql_connect($host, $usuario, $password) or die('No pude conectarme a la base de datos');
?&gt;</pre>
<p>donde <code>configuracion_db.php</code> era simplemente:</p>
<pre name="code" class="php">&lt;?php 
$host = 'localhost';
$usuario = 'mi_usuario';
$password = 'mi_password';
?&gt; </pre>
<p>El primero se incluia prácticamente como cabecera para todas las páginas porque necesitaban acceso a la base de datos, y también se incluia dentro de otros bloques dentro de la misma página.</p>
<p>O peor aún, incluir en cada archivo los parámetros de configuración. Esto último es simplemente un caos y es no saber programar, así que toma un curso de programacion básica en otro lenguaje antes de programar en PHP <img src='http://vida.danguer.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Para el primer caso si bien es válido, es simplemente malo debido a que otro script puede fácilmente sobreescribir esas variables (o el mismo script por error). Aunque es utilizado, es muchísimo mejor utilizar un patron de diseño llamado: <strong>Singleton</strong></p>
<p>El <strong>Singleton</strong> es un patron de diseño muy simple, en términos de orientación a objetos es un método estático de una clase que regresa siempre la misma instancia de la clase. Es decir solamente existirá un objeto en todo el sistema y que lo creará ese método estático normalmente llamado: <code>obtenerInstancia()</code></p>
<p>En lenguaje de funciones es simplemente una función que regresará la misma variable (tendrá la misma dirección de memoria) cada vez que se llame, así que en lugar de hacer el primer ejemplo utiliza este:</p>
<pre name="code" class="php">&lt;?php
function obtenerConectorMysql() {
     static $conector_mysql = null; 
     if ($conector_mysql == null) {
         //aqui insertar las instrucciones para obtener el host, usuario y password, 
         // por ejemplo de un archivo o simplemente escribirlas aqui
         $conector _mysql = mysql_connect($host, $usuario, $password);
     } 

     return $conector_mysql;
}</pre>
<p> </p>
<p>Esto simplemente crea la primera vez que se llame el conector_mysql, después simplemente lo regresa por lo que no se crean diferentes instancias, es la misma conexión a MySQL</p>
<p>Si lo quieres hacer mediante clases, puedes utilizarlo algo similar como una llamada a una función estática o &#8220;envolverlo&#8221; en la clase que tengas para manejar la base de datos.</p>
<p><strong>Tip: La seguridad no es para sitios de comercio o bancos solamente</strong></p>
<p>Mucha gente piensa que debe hacer &#8220;seguro&#8221; un sitio solamente si va a tener operaciones monetarias. Nada más fuera de la realidad. </p>
<p>Todos los sitios necesitan seguridad para evitar que los ataques logren su resultado: hacer &#8220;explotar&#8221; la aplicación.</p>
<p>Evitando los errores más comunes tendrás una aplicación que si bien no es tan segura como la de la CIA (lease con sarcasmo) evitará el 90% de los ataques comunes.</p>
<ol>
<li>Al desarrollar una aplicación, recuerda que el usuario no es de fiar, por lo que todo lo que provenga del usuario puede ser alterado</li>
<li>Siempre verifica la información que el usuario envió mediante parámetros. Si es posible restringe mediante un arreglo de valores válidos, si no es posible entonces haz muchas verificaciones, por ejemplo en el caso de un archivo, elimina caracteres peligrosos como: &#8216;..&#8217; o &#8216;/&#8217; que pueden hacer que el sistema lea (o incluso escriba) un archivo muy diferente al planeado.<br />
Esto se hace indispensable si vas a utilizar una función poderosa como <code>include()</code> o acceso al archivo (como <code>fopen()</code> )</li>
<li>Nunca pongas datos importantes en una <code>cookie</code>, utiliza sesiones. Si lees datos de una <code>cookie</code> nunca asumas que por ser <code>cookie</code> es dificil de alterar<br />
Si los datos van a &#8220;perdurar&#8221; más alla de una sesión, entonces deja en la cookie un identificador único y guárdalo en la base de datos, de esta manera el usuario solo debe proveer su identificador y no otra información que pudiera ser alterada. </li>
<li>Siempre &#8220;escapa&#8221; las variables que vas a utilizar en una consulta a la base de datos, utiliza funciones como: <code>mysql_escape_string()</code>, si utilizas un framework la mayoría de ellos tienen una función para hacer esto (que terminan llamando a algo similar a la primera función)</li>
</ol>
<p> </p>
<p><strong>Tip: PHP5 no es una opción, es obligatorio &gt;=)</strong></p>
<p>No veas a PHP5 como una &#8220;extensión&#8221; o una versión más. El propósito de PHP5 es hacer una transición entre el mundo de scripts de código espaguetti a un sistema de clases muy bien separadas.</p>
<p>Aunque PHP5 aún permite programar sin clases y con solo funciones; si tienes la oportunidad no dudes en utilizar PHP5 con clases con todo lo nuevo que trae. La guia de estudio de Certificación Zend es un buen inicio. </p>
<p>PHP5 tiene un gran potencial y está esperando para ser plenamente utilizado, algunos frameworks ya están utilizando plenamente su potencial, entre ellos <a href="http://framework.zend.com" target="_blank">Zend Framework</a> que es altamente recomendable.</p>
<p> </p>
<p><strong>Último tip: MVC es lo único para web <img src='http://vida.danguer.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </strong></p>
<p>Si vas a desarrollar una aplicación en PHP que contenga todo lo que una aplicación web contiene (contenido en HTML, bases de datos, procesamiento, etc) simplemente utiliza un framework que tenga un diseño de MVC; los más conocidos son <a href="http://framework.zend.com" target="_blank">Zend Framework</a> (mi recomendación nuevamente) y <a href="http://cakephp.org/" target="_blank">CakePHP</a>, también están otros en rápido ascenso como <a href="http://www.symfony-project.org" target="_blank">Simfony</a> y <a href="http://codeigniter.com/" target="_blank">Code Igniter</a></p>
<p>También son de uso popular los CMS como <a href="http://drupal.org" target="_blank">drupal</a> y <a href="http://www.joomlaspanish.org" target="_blank">joomla</a>/<a href="http://www.mambohispano.org" target="_blank">mambo</a>, aunque ellos no proveen directamente el modelo MVC si proveen el modelo Vista-Espaguetti por lo que con un poco de trabajo extra puedes lograr algo similar a MVC</p>
<p> </p>
<p>En resumen PHP es un lenguaje muy poderoso y con historia; por lo que es fácilmente quedarse con las primeras formas de programar, pero con todos los nuevos desarrollos ahora si se puede empezar a hablar de un PHP a nivel empresarial (ya formalmente <img src='http://vida.danguer.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/10/05/como-programar-decente-en-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
