<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2spanishfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>MilMazz</title>
	
	<link>http://blog.milmazz.com.ve</link>
	<description>MilMazz, es el weblog personal de Milton Mazzarri, Ingeniero de Sistemas y entusiasta por la filosofía detrás del Software Libre. Intento discutir temas afines a la Tecnología, Internet, Software Libre y algunos otros tópicos que llaman mi atención.</description>
	<lastBuildDate>Sat, 31 Dec 2011 07:23:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/milmazz/blog" /><feedburner:info uri="milmazz/blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>milmazz/blog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/content?lg=es&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://eur.i1.yimg.com/eur.yimg.com/i/es/my/addto1.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.feedness.com/alta/http://feeds.feedburner.com/milmazz/blog" src="http://www.feedness.com/ayuda/wp-content/square_b_sh_feed.gif">Subscribe with Feedness</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/milmazz/blog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fmilmazz%2Fblog" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><feedburner:browserFriendly>Muchas gracias por interesarte en leer mi blog. Intentaré compartir contigo noticias sobre Tecnología, Internet, Programación, Software Libre y GNU/Linux.</feedburner:browserFriendly><item>
		<title>Fortaleciendo nuestras contraseñas</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/n-yUIUTDvZ4/fortaleciendo-nuestras-contrasenas</link>
		<comments>http://blog.milmazz.com.ve/archivos/2011/12/31/fortaleciendo-nuestras-contrasenas#comments</comments>
		<pubDate>Sat, 31 Dec 2011 07:23:55 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[Seguridad]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[cracklib]]></category>
		<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[pam]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=220</guid>
		<description><![CDATA[Si una de las promesas que tiene para este cierre de año es fortalecer las contraseñas en sus equipos personales, cambiarlas mensualmente y no repetir la misma contraseña en al menos doce cambios. En este artículo se le explicará como &#8230; <a href="http://blog.milmazz.com.ve/archivos/2011/12/31/fortaleciendo-nuestras-contrasenas">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Si una de las promesas que tiene para este cierre de año es fortalecer las contraseñas en sus equipos personales, cambiarlas mensualmente y no repetir la misma contraseña en al menos doce cambios. En este artículo se le explicará como hacerlo sin tener que invertir una uva en ello, todo esto gracias al paquete <code>libpam-cracklib</code> en Debian, el procedimiento mostrado debe aplicarse a otras distribuciones derivadas de Debian.</p>
<p>Pareciese lógico que algunas de las mejores prácticas para el fortalecimiento de las contraseñas son las siguientes:</p>
<ul>
<li>Cambiar las contraseñas periódicamente.</li>
<li>Establecer una longitud mínima en las contraseñas.</li>
<li>Establecer <strong>buenas</strong> reglas para las nuevas contraseñas, es decir, mezcla entre letras mayúsculas, minúsculas, dígitos y caracteres alfanuméricos.</li>
<li>Mantener un histórico de las contraseñas usadas previamente, de ese modo, alentamos a los usuarios establecer nuevas contraseñas.</li>
<li>Indicarle a los usuarios que es <strong>inaudito</strong> que se anoten las contraseñas en un <em>post-it</em> y se dejen pegadas en los monitores o incluso en las gavetas de sus archivadores.</li>
</ul>
<p>El primer paso es instalar el paquete <code>libpam-cracklib</code></p>
<pre><code># apt-get install libpam-cracklib</code></pre>
<p>A partir de la versión 1.0.1-6 de PAM se recomienda manejar la configuración vía <code>pam-auth-update</code>. Por lo tanto, por favor tome un momento y lea la sección 8 del manual del comando <code>pam-auth-update</code> para aclarar su uso y ventajas.</p>
<pre><code>$ man 8 pam-auth-update</code></pre>
<p>Ahora establezca una configuración similar a la siguiente, vamos primero con la exigencia en la fortaleza de las contraseñas, para ello edite o cree el fichero <code>/usr/share/pam-configs/cracklib</code>.</p>
<pre><code>
Name: Cracklib password strength checking
Default: yes
Priority: 1024
Conflicts: unix-zany
Password-Type: Primary
Password:
	requisite			pam_cracklib.so retry=3 minlen=8 difok=3
Password-Initial:
	requisite			pam_cracklib.so retry=3 minlen=8 difok=3
</code></pre>
<p><strong>NOTA:</strong> Le recomiendo leer la sección 8 del manual de <code>pam_cracklib</code> para encontrar un mayor numero de opciones de configuración. Esto es solo un ejemplo.</p>
<p>En versiones previas el modulo <code>pam_cracklib</code> hacia uso del fichero <code>/etc/security/opasswd</code> para conocer si la propuesta de cambio de contraseña no había sido utilizada previamente. Dicha funcionalidad ahora corresponde al nuevo modulo <code>pam_pwhistory</code></p>
<p>Definamos el funcionamiento de <code>pam_pwhistory</code> a través del fichero <code>/usr/share/pam-configs/history</code>.</p>
<pre><code>
Name: PAM module to remember last passwords
Default: yes
Priority: 1023
Password-Type: Primary
Password:
	requisite			pam_pwhistory.so use_authtok enforce_for_root remember=12 retry=3
Password-Initial:
	requisite			pam_pwhistory.so use_authtok enforce_for_root remember=12 retry=3
</code></pre>
<p><strong>NOTA:</strong> Para mayor detalle de las opciones puede revisar la sección 8 del manual de <code>pam_pwhistory</code></p>
<p>Seguidamente proceda a actualizar la configuración de PAM vía <code>pam-auth-update</code>.</p>
<p><a href="http://blog.milmazz.com.ve/wp-content/uploads/2011/12/pantallazo.png"><img class="aligncenter size-medium wp-image-430" src="http://blog.milmazz.com.ve/wp-content/uploads/2011/12/pantallazo-300x132.png" alt="" width="300" height="132" /></a></p>
<p>Una vez cubierta la fortaleza de las contraseñas nuevas y de evitar la reutilización de las ultimas 12, de acuerdo al ejemplo mostrado, resta cubrir la definición de los periodos de cambio de las contraseñas.</p>
<p>Para futuros usuarios debemos ajustar ciertos valores en el fichero <code>/etc/login.defs</code></p>
<pre><code>
#
# Password aging controls:
#
#       PASS_MAX_DAYS   Maximum number of days a password may be used.
#       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
#       PASS_WARN_AGE   Number of days warning given before a password expires.
#
PASS_MAX_DAYS   30
PASS_MIN_DAYS   0
PASS_WARN_AGE   5
</code></pre>
<p>Las reglas previas no aplicaran para los usuarios existentes, pero para este tipo de usuarios podremos hacer uso del comando <code>chage</code> de la siguiente manera:</p>
<pre><code># chage -m 0 -M 30 -W 5 ${user}</code></pre>
<p>Donde el valor de <code>${user}</code> debe ser reemplazo por el <em>username</em>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=n-yUIUTDvZ4:DjlkTcNuRRM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=n-yUIUTDvZ4:DjlkTcNuRRM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=n-yUIUTDvZ4:DjlkTcNuRRM:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=n-yUIUTDvZ4:DjlkTcNuRRM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=n-yUIUTDvZ4:DjlkTcNuRRM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=n-yUIUTDvZ4:DjlkTcNuRRM:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2011/12/31/fortaleciendo-nuestras-contrasenas/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2011/12/31/fortaleciendo-nuestras-contrasenas</feedburner:origLink></item>
		<item>
		<title>apt-get detrás de proxy con autenticación NTLM</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/DBbvBOtgxIQ/apt-get-detras-de-proxy-con-autenticacion-ntlm</link>
		<comments>http://blog.milmazz.com.ve/archivos/2011/12/29/apt-get-detras-de-proxy-con-autenticacion-ntlm#comments</comments>
		<pubDate>Thu, 29 Dec 2011 21:46:59 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[apt-get]]></category>
		<category><![CDATA[cntlm]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[proxy]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=425</guid>
		<description><![CDATA[Por motivos que no vienen al caso discutir en este artículo tuve que instalar Debian GNU/Linux detrás de un proxy que aún utiliza NTLM como medio de autenticación, aunque NTLM ya no es recomendado por Microsoft desde hace años en &#8230; <a href="http://blog.milmazz.com.ve/archivos/2011/12/29/apt-get-detras-de-proxy-con-autenticacion-ntlm">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Por motivos que no vienen al caso discutir en este artículo tuve que instalar Debian GNU/Linux detrás de un <em>proxy</em> que aún utiliza <acronym title="NT LAN Manager">NTLM</acronym> como medio de autenticación, aunque <a href="http://msdn.microsoft.com/en-us/library/cc236715(v=PROT.10).aspx">NTLM ya no es recomendado por Microsoft</a> desde hace años en pro de usar <a href="http://web.mit.edu/kerberos/">Kerberos</a>.</p>
<p>Una vez instalada la distribución quería utilizar <code>apt-get</code> para actualizarla e instalar nuevos paquetes, el resultado fue que <code>apt-get</code> no funciona de manera transparente detrás de un <em>proxy</em> con autenticación <acronym title="NT LAN Manager">NTLM</acronym>. La solución fue colocar un <em>proxy interno</em> que esté atento a peticiones en un puerto particular en el <em>host</em>, el <em>proxy interno</em> se encargará de proveer de manera correcta las credenciales al <em>proxy externo</em>.</p>
<p>La solución descrita previamente resulta sencilla al utilizar <code>cntlm</code>. En principio será necesario instalarlo vía <code>dpkg</code>, posteriormente deberá editar los campos apropiados en el fichero <code>/etc/cntlm.conf</code></p>
<ul>
<li>Username</li>
<li>Domain</li>
<li>Password</li>
<li>Proxy</li>
</ul>
<p>Seguidamente reinicie el servicio:</p>
<pre><code># /etc/init.d/cntlm restart</code></pre>
<p>Ahora solo resta configurar <code>apt-get</code> para que utilice nuestro <em>proxy interno</em>, para ello edite el fichero <em>/etc/apt.conf.d/02proxy</em></p>
<pre><code>Acquire::http::Proxy "http://127.0.0.1:3128";</code></pre>
<p><strong>NOTA:</strong> Se asume que el puerto de escucha de <code>cntlm</code> es el <em>3128</em>.</p>
<p>Ahora puede hacer uso correcto de <code>apt-get</code>:</p>
<pre><code># apt-get update
# apt-get upgrade
...</code></pre>
<p><strong>NOTA FINAL:</strong> Es evidente que cualquier comando o herramienta que necesite autenticarse contra el <em>proxy externo</em> deberá configurarlo para que utilice el <em>proxy interno</em>, lo explicado en este artículo no solo aplica para el comando <code>apt-get</code>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=DBbvBOtgxIQ:3II_vgF4YUw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=DBbvBOtgxIQ:3II_vgF4YUw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=DBbvBOtgxIQ:3II_vgF4YUw:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=DBbvBOtgxIQ:3II_vgF4YUw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=DBbvBOtgxIQ:3II_vgF4YUw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=DBbvBOtgxIQ:3II_vgF4YUw:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2011/12/29/apt-get-detras-de-proxy-con-autenticacion-ntlm/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2011/12/29/apt-get-detras-de-proxy-con-autenticacion-ntlm</feedburner:origLink></item>
		<item>
		<title>Enviando correos con Perl</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/iv2yE3keC7w/enviando-correos-con-perl</link>
		<comments>http://blog.milmazz.com.ve/archivos/2011/09/21/enviando-correos-con-perl#comments</comments>
		<pubDate>Wed, 21 Sep 2011 21:58:02 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[gulmer]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=408</guid>
		<description><![CDATA[Regularmente los administradores de sistemas requieren notificar, vía correo electrónico, a sus usuarios de ciertos cambios o nuevos servicios disponibles. La experiencia me ha indicado que el usuario aprecia más un correo personalizado que uno general. Sin embargo, lograr lo &#8230; <a href="http://blog.milmazz.com.ve/archivos/2011/09/21/enviando-correos-con-perl">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Regularmente los administradores de sistemas requieren notificar, vía correo electrónico, a sus usuarios de ciertos cambios o nuevos servicios disponibles. La experiencia me ha indicado que el usuario aprecia más un correo personalizado que uno general. Sin embargo, lograr lo primero de manera manual es bastante tedioso e ineficaz. Por lo tanto, es lógico pensar en la posibilidad de automatizar el proceso de envío de correos electrónicos personalizados, en este artículo, explicaré una de las tantas maneras de lograrlo haciendo uso del lenguaje de programación <a title="Perl" href="http://www.perl.org/">Perl</a>.</p>
<p>En <a title="Comprehensive Perl Archive Network" href="http://www.cpan.org/">CPAN</a> podrá encontrar muchas alternativas, recuerde el principio <a href="http://en.wikipedia.org/wiki/There_is_more_than_one_way_to_do_it">TIMTOWTDI</a>. Sin embargo, la opción que más me atrajo fue <code>MIME::Lite:TT</code>, básicamente este módulo en Perl es un <em>wrapper</em> de <code>MIME::Lite</code> que le permite el uso de plantillas, vía <code>Template::Toolkit</code>, para el cuerpo del mensaje del correo electrónico. También puede encontrar <code>MIME::Lite::TT::HTML</code> que le permitirá enviar correos tanto en texto sin formato (<code>MIME::Lite::TT</code>) como en formato HTML. Sin embargo, estoy en contra de enviar correos en formato HTML, lo dejo a su criterio.</p>
<p>Una de las ventajas de utilizar <code>Template::Toolkit</code> para el cuerpo del mensaje es separar en <em>capas</em> nuestra <em>script</em>, si se observa desde una versión muy simplificada del patrón <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" title="Modelo Vista Controlador">MVC</a>, el control de la lógica de programación reside en el <em>script</em> en Perl, la plantilla basada en <em>Template Toolkit</em> ofrecería la vista de los datos, de modo tal que podríamos garantizar que la presentación está separada de los datos, los cuales pueden encontrarse desde una base de datos o un simple fichero CSV. Otra ventaja evidente es el posible reuso de componentes posteriormente.</p>
<p>Un primer ejemplo del uso de <code>MIME::Lite:TT</code> puede ser el siguiente:</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/perl

use strict;
use warnings;
use MIME::Lite::TT;

my %options;
$options{INCLUDE_PATH} = '/home/jdoe/example';

my %params;
$params{first_name} = &quot;Milton&quot;;
$params{last_name}  = &quot;Mazzarri&quot;;
$params{username}   = &quot;milmazz&quot;;
$params{groups}     = &quot;sysadmin&quot;;

my $msg = MIME::Lite::TT-&gt;new(
    From        =&gt; 'jdoe@example.com',
    To          =&gt; 'milmazz@example.com',
    Charset     =&gt; 'utf8',
    TimeZone    =&gt; 'America/Caracas',
    Subject     =&gt; 'Example',
    Template    =&gt; 'example.txt.tt',
    TmplOptions =&gt; \%options,
    TmplParams  =&gt; \%params,
);

$msg-&gt;send();
</pre>
<p>Y el cuerpo del correo electrónico, lo que en realidad es una plantilla basada en <code>Template::Toolkit</code>, vendría definido en el fichero <code>example.txt.tt</code> de la siguiente manera:</p>
<pre class="brush: perl; title: ; notranslate">
Hola [% last_name %], [% first_name %].

Tu nombre de usuario es [% username %].

Un saludo, feliz día.

Su querido BOFH de siempre.
</pre>
<p>En el <em>script</em> en Perl mostrado previamente podemos percatarnos que los datos del destinario se encuentran inmersos en la lógica. Por lo tanto, el siguiente paso sería desacoplar esta parte de la siguiente manera:</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/perl

use strict;
use warnings;
use MIME::Lite::TT;
use Class::CSV;

my %options;
$options{INCLUDE_PATH} = '/home/jdoe/example';

# Lectura del fichero CSV
my $csv = Class::CSV-&gt;parse(
    filename       =&gt; 'example.csv',
    fields         =&gt; [qw/last_name first_name username email/],
    csv_xs_options =&gt; { binary =&gt; 1, }
);

foreach my $line ( @{ $csv-&gt;lines() } ) {
    my %params;

    $params{first_name} = $line-&gt;first_name();
    $params{last_name}  = $line-&gt;last_name();
    $params{username}   = $line-&gt;username();

    my $msg = MIME::Lite::TT-&gt;new(
        From        =&gt; 'jdoe@example.com',
        To          =&gt; $line-&gt;email(),
        Charset     =&gt; 'utf8',
        TimeZone    =&gt; 'America/Caracas',
        Subject     =&gt; 'Example',
        Template    =&gt; 'example.txt.tt',
        TmplOptions =&gt; \%options,
        TmplParams  =&gt; \%params,
    );

    $msg-&gt;send();
}
</pre>
<p>Ahora los datos de los destinarios los extraemos de un fichero en formato <acronym title="Comma-Separated Values">CSV</acronym>, en este ejemplo, el fichero en formato <acronym title="Comma-Separated Values">CSV</acronym> lo hemos denominado <code>example.csv</code>.</p>
<p>Cabe aclarar que <code>$msg-&gt;send()</code> realiza el envío por medio de <code>Net::SMTP</code> y podrá usar las opciones que se describen en dicho módulo. Sin embargo, si necesita establecer una conexión <acronym title="Secure Sockets Layer">SSL</acronym> con el servidor <acronym title="Simple Mail Transfer Protocol">SMTP</acronym> es oportuno recurrir a <code>Net::SMTP::SSL</code>:</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/perl

use strict;
use warnings;
use MIME::Lite::TT;
use Net::SMTP::SSL;
use Class::CSV;

my $from = 'jdoe@example.com';
my $host = 'mail.example.com';
my $user = 'jdoe';
my $pass = 'example';

my %options;
$options{INCLUDE_PATH} = '/home/jdoe/example';

# Lectura del fichero CSV
my $csv = Class::CSV-&gt;parse(
    filename       =&gt; 'example.csv',
    fields         =&gt; [qw/last_name first_name username email/],
    csv_xs_options =&gt; { binary =&gt; 1, }
);

foreach my $line ( @{ $csv-&gt;lines() } ) {
    my %params;

    $params{first_name} = $line-&gt;first_name();
    $params{last_name}  = $line-&gt;last_name();
    $params{username}   = $line-&gt;username();

    my $msg = MIME::Lite::TT-&gt;new(
        From        =&gt; $from,
        To          =&gt; $line-&gt;email(),
        Charset     =&gt; 'utf8',
        TimeZone    =&gt; 'America/Caracas',
        Subject     =&gt; 'Example',
        Template    =&gt; 'example.txt.tt',
        TmplOptions =&gt; \%options,
        TmplParams  =&gt; \%params,
    );

    my $smtp = Net::SMTP::SSL-&gt;new( $host, Port =&gt; 465 )
      or die &quot;No pude conectarme&quot;;
    $smtp-&gt;auth( $user, $pass )
      or die &quot;No pude autenticarme:&quot; . $smtp-&gt;message();
    $smtp-&gt;mail($from)                 or die &quot;Error:&quot; . $smtp-&gt;message();
    $smtp-&gt;to( $line-&gt;email() )        or die &quot;Error:&quot; . $smtp-&gt;message();
    $smtp-&gt;data()                      or die &quot;Error:&quot; . $smtp-&gt;message();
    $smtp-&gt;datasend( $msg-&gt;as_string ) or die &quot;Error:&quot; . $smtp-&gt;message();
    $smtp-&gt;dataend()                   or die &quot;Error:&quot; . $smtp-&gt;message();
    $smtp-&gt;quit()                      or die &quot;Error:&quot; . $smtp-&gt;message();
}
</pre>
<p>Note en este último ejemplo que la representación en cadena de caracteres del cuerpo del correo electrónico viene dado por <code>$msg-&gt;as_string</code>.</p>
<p>Para finalizar, es importante mencionar que también podrá adjuntar ficheros de cualquier tipo a sus correos electrónicos, solo debe prestar especial atención en el tipo <acronym title="Multipurpose Internet Mail Extensions">MIME</acronym> de los ficheros que adjunta, es decir, si enviará un fichero adjunto PDF debe utilizar el tipo <code>application/pdf</code>, si envía una imagen en el formato GIF, debe usar el tipo <code>image/gif</code>. El método a seguir para adjuntar uno o más ficheros lo dejo para su investigación <img src='http://blog.milmazz.com.ve/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=iv2yE3keC7w:74NUyVD3yW0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=iv2yE3keC7w:74NUyVD3yW0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=iv2yE3keC7w:74NUyVD3yW0:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=iv2yE3keC7w:74NUyVD3yW0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=iv2yE3keC7w:74NUyVD3yW0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=iv2yE3keC7w:74NUyVD3yW0:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2011/09/21/enviando-correos-con-perl/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2011/09/21/enviando-correos-con-perl</feedburner:origLink></item>
		<item>
		<title>Cambiar focos delanteros de un Ford Fiesta</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/M7ToImb8VF0/cambiar-focos-delanteros-ford-fiesta</link>
		<comments>http://blog.milmazz.com.ve/archivos/2011/03/30/cambiar-focos-delanteros-ford-fiesta#comments</comments>
		<pubDate>Wed, 30 Mar 2011 06:41:33 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[Mecánica]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[fiesta]]></category>
		<category><![CDATA[ford]]></category>
		<category><![CDATA[mecánica]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=396</guid>
		<description><![CDATA[Aprovechando que uno de los bombillos convencionales de mi automóvil llegó al final de su vida útil decidí mejorar la iluminación de los faros delanteros debido los constantes viajes que realizo de noche y las malas condiciones (lluvia, neblina) con las que me encuentro ocasionalmente. <a href="http://blog.milmazz.com.ve/archivos/2011/03/30/cambiar-focos-delanteros-ford-fiesta">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Advertencia:</strong> Esta es la primera de una posible serie de entradas acerca de tópicos relacionados con la mecánica y el mantenimiento regular de automóviles, desde ya aclaro que no es mi especialidad por lo cual agradezco cualquier comentario, sugerencia o crítica. Sin embargo, espero que por medio de esta serie de artículos logre transmitir lo poco que voy aprendiendo acerca de este fascinante tema.</p>
<p>Aprovechando que uno de los bombillos convencionales de mi automóvil llegó al final de su vida útil decidí mejorar la iluminación de los faros delanteros debido los constantes viajes que realizo de noche y las malas condiciones (lluvia, neblina) con las que me encuentro ocasionalmente.</p>
<p>Antes de realizar la compra, tenía claro lo siguiente: <strong>No</strong> iba a modificar el automóvil y el objetivo es mejorar la visibilidad al conducir en condiciones adversas, nada de <acronym title="High Intensity Discharge">HID</acronym> y <em>tuning</em> innecesario.</p>
<p>Debido a la poca variedad que logré encontrar acá me decanté por unos bombillos OSRAM <em>Cool Blue</em> estándar (4000 Kelvin), no encontré ni los <em>Cool Blue Mega</em> (4300K), <em>Cool Blue Hyper</em> (5000K) o los <em>Night Breaker</em> de OSRAM. Por cierto, el modelo de las lámparas para mi automóvil son H7 (bajas) y H1 (altas). Revise los detalles técnicos de su vehículo en el <em>Manual del propietario</em>.</p>
<p>El procedimiento para el cambio de los focos es sencillo, está documentado en el <em>Manual del Propietario y Mantenimiento</em> del vehículo. Sin embargo, he publicado un álbum de fotos con ciertas notas y descripciones para mejor comprensión del tema en mi cuenta <a href="http://www.flickr.com/photos/milmazz/" title="Galería de milmazz">Flickr</a>.</p>
<p><object width="400" height="300"><param name="flashvars" value="offsite=true&#038;lang=es-us&#038;page_show_url=%2Fphotos%2Fmilmazz%2Fsets%2F72157626258649047%2Fshow%2F&#038;page_show_back_url=%2Fphotos%2Fmilmazz%2Fsets%2F72157626258649047%2F&#038;set_id=72157626258649047&#038;jump_to="></param><param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"></param><param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&#038;lang=es-us&#038;page_show_url=%2Fphotos%2Fmilmazz%2Fsets%2F72157626258649047%2Fshow%2F&#038;page_show_back_url=%2Fphotos%2Fmilmazz%2Fsets%2F72157626258649047%2F&#038;set_id=72157626258649047&#038;jump_to=" width="400" height="300"></embed></object></p>
<p>Después de instalar las lámparas puedo decir que estoy contento con las <em>Cool Blue</em> estándar de OSRAM, se percibe de inmediato una notable mejoría respecto a la lámpara convencional, consumiendo la misma potencia en vatios. Las <em>Cool Blue</em> emiten luz blanca clara y azulada, el haz de luz es similar a las lámparas <acronym title="High Intensity Discharge">HID</acronym> (las cuales por lo que leí van del rango 4000K a 12000K), lo más importante es que no tuve que modificar mi carro en lo absoluto para obtener dicho efecto.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=M7ToImb8VF0:rlrPCM8FyE8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=M7ToImb8VF0:rlrPCM8FyE8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=M7ToImb8VF0:rlrPCM8FyE8:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=M7ToImb8VF0:rlrPCM8FyE8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=M7ToImb8VF0:rlrPCM8FyE8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=M7ToImb8VF0:rlrPCM8FyE8:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2011/03/30/cambiar-focos-delanteros-ford-fiesta/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2011/03/30/cambiar-focos-delanteros-ford-fiesta</feedburner:origLink></item>
		<item>
		<title>Construyendo de manera efectiva y rápida imágenes ISO de Debian con jigdo</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/wxAMdqr4COg/construyendo-de-manera-efectiva-y-rapida-imagenes-iso-de-debian-con-jigdo</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/12/02/construyendo-de-manera-efectiva-y-rapida-imagenes-iso-de-debian-con-jigdo#comments</comments>
		<pubDate>Thu, 02 Dec 2010 18:34:39 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[iso]]></category>
		<category><![CDATA[jigdo]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=378</guid>
		<description><![CDATA[Si usted desea el conjunto de CD o DVD para instalar Debian, tiene muchas posibilidades, desde la compra de los mismos, muchos de los vendedores contribuyen con Debian. También puede realizar descargas vía HTTP/FTP, vía torrent o rsync. Pero en &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/12/02/construyendo-de-manera-efectiva-y-rapida-imagenes-iso-de-debian-con-jigdo">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Si usted desea el conjunto de CD o DVD para instalar Debian, tiene muchas posibilidades, desde la <a href="http://www.debian.org/CD/vendors/">compra</a> de los mismos, muchos de los vendedores contribuyen con Debian. También puede realizar descargas vía <a href="http://www.debian.org/CD/http-ftp/">HTTP/FTP</a>, vía <a href="http://www.debian.org/CD/torrent-cd/">torrent</a> o <a href="http://www.debian.org/CD/mirroring/rsync-mirrors">rsync</a>. Pero en este artículo se discutirá sobre un método para construir las imágenes ISO de Debian de manera eficiente, sobretodo si cuenta con un repositorio local de paquetes, dicho método se conoce de manera abreviada como <a href="http://atterer.org/jigdo/">jigdo</a> o <em>Jigsaw Download</em>.</p>
<p>Las ventajas que ofrece <a href="http://www.debian.org/CD/jigdo-cd/">jigdo</a> están bien claras en el portal de Debian, cito:</p>
<blockquote lang="es" cite="http://www.debian.org/CD/jigdo-cd/"><p>¿Por qué jigdo es mejor que una descarga directa?</p>
<p>¡Porque es más rápido! Por varias razones, hay muchas menos réplicas para imágenes de CDs que para el archivo «normal» de Debian. Consecuentemente, si descarga desde una réplica de imágenes de CD, esa réplica no sólo estará más lejos de su ubicación, además estará sobrecargada, especialmente justo después de una publicación.</p>
<p>Además, algunos tipos de imágenes no están disponibles para descarga completa como .iso porque no hay suficiente espacio en nuestros servidores para alojarlas.</p></blockquote>
<p>Considero que la pregunta pertinente ahora es: <em>¿Cómo descargo la imagen con jigdo?</em>.</p>
<p>En primer lugar, instalamos el paquete <code>jigdo-file</code>.</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
# aptitude install jigdo-file
</pre>
<p>Mi objetivo era generar los 2 primeros CD para Debian Lenny, para la fecha de publicación de este artículo la versión más reciente es la <a title="Updated Debian GNU/Linux: 5.0.7 released" href="http://www.debian.org/News/2010/20101127">5.0.7</a>. La lista de imágenes oficiales para <em>jigdo</em> las puede encontrar <a href="http://www.debian.org/CD/jigdo-cd/#which">acá</a>.</p>
<pre class="brush: powershell; light: true; title: ; notranslate">

milmazz@manaslu /tmp $ cat files

http://cdimage.debian.org/debian-cd/5.0.7/i386/jigdo-cd/debian-507-i386-CD-1.jigdo

http://cdimage.debian.org/debian-cd/5.0.7/i386/jigdo-cd/debian-507-i386-CD-1.template

http://cdimage.debian.org/debian-cd/5.0.7/i386/jigdo-cd/debian-507-i386-CD-2.jigdo

http://cdimage.debian.org/debian-cd/5.0.7/i386/jigdo-cd/debian-507-i386-CD-2.template

milmazz@manaslu /tmp $ wget -c -i files
--2010-12-02 12:39:52--  http://cdimage.debian.org/debian-cd/5.0.7/i386/jigdo-cd/debian-507-i386-CD-1.jigdo
Resolving cdimage.debian.org... 130.239.18.163, 130.239.18.173, 2001:6b0:e:2018::173, ...
Connecting to cdimage.debian.org|130.239.18.163|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 31737 (31K) 1
Saving to: `debian-507-i386-CD-1.jigdo'

100%[===================================================================================================================&gt;] 31.737      44,7K/s   in 0,7s

...

FINISHED --2010-12-02 12:50:15--
Downloaded: 4 files, 27M in 10m 21s (44,7 KB/s)
milmazz@manaslu /tmp $ ls
debian-507-i386-CD-1.jigdo  debian-507-i386-CD-1.template  debian-507-i386-CD-2.jigdo  debian-507-i386-CD-2.template files
</pre>
<p>Una vez descargados los ficheros necesarios, es hora de ejecutar el comando <code>jigdo-lite</code>, siga las instrucciones del asistente.</p>
<pre class="brush: powershell; light: true; title: ; notranslate">

milmazz@manaslu ~ $ jigdo-lite debian-507-i386-CD-2.jigdo

Jigsaw Download &quot;lite&quot;
Copyright (C) 2001-2005  |  jigdo@
Richard Atterer          |  atterer.net
Loading settings from `/home/milmazz/.jigdo-lite'

-----------------------------------------------------------------
Images offered by `debian-507-i386-CD-2.jigdo':
1: 'Debian GNU/Linux 5.0.7 &quot;Lenny&quot; - Official i386 CD Binary-2 20101127-16:55 (20101127)' (debian-507-i386-CD-2.iso)

Further information about `debian-507-i386-CD-2.iso':
Generated on Sat, 27 Nov 2010 17:02:14 +0000

-----------------------------------------------------------------
If you already have a previous version of the CD you are
downloading, jigdo can re-use files on the old CD that are also
present in the new image, and you do not need to download them
again. Mount the old CD ROM and enter the path it is mounted under
(e.g. `/mnt/cdrom').
Alternatively, just press enter if you want to start downloading
the remaining files.
Files to scan:
</pre>
<p>El comando despliega información acerca de la imagen ISO que generará, en este caso particular, <code>debian-507-i386-CD-2.iso</code>. Además, <code>jigdo-lite</code> puede reutilizar ficheros que se encuentren en CD viejos y así no tener que descargarlos de nuevo. Sin embargo, este no era mi caso así que presione la tecla <kbd>ENTER</kbd>.</p>
<pre class="brush: powershell; light: true; title: ; notranslate">

-----------------------------------------------------------------
The jigdo file refers to files stored on Debian mirrors. Please
choose a Debian mirror as follows: Either enter a complete URL
pointing to a mirror (in the form
`ftp://ftp.debian.org/debian/'), or enter any regular expression
for searching through the list of mirrors: Try a two-letter
country code such as `de', or a country name like `United
States', or a server name like `sunsite'.
Debian mirror [http://debian.example.com/debian/]:
</pre>
<p>En esta fase <code>jigdo-lite</code> solicita la dirección <strong>URL completa</strong> de un repositorio, aproveche la oportunidad de utilizar su repositorio local si es que cuenta con uno. Luego de presionar la tecla <kbd>ENTER</kbd> es tiempo de relajarse y esperar que <code>jigdo</code> descargue todos y cada uno de los ficheros que componen la imagen ISO.</p>
<p>Luego de descargar los paquetes y realizar las operaciones necesarias para la construcción de la imagen ISO <code>jigdo</code> le informará los resultados.</p>
<pre class="brush: powershell; light: true; title: ; notranslate">

FINISHED --2010-12-01 14:43:50--
Downloaded: 6 files, 2,5M in 1,8s (1,39 MB/s)
Found 6 of the 6 files required by the template
Successfully created `debian-507-i386-CD-2.iso'

-----------------------------------------------------------------
Finished!
The fact that you got this far is a strong indication that `debian-507-i386-CD-2.iso'
was generated correctly. I will perform an additional, final check,
which you can interrupt safely with Ctrl-C if you do not want to wait.

OK: Checksums match, image is good!
</pre>
<p>Ahora bien, haciendo uso de un repositorio local, es bueno preguntarse en cuanto tiempo aproximadamente puedes construir tu imagen ISO, en mi caso el tiempo de construcción de <code>debian-507-i386-CD-2.iso</code> fue de:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">

milmazz@manaslu ~ $ time jigdo-lite debian-507-i386-CD-2.jigdo

...

real	8m35.704s
user	0m13.101s
sys	0m16.569s
</pre>
<p>Nada mal, ¿no les parece?.</p>
<p>Ahora bien, haciendo uso de un repositorio local, es bueno preguntarse en cuanto tiempo aproximadamente puedes construir tu imagen ISO, en mi caso el tiempo de construcción de <code>debian-507-i386-CD-2.iso</code> fue de:</p>
<h2>Referencias</h2>
<ul>
<li><a title="Jigsaw Download" href="http://atterer.org/jigdo">jigdo &#8211; Jigsaw Download</a></li>
<li><a href="http://www.debian.org/CD/jigdo-cd/">Descargar imágenes de CD de Debian con jigdo</a></li>
<li><a title="Debian Jigdo mini-HOWTO" href="http://atterer.org/jigdo/debian-jigdo-mini-howto">Debian Jigdo mini-HOWTO</a></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=wxAMdqr4COg:5X7BufadltA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=wxAMdqr4COg:5X7BufadltA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=wxAMdqr4COg:5X7BufadltA:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=wxAMdqr4COg:5X7BufadltA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=wxAMdqr4COg:5X7BufadltA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=wxAMdqr4COg:5X7BufadltA:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/12/02/construyendo-de-manera-efectiva-y-rapida-imagenes-iso-de-debian-con-jigdo/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/12/02/construyendo-de-manera-efectiva-y-rapida-imagenes-iso-de-debian-con-jigdo</feedburner:origLink></item>
		<item>
		<title>Introducción a pruebas de rendimiento sobre aplicaciones Web con Multi-Mechanize (Parte I)</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/pFIk_h8EfFU/introduccion-a-pruebas-de-rendimiento-sobre-aplicaciones-web-con-multi-mechanize-parte-i</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/12/01/introduccion-a-pruebas-de-rendimiento-sobre-aplicaciones-web-con-multi-mechanize-parte-i#comments</comments>
		<pubDate>Wed, 01 Dec 2010 20:46:11 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[mechanize]]></category>
		<category><![CDATA[pruebas]]></category>
		<category><![CDATA[rendimiento]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=369</guid>
		<description><![CDATA[Corey Goldberg, autor de la herramienta para pruebas de rendimiento Pylot, anunciaba a mediados del mes de febrero de este año que estaba trabajando en un nuevo framework para este mismo tipo de pruebas, al que denominó Multi-Mechanize. Pero parece &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/12/01/introduccion-a-pruebas-de-rendimiento-sobre-aplicaciones-web-con-multi-mechanize-parte-i">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a title="Corey Goldberg" href="http://coreygoldberg.blogspot.com">Corey Goldberg</a>, autor de la herramienta para pruebas de rendimiento <a title="Pylot" href="http://www.pylot.org/">Pylot</a>, <a title="Multi-Mechanize - new open source performance testing tool " href="http://coreygoldberg.blogspot.com/2010/02/multi-mechanize-new-open-source.html">anunciaba</a> a mediados del mes de febrero de este año que estaba trabajando en un nuevo <em>framework</em> para este mismo tipo de pruebas, al que denominó Multi-Mechanize. Pero parece lógico preguntarse: ¿por qué otra herramienta?, Corey argumentaba que el diseño de <em>Pylot</em> está bastante limitado debido al hecho que los <em>casos de pruebas</em> deben establecerse en forma declarativa, vía XML, llegando a la conclusión que era necesario un lenguaje de <em>scripting</em> para la definición de los casos de pruebas, además, la mejora en la concurrencia de las mismas.</p>
<p><a title="Multi Mechanize" href="http://code.google.com/p/multi-mechanize/">Multi-Mechanize</a> es un <em>framework</em> orientado a pruebas de rendimiento y carga en sitios <em>Web</em>. Este <em>framework</em> permite la ejecución simultánea de <em>scripts</em> en <a title="Python" href="http://www.python.org/">Python</a> por medio de un motor multi-proceso, multi-hilo para reproducir secuencias de comandos y generar usuarios virtuales de manera concurrente, todo esto con el fin de establecer carga en contra de un sitio o servicio <em>Web</em>.</p>
<p>Una de las grandes ventajas de Multi-Mechanize es que ofrece la posibilidad de incluir en los <em>scripts</em> el poderoso módulo <a title="Python Mechanize" href="http://wwwsearch.sourceforge.net/mechanize/">mechanize</a> (derivado de <a title="WWW:Mechanize" href="http://search.cpan.org/dist/WWW-Mechanize/">WWW::Mechanize</a> en Perl) junto con el lenguaje de programación Python. Permitiendo crear <em>scripts</em> de pruebas que simulan la actividad de <em>usuarios virtuales</em> de manera rápida y sencilla, estos <em>scripts</em> generarán peticiones HTTP para navegar o enviar solicitudes de forma inteligente un sitio o servicio <em>Web</em>.</p>
<p>Los resultados se almacenan en formato <acronym title="Comma-Separated Values">CSV</acronym> o en una base de datos, junto con el informe en formato <acronym title="HyperText Markup Language">HTML</acronym> que contiene las estadísticas y gráficos.</p>
<p>Un ejemplo de la capacidad de reportes que ofrece Multi-Mechanize puede verla en <a href="http://code.google.com/p/multi-mechanize/">http://code.google.com/p/multi-mechanize/</a></p>
<h2>Requisitos</h2>
<p>Multi-Mechanize requiere Python 2.x (2.6 o 2.7), si desea generar gráficos a partir de las pruebas, debe instalar <a title="Matplotlib" href="http://matplotlib.sourceforge.net/">Matplotib</a> y sus dependencias, mayor información vea la página de <a href="http://code.google.com/p/multi-mechanize/wiki/FAQ">Preguntas de Uso Frecuente</a></p>
<p>De manera adicional necesitará el módulo <a title="Python Mechanize" href="http://wwwsearch.sourceforge.net/mechanize/">mechanize</a>.</p>
<p>La instalación de los requisitos en Debian GNU/Linux y derivados es tal como se describe a continuación:</p>
<pre># aptitude install python-mechanize python-matplotlib</pre>
<h3>Almacenamiento de datos de prueba y resultados en Bases de Datos</h3>
<p>Opcionalmente, los resultados pueden ser almacenados en una base de datos. Para ello debe agregar la opción <code>results_database</code> en el fichero de configuración <code>config.cfg</code>, el cual define la cadena de conexión a la base de datos.</p>
<p>El almacenamiento en base de datos requiere tener instalado previamente <a title="SQLAlchemy" href="http://www.sqlalchemy.org/">SQLAlchemy</a></p>
<p>Algunos ejemplos de conexión a bases de datos son los siguientes:</p>
<table>
<tbody>
<tr>
<td>SQLite</td>
<td><code>sqlite:///dbname</code></td>
</tr>
<tr>
<td>MySQL</td>
<td><code>mysql://user:password@localhost/dbname</code></td>
</tr>
<tr>
<td>PostgreSQL</td>
<td><code>postgresql://user:password@host:port/dbname</code></td>
</tr>
<tr>
<td>MS SQL Server</td>
<td><code>mssql://mydsn</code></td>
</tr>
</tbody>
</table>
<p>Tenga en cuenta que el soporte de <em>SQLite</em> es nativo en Python. Por lo tanto, no es necesario su instalación y configuración.</p>
<p>Para mayor información sobre el soporte a base de datos vea <a href="http://code.google.com/p/multi-mechanize/wiki/DatabaseStorage">Database Storage</a></p>
<h2>Instalando Multi-Mechanize</h2>
<p>Puede descargar el proyecto Multi-Mechanize desde <a href="http://code.google.com/p/multi-mechanize/downloads/list">http://code.google.com/p/multi-mechanize/downloads/list</a></p>
<p>Una vez descargado el proyecto Multi-Mechanize, descomprima y vaya a la raíz del proyecto y ejecute desde la línea de comandos:</p>
<pre>$ python multi-mechanize.py default_project</pre>
<p>Este comando ejecutará el proyecto de prueba incluido en la distribución de Multi-Mechanize, el proyecto de prueba generará datos aleatorios.</p>
<p><strong>NOTA:</strong> Se le recomienda analizar los <em>scripts</em> incluidos en <code>projects/default_project/test_scripts/</code></p>
<h2>Comenzando con Multi-Mechanize</h2>
<p>Para iniciar, usted puede usar el directorio <code>default_project</code> que incluye la distribución de Multi-Mechanize. Si usted necesita manejar múltiples proyectos, solo cree un directorio al mismo nivel de <code>default_project</code> para cada uno de los proyectos, se le recomienda mantener la misma estructura del proyecto por omisión. Recuerde que se necesita especificar el proyecto que ejecutará desde la línea de comandos.</p>
<p>Cada proyecto debe contener lo siguiente:</p>
<dl>
<dt><code>config.cfg</code></dt>
<dd>Fichero de configuración, establezca sus opciones de prueba.</dd>
<dt><code>test_scripts</code></dt>
<dd>Directorio de almacenamiento de scripts de sus usuarios virtuales.</dd>
<dt><code>results</code></dt>
<dd> Directorio para el almacenamiento de los resultados. Acá encontrará subdirectorios cuyos nombres son una estampa de tiempo y son creados por cada ejecución de las pruebas y contiene datos en formato CSV, un sumario en formato HTML e imágenes en formato PNG.</dd>
</dl>
<h3>Formato del fichero de configuración</h3>
<p>Cada proyecto contiene un fichero <code>config.cfg</code> donde debe definir la configuración para una prueba.</p>
<p>A continuación se le muestra un fichero de configuración que muestra todas las opciones posibles de configuración:</p>
<pre>[global]
run_time: 300
rampup: 300
console_logging: off
results_ts_interval: 30
results_database: sqlite:///projects/default_project/results.db
post_run_script: python projects/default_project/foo.py

[user_group-1]
threads: 30
script: example_mock.py

[user_group-2]
threads: 30
script: example_mock.py
</pre>
<h4>Opciones globales</h4>
<dl>
<dt><code>run_time</code></dt>
<dd>Duración de la prueba en segundos</dd>
<dt><code>rampup</code></dt>
<dd>Duración en segundos de la rampa de usuarios (hilos)</dd>
<dt><code>console_logging</code></dt>
<dd>Activar/Desactivar el registro a la salida estándar</dd>
<dt><code>results_ts_interval</code></dt>
<dd>Intervalos de las series de tiempo para el análisis de los resultados expresadas en segundos.</dd>
<dt><code>results_database</code></dt>
<dd>Cadena de conexión a base de datos (opcional)</dd>
<dt><code>post_run_script</code></dt>
<dd> <em>script</em> que será invocado después de la culminación de la prueba (opcional)</dd>
</dl>
<h4>Grupos de usuarios</h4>
<dl>
<dt><code>threads</code></dt>
<dd>Número de hilos/usuarios virtuales</dd>
<dt><code>script</code> </dt>
<dd>Script del usuario virtual a ejecutar.</dd>
</dl>
<p>Para mayor información sobre el formato del fichero de configuración consulte: <a title="Configuration File" href="http://code.google.com/p/multi-mechanize/wiki/ConfigFile">Config File</a>.</p>
<p>En la segunda parte de este artículo mostraré algunos ejemplos con <em>casos de pruebas</em> que se ejecutarán sobre una <a title="Instalación básica de Trac y Subversion" href="http://blog.milmazz.com.ve/archivos/2010/04/23/instalacion-basica-de-trac-y-subversion">instalación de Trac</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=pFIk_h8EfFU:3mPZ7NiQf5g:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=pFIk_h8EfFU:3mPZ7NiQf5g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=pFIk_h8EfFU:3mPZ7NiQf5g:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=pFIk_h8EfFU:3mPZ7NiQf5g:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=pFIk_h8EfFU:3mPZ7NiQf5g:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=pFIk_h8EfFU:3mPZ7NiQf5g:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/12/01/introduccion-a-pruebas-de-rendimiento-sobre-aplicaciones-web-con-multi-mechanize-parte-i/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/12/01/introduccion-a-pruebas-de-rendimiento-sobre-aplicaciones-web-con-multi-mechanize-parte-i</feedburner:origLink></item>
		<item>
		<title>Generar reporte en formato CSV de tickets en Trac desde Perl</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/W_6taMnuEjM/generar-reporte-en-formato-csv-de-tickets-en-trac-desde-perl</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/11/17/generar-reporte-en-formato-csv-de-tickets-en-trac-desde-perl#comments</comments>
		<pubDate>Wed, 17 Nov 2010 21:42:06 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[trac]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=355</guid>
		<description><![CDATA[El día de hoy recibí una llamada telefónica de un compañero de labores en donde me solicitaba con cierta preocupación un &#8220;pequeño&#8221; reporte del estado de un listado de tickets que recién me había enviado vía correo electrónico puesto que &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/11/17/generar-reporte-en-formato-csv-de-tickets-en-trac-desde-perl">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>El día de hoy recibí una llamada telefónica de un compañero de labores en donde me solicitaba con cierta preocupación un &#8220;pequeño&#8221; reporte del estado de un listado de <em>tickets</em> que recién me había enviado vía correo electrónico puesto que no contaba con conexión a la <em>intranet</em>, al analizar un par de <em>tickets</em> me dije que no iba a ser fácil realizar la consulta desde el asistente que brinda el mismo <a title="Trac" href="http://trac.edgewall.com">Trac</a>. Así que inmediatamente puse las manos sobre un pequeño <em>script</em> en Perl que hiciera el <em>trabajo sucio</em> por mí.</p>
<p>Es de hacer notar que total de tickets a revisar era el siguiente:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
$ wc -l tickets
126 tickets
</pre>
<p>Tomando en cuenta el resultado previo, era <strong>inaceptable</strong> hacer dicha labor de manera manual. Por lo tanto, confirmaba que realizar un <em>script</em> era la vía correcta y a la final iba a ser más divertido.</p>
<p>Tomando en cuenta que el formato de entrada era el siguiente:</p>
<p>#3460<br />
#3493<br />
&#8230;</p>
<p>El formato de la salida que esperaba era similar a la siguiente:</p>
<p>3460,&quot;No expira la sesión&#8230;&quot;,closed,user</p>
<p>Básicamente el formato implica el <em>id</em>, <em>sumario</em>, <em>estado</em> y <em>responsable</em> asociado al <strong>ticket</strong>.</p>
<p><a title="Net::Trac" href="http://search.cpan.org/~jesse/Net-Trac-0.15/lib/Net/Trac.pm">Net::Trac</a> le ofrece una manera sencilla de interactuar con una instancia remota de Trac, desde el manejo de credenciales, consultas, revisión de <em>tickets</em>, entre otros. A la vez, se hace uso del módulo <a title="Class::CSV" href="http://search.cpan.org/~djr/Class-CSV-1.03/CSV.pm">Class::CSV</a> el cual le ofrece análisis y escritura de documentos en formato <abbr title="Comma Separated Values">CSV</abbr>.</p>
<div id="gist-704082" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1">#!/usr/bin/perl </span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="k">use</span> <span class="n">warnings</span><span class="p">;</span></div><div class='line' id='LC4'><span class="k">use</span> <span class="n">strict</span><span class="p">;</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">use</span> <span class="nn">Net::</span><span class="n">Trac</span><span class="p">;</span></div><div class='line' id='LC7'><span class="k">use</span> <span class="nn">Class::</span><span class="n">CSV</span><span class="p">;</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="c1"># Estableciendo la conexion a la instancia remota de Trac</span></div><div class='line' id='LC10'><span class="k">my</span> <span class="nv">$trac</span> <span class="o">=</span> <span class="nn">Net::Trac::</span><span class="n">Connection</span><span class="o">-&gt;</span><span class="k">new</span><span class="p">(</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">url</span>      <span class="o">=&gt;</span> <span class="s">&#39;http://trac.example.com/project&#39;</span><span class="p">,</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span>     <span class="o">=&gt;</span> <span class="s">&#39;user&#39;</span><span class="p">,</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">password</span> <span class="o">=&gt;</span> <span class="s">&#39;password&#39;</span></div><div class='line' id='LC14'><span class="p">);</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="c1"># Construccion del objecto CSV y definicion de opciones</span></div><div class='line' id='LC17'><span class="k">my</span> <span class="nv">$csv</span> <span class="o">=</span> <span class="nn">Class::</span><span class="n">CSV</span><span class="o">-&gt;</span><span class="k">new</span><span class="p">(</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fields</span>         <span class="o">=&gt;</span> <span class="p">[</span><span class="sx">qw/ticket sumario estado responsable/</span><span class="p">],</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">line_separator</span> <span class="o">=&gt;</span> <span class="s">&quot;\r\n&quot;</span><span class="p">,</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">csv_xs_options</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">binary</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span> <span class="p">}</span>    <span class="c1"># Manejo de caracteres non-ASCII</span></div><div class='line' id='LC21'><span class="p">);</span></div><div class='line' id='LC22'><br/></div><div class='line' id='LC23'><span class="c1"># Nos aseguramos que el inicio de sesion haya sido exitoso</span></div><div class='line' id='LC24'><span class="k">if</span> <span class="p">(</span> <span class="nv">$trac</span><span class="o">-&gt;</span><span class="n">ensure_logged_in</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">my</span> <span class="nv">$ticket</span> <span class="o">=</span> <span class="nn">Net::Trac::</span><span class="n">Ticket</span><span class="o">-&gt;</span><span class="k">new</span><span class="p">(</span> <span class="n">connection</span> <span class="o">=&gt;</span> <span class="nv">$trac</span> <span class="p">);</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1"># Consultamos cada uno de los tickets indicados en el fichero de entrada</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="p">(</span> <span class="k">my</span> <span class="nv">$line</span> <span class="o">=</span> <span class="o">&lt;&gt;</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">chomp</span><span class="p">(</span><span class="nv">$line</span><span class="p">);</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span> <span class="nv">$line</span> <span class="o">=~</span> <span class="sr">m/^#\d+$/</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">$line</span> <span class="o">=~</span> <span class="sr">s/^#(\d+)$/$1/</span><span class="p">;</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">$ticket</span><span class="o">-&gt;</span><span class="n">load</span><span class="p">(</span><span class="nv">$line</span><span class="p">);</span></div><div class='line' id='LC33'><br/></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">$csv</span><span class="o">-&gt;</span><span class="n">add_line</span><span class="p">(</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ticket</span>      <span class="o">=&gt;</span> <span class="nv">$ticket</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">,</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">sumario</span>     <span class="o">=&gt;</span> <span class="nv">$ticket</span><span class="o">-&gt;</span><span class="n">summary</span><span class="p">,</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">estado</span>      <span class="o">=&gt;</span> <span class="nv">$ticket</span><span class="o">-&gt;</span><span class="n">status</span><span class="p">,</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">responsable</span> <span class="o">=&gt;</span> <span class="nv">$ticket</span><span class="o">-&gt;</span><span class="n">owner</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">);</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&quot;[INFO] La linea no cumple el formato requerido: $line\n&quot;</span><span class="p">;</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">$csv</span><span class="o">-&gt;</span><span class="k">print</span><span class="p">();</span></div><div class='line' id='LC48'><span class="p">}</span></div><div class='line' id='LC49'><span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&quot;No se pudieron asegurar las credenciales&quot;</span><span class="p">;</span></div><div class='line' id='LC51'><span class="p">}</span></div><div class='line' id='LC52'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/704082/c7e8fdb1b9a3e08b7e63bcd366f294ddf2ab4beb/trac_query.pl" style="float:right;">view raw</a>
            <a href="https://gist.github.com/704082#file_trac_query.pl" style="float:right;margin-right:10px;color:#666">trac_query.pl</a>
            <a href="https://gist.github.com/704082">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>La manera de ejecutar el <code>script</code> es la siguiente:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
$ perl trac_query.pl tickets
</pre>
<p>En donde <code>trac_query.pl</code> es el nombre del <em>script</em> y <code>tickets</code> es el fichero de entrada.</p>
<p>Debo aclarar que el <em>script</em> carece de comentarios, <em>mea culpa</em>. Además, el manejo de opciones vía linea de comandos es <em>inexistente</em>, si desea mejorarlo puede hacer uso de <a title="Getopt::Long" href="http://perldoc.perl.org/Getopt/Long.html">Getopt::Long</a>.</p>
<p>Cualquier comentario, sugerencia o corrección es bienvenida.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=W_6taMnuEjM:Fp5wnR8CVLI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=W_6taMnuEjM:Fp5wnR8CVLI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=W_6taMnuEjM:Fp5wnR8CVLI:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=W_6taMnuEjM:Fp5wnR8CVLI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=W_6taMnuEjM:Fp5wnR8CVLI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=W_6taMnuEjM:Fp5wnR8CVLI:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/11/17/generar-reporte-en-formato-csv-de-tickets-en-trac-desde-perl/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/11/17/generar-reporte-en-formato-csv-de-tickets-en-trac-desde-perl</feedburner:origLink></item>
		<item>
		<title>Instalando dependencias no-libres de JAVA en ambientes pbuilder</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/GSRiULCqFOg/instalando-dependencias-no-libres-de-java-en-ambientes-pbuilder</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/11/15/instalando-dependencias-no-libres-de-java-en-ambientes-pbuilder#comments</comments>
		<pubDate>Mon, 15 Nov 2010 21:44:37 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[debconf]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[pbuilder]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=345</guid>
		<description><![CDATA[El día de hoy asumí la construcción de unos paquetes internos compatibles con Debian 5.0 (a.k.a. Lenny) que anteriormente eran responsabilidad de ex-compañeros de labores. El paquete en cuestión posee una dependencia no-libre, sun-java6-jre. En este artículo se describirá como &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/11/15/instalando-dependencias-no-libres-de-java-en-ambientes-pbuilder">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>El día de hoy asumí la construcción de unos paquetes internos compatibles con <a title="Debian - El sistema operativo universal" href="http://www.debian.org">Debian</a> 5.0 (a.k.a. Lenny) que anteriormente eran responsabilidad de ex-compañeros de labores. El paquete en cuestión posee una dependencia <strong>no-libre</strong>, <code>sun-java6-jre</code>. En este artículo se describirá como lograr adecuar su configuración de <code>pbuilder</code> para la correcta construcción del paquete.</p>
<p>Asumiendo que tiene un configuración similar a la siguiente:</p>
<pre class="brush: powershell; title: ; notranslate">
$ cat /etc/pbuilderrc
MIRRORSITE=http://example.com/debian
DEBEMAIL=&quot;Maintainer Name &#060;mail@example.com&#062;&quot;
DISTRIBUTION=lenny
DEBOOTSTRAP=&quot;cdebootstrap&quot;
COMPONENTS=&quot;main contrib non-free&quot;
</pre>
<p>Para mayor información sobre estas opciones sírvase leer:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
$ man 5 pbuilderrc
</pre>
<p>Mientras intenta compilar su paquete en el ambiente proporcionado por <code>pbuilder</code> el proceso fallará ya que no se mostró la ventana para aceptar la licencia de JAVA. Podrá observar en el registro de la construcción del build un mensaje similar al siguiente:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
Unpacking sun-java6-jre (from .../sun-java6-jre_6-20-0lenny1_all.deb) ...

sun-dlj-v1-1 license could not be presented
try 'dpkg-reconfigure debconf' to select a frontend other than noninteractive

dpkg: error processing /var/cache/apt/archives/sun-java6-jre_6-20-0lenny1_all.deb (--unpack):
subprocess pre-installation script returned error exit status 2
</pre>
<p>Para evitar esto altere la configuración del fichero <code>pbuilderrc</code> de la siguiente manera:</p>
<pre class="brush: powershell; highlight: [7]; title: ; notranslate">
$ cat /etc/pbuilderrc
MIRRORSITE=http://example.com/debian
DEBEMAIL=&quot;Maintainer Name &#060;mail@example.com&#062;&quot;
DISTRIBUTION=lenny
DEBOOTSTRAP=&quot;cdebootstrap&quot;
COMPONENTS=&quot;main contrib non-free&quot;
export DEBIAN_FRONTEND=&quot;readline&quot;
</pre>
<p>Una vez alterada la configuración podrá interactuar con las opciones que le ofrece <code>debconf</code>.</p>
<p>Ahora bien, si usted constantemente tiene que construir paquetes con dependencias <strong>no-libres</strong> como las de JAVA, es probable que le interese lo que se menciona a continuación.</p>
<p>Si lee detenidamente la página del manual de <code>pbuilder</code> en su sección 8 podrá encontrar lo siguiente:</p>
<pre class="brush: powershell; title: ; notranslate">
$ man 8 pbuilder
...
--save-after-login
--save-after-exec
Save the chroot image after exiting from the chroot instead of deleting changes.  Effective for login and execute session.
...
</pre>
<p>Por lo tanto, usaremos esta funcionalidad que ofrece <code>pbuilder</code> para insertar valores por omisión en la base de datos de <code>debconf</code> para que no se nos pregunte si deseamos aceptar la licencia de JAVA:</p>
<pre class="brush: powershell; highlight: [1,14,15,16,17,18,19,20]; title: ; notranslate">
# pbuilder login --save-after-login
I: Building the build Environment
I: extracting base tarball [/var/cache/pbuilder/base.tgz]
I: creating local configuration
I: copying local configuration
I: mounting /proc filesystem
I: mounting /dev/pts filesystem
I: Mounting /var/cache/pbuilder/ccache
I: policy-rc.d already exists
I: Obtaining the cached apt archive contents
I: entering the shell
File extracted to: /var/cache/pbuilder/build//27657

pbuilder:/# cat &#062; java-license &#060;&#060; EOF
&#062; sun-java6-bin shared/accepted-sun-dlj-v1-1 boolean true
&#062; sun-java6-jdk shared/accepted-sun-dlj-v1-1 boolean true
&#062; sun-java6-jre shared/accepted-sun-dlj-v1-1 boolean true
&#062; EOF
pbuilder:/# debconf-set-selections &#060; java-license
pbuilder:/# exit
logout
I: Copying back the cached apt archive contents
I: Saving the results, modifications to this session will persist
I: unmounting /var/cache/pbuilder/ccache filesystem
I: unmounting dev/pts filesystem
I: unmounting proc filesystem
I: creating base tarball [/var/cache/pbuilder/base.tgz]
I: cleaning the build env
I: removing directory /var/cache/pbuilder/build//27657 and its subdirectories
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=GSRiULCqFOg:CCChs0CSnwM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=GSRiULCqFOg:CCChs0CSnwM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=GSRiULCqFOg:CCChs0CSnwM:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=GSRiULCqFOg:CCChs0CSnwM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=GSRiULCqFOg:CCChs0CSnwM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=GSRiULCqFOg:CCChs0CSnwM:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/11/15/instalando-dependencias-no-libres-de-java-en-ambientes-pbuilder/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/11/15/instalando-dependencias-no-libres-de-java-en-ambientes-pbuilder</feedburner:origLink></item>
		<item>
		<title>Presentaciones</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/TjoFir5dguI/presentaciones</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/11/13/presentaciones#comments</comments>
		<pubDate>Sat, 13 Nov 2010 08:08:53 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[beamer]]></category>
		<category><![CDATA[canaima]]></category>
		<category><![CDATA[dbconfig-common]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[gnupg]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[presentaciones]]></category>
		<category><![CDATA[pylint]]></category>
		<category><![CDATA[trac]]></category>
		<category><![CDATA[turpial]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=312</guid>
		<description><![CDATA[Desde hace algunos meses he decidido recopilar y organizar algunas de las presentaciones que he dado hasta ahora en eventos de Software Libre, Universidades y empresas privadas. El software que regularmente utilizo para realizar mis presentaciones es Beamer, una clase &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/11/13/presentaciones">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Desde hace algunos meses he decidido recopilar y organizar algunas de las presentaciones que he dado hasta ahora en eventos de <em>Software Libre</em>, Universidades y empresas privadas.</p>
<p>El software que regularmente utilizo para realizar mis presentaciones es <a href="http://latex-beamer.sourceforge.net/" title="Latex Beamer">Beamer</a>, una clase <a href="http://www.latex-project.org/">LaTeX</a> que facilita enormente la producción de presentaciones de alta calidad, este software trabaja de la mano con <code>pdflatex</code>, también con <code>dvips</code>.</p>
<p>La lista de presentaciones que he recopilado hasta la fecha son las siguientes:</p>
<dl>
<dt><a href="http://www.slideshare.net/milmazz/pylint" title="Pylint">Análisis estático del código fuente en Python</a></dt>
<dd>Se describe el concepto del análisis estático del código, se indica los pasos a seguir para la detección de errores mediante la herramienta <em>Pylint</em>, se exponen sus funcionalidades, reportes y se muestran ejemplos para corregir los errores encontrados por la herramienta.</dd>
<dt><a href="http://www.slideshare.net/milmazz/desarrollo-colectivo-en-turpial" title="Turpial">Desarrollo colectivo en Turpial</a></dt>
<dd>Se describe la visión del cliente para Twitter Turpial, sus funcionalidades actuales, el uso de herramientas como <em>Transifex</em>, <em>PyBabel</em>, <em>Distutils</em>, <em>Sphinx</em>, dichas herramientas facilitan y mejoran la calidad del software que se desarrolla.</dd>
<dt><a href="http://www.slideshare.net/milmazz/canaima-gnulinux">Canaima GNU/Linux</a></dt>
<dd>Una introducción, se describe la historia, definición del proyecto Canaima, principales características, procesos para colaborar, enlaces de interés, entre otros.</dd>
<dt><a href="http://www.slideshare.net/milmazz/proyecto-maestro-virtual-novela-grfica-creada-con-el-motor-renpy">Novela gráfica creada con el motor Ren&#8217;Py</a></dt>
<dd>Se relata la experiencia del desarrollo de una novela gráfica para niños de 5to. grado de educación, de acuerdo a currículo impartido en las escuelas venezolanas.</dd>
<dt><a href="http://www.slideshare.net/milmazz/trac-3717222" title="Trac">Trac</a></dt>
<dd>Herramientas libres para el apoyo en el proceso de desarrollo de software, se discute las características y funcionalidades que ofrece el software. Además del proceso de personalización por medio de complementos o plugins.</dd>
<dt>GnuPG, GNU Privacy Guard</dt>
<dd>Importancia del cifrado de la información, diferencias entre llaves simétricas y asimétricas, criptografía, fiestas de firmado de llaves, beneficios. Instalación y suo práctico de GnuPG.</dd>
<dt>Uso de <code>dbconfig-common</code></dt>
<dd>Presentación que es parte de la serie mejores prácticas para el empaquetamiento de aplicaciones en Debian, se describe el uso de la herramienta y su respectiva integración con el asistente debhelper</dd>
<dt>Conociendo el framework web Django</dt>
<dd>Introducción, historia, características, primeros pasos, instalación y demostración de desarrollo de una aplicación sencilla bajo este excelente framework basado en el lenguaje de Programación Python</dd>
</dl>
<p>Las fuentes en LaTeX de las presentaciones, así como su licencia de uso y proceso de conversión al formato PDF se describe en el proyecto <a href="https://github.com/milmazz/Presentations" title="Presentaciones">Presentations</a> que he creado en <a href="http://www.github.com/" title="github">github</a>.</p>
<p>Agradezco enormemente cualquier comentario que pueda hacer respecto a los temas presentados puesto que en el próximo mes trataré de actualizar el contenido, así como incluir nuevas presentaciones. ¿Desearía poder conocer más sobre un tema en particular?, ¿cuál sería ese tema?.</p>
<p><strong>Nota final</strong>: Si encuentra algún <strong>error</strong> por favor notificarlo vía <a href="https://github.com/milmazz/Presentations/issues">issues</a> del proyecto <a href="https://github.com/milmazz/Presentations" title="Presentaciones">Presentations</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=TjoFir5dguI:fppKtqVeaEo:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=TjoFir5dguI:fppKtqVeaEo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=TjoFir5dguI:fppKtqVeaEo:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=TjoFir5dguI:fppKtqVeaEo:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=TjoFir5dguI:fppKtqVeaEo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=TjoFir5dguI:fppKtqVeaEo:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/11/13/presentaciones/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/11/13/presentaciones</feedburner:origLink></item>
		<item>
		<title>Mejoras en el comportamiento a la hora de eliminar un ForeignKey</title>
		<link>http://feedproxy.google.com/~r/milmazz/blog/~3/Hrp6i1WCGYw/mejoras-en-el-comportamiento-a-la-hora-de-eliminar-un-foreignkey</link>
		<comments>http://blog.milmazz.com.ve/archivos/2010/11/09/mejoras-en-el-comportamiento-a-la-hora-de-eliminar-un-foreignkey#comments</comments>
		<pubDate>Wed, 10 Nov 2010 00:21:35 +0000</pubDate>
		<dc:creator>milmazz</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://blog.milmazz.com.ve/?p=313</guid>
		<description><![CDATA[Cuando un objeto referenciado por una clave foránea (ForeignKey) es eliminado, Django por omisión emula el comportamiento de la sentencia SQL ON DELETE CASCADE y también se elimina el objeto que contiene el ForeignKey. A partir de la versión 1.3 &#8230; <a href="http://blog.milmazz.com.ve/archivos/2010/11/09/mejoras-en-el-comportamiento-a-la-hora-de-eliminar-un-foreignkey">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.milmazz.com.ve/wp-content/uploads/2010/11/djangove.png"><img class="alignleft size-full wp-image-315" src="http://blog.milmazz.com.ve/wp-content/uploads/2010/11/djangove.png" alt="Logo de Django " width="250" height="87" /></a> Cuando un objeto referenciado por una clave foránea (<code>ForeignKey</code>) es eliminado, <a href="http://www.djangoproject.com">Django</a> por omisión emula el comportamiento de la sentencia SQL <code>ON DELETE CASCADE</code> y también se elimina el objeto que contiene el <em>ForeignKey</em>.</p>
<p>A partir de la versión 1.3 de Django el comportamiento descrito en el párrafo anterior puede ser sobreescrito al especificar el argumento <code>on_delete</code>. Por ejemplo, si usted permite que una clave foránea pueda ser <em>nula</em> y usted desea que sea establecida a <code>NULL</code> cuando un objeto referenciado sea eliminado:</p>
<pre class="brush: python; light: true; title: ; notranslate">
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
</pre>
<p>Los posibles valores para el argumento <code>on_delete</code> pueden encontrarse en django.db.models:</p>
<dl>
<dt>CASCADE</dt>
<dd>Eliminación en cascada, el comportamiento por omisión.</dd>
<dt>PROTECT</dt>
<dd>Prevee la eliminación del objeto referenciado al lanzar una excepción del tipo: <code>django.db-IntegrityError</code>.</dd>
<dt>SET_NULL</dt>
<dd>Establece la clave foránea a <code>NULL</code>, esto solo es posible si el argumento <code>null</code> es <code>True</code>.</dd>
<dt>SET_DEFAULT</dt>
<dd>Establece la clave foránea a su valor por omisión, tenga en cuenta que un valor por omisión debe ser establecido.</dd>
<dt>SET()</dt>
<dd>Establece el valor del <code>ForeignKey</code> indicado en <code>SET()</code>, si una función es invocada, el resultado de dicha función será el valor establecido.</dd>
<dt>DO_NOTHING</dt>
<dd>No tomar acciones. Si el gestor de base de datos requiere integridad referencial, esto causará una excepción del tipo <code>IntegrityError</code>.</dd>
</dl>
<p>A continuación un par de ejemplos de esta nueva funcionalidad:</p>
<pre class="brush: python; title: ; notranslate">
# models.py
from django.db import models

class Author(models.Model):
    nickname = models.CharField(max_length=32)

    def __unicode__(self):
        return self.nickname

class Post(models.Model):
    author = models.ForeignKey(Author, blank=True, null=True, on_delete=models.SET_NULL)
    title = models.CharField(max_length=128)

    def __unicode__(self):
        return self.title
</pre>
<p>Nuestra sesión interactiva con el API sería similar a la siguiente:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
$ python manage.py shell
</pre>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; from ondelete.models import Author, Post

&gt;&gt;&gt; Author.objects.all()
[]
# Creamos el autor
&gt;&gt;&gt; author = Author(nickname='milmazz')
# Guardamos el objeto en la base de datos al usar de manera explícita el método save()
&gt;&gt;&gt; author.save()

# Obtenemos el autor en base a su id
&gt;&gt;&gt; Author.objects.get(pk=1)
&lt;Author: milmazz&gt;

# Creamos par de artículos
&gt;&gt;&gt; article1 = Post(author=author, title=&quot;Article 1&quot;)
&gt;&gt;&gt; article1.save()

&gt;&gt;&gt; article2 = Post(author=author, title=&quot;Article 2&quot;)
&gt;&gt;&gt; article2.save()

&gt;&gt;&gt; for article in Post.objects.all():
     print(&quot;%s by %s&quot; % (article.title, article.author))
Article 1 by milmazz
Article 2 by milmazz

# Eliminamos el autor
&gt;&gt;&gt; author.delete()

&gt;&gt;&gt; for article in Post.objects.all():
    print(&quot;%s by %s&quot; % (article.title, article.author))
Article 1 by None
Article 2 by None
</pre>
<p>Un segundo ejemplo, ahora haciendo uso del valor <code>SET()</code> en el argumento <code>on_delete</code>:</p>
<pre class="brush: python; title: ; notranslate">
# models.py
from django.db import models
from django.contrib.auth.models import User

def get_superuser():
    return User.objects.get(pk=1)

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET(get_superuser))
    title = models.CharField(max_length=128)

    def __unicode__(self):
        return self.title
</pre>
<p>Nuestra sesión interactiva con el API sería similar a la siguiente:</p>
<pre class="brush: powershell; light: true; title: ; notranslate">
$ python manage.py shell
</pre>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; from ondelete.models import Post
&gt;&gt;&gt; from django.contrib.auth.models import User

&gt;&gt;&gt; User.objects.all()
[&lt;User: milmazz&gt;]
# Creamos un nuevo usuario
&gt;&gt;&gt; author = User(username='milton')
# Guardamos el objeto en la base de datos,
# de manera explícita al invocar el método save()
&gt;&gt;&gt; author.save()
# Vista de los usuarios registrados en la base de datos
&gt;&gt;&gt; User.objects.all()
[&lt;User: milmazz&gt;, &lt;User: milton&gt;]

# Creamos par de artículos
&gt;&gt;&gt; article1 = Post(user=author, title=&quot;Article 1&quot;)
&gt;&gt;&gt; article1.save()

&gt;&gt;&gt; article2 = Post(user=author, title=&quot;Article 2&quot;)
&gt;&gt;&gt; article2.save()

&gt;&gt;&gt; for article in Post.objects.all():
     print(&quot;%s by %s&quot; % (article.title, article.user))
Article 1 by milton
Article 2 by milton

# Eliminamos el usuario 'milton'
&gt;&gt;&gt; author.delete()

&gt;&gt;&gt; for article in Post.objects.all():
    print(&quot;%s by %s&quot; % (article.title, article.user))
Article 1 by milmazz
Article 2 by milmazz
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=Hrp6i1WCGYw:dqMnv-iLE90:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=Hrp6i1WCGYw:dqMnv-iLE90:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=Hrp6i1WCGYw:dqMnv-iLE90:-BTjWOF_DHI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=Hrp6i1WCGYw:dqMnv-iLE90:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/milmazz/blog?a=Hrp6i1WCGYw:dqMnv-iLE90:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/milmazz/blog?i=Hrp6i1WCGYw:dqMnv-iLE90:gIN9vFwOqvQ" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.milmazz.com.ve/archivos/2010/11/09/mejoras-en-el-comportamiento-a-la-hora-de-eliminar-un-foreignkey/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.milmazz.com.ve/archivos/2010/11/09/mejoras-en-el-comportamiento-a-la-hora-de-eliminar-un-foreignkey</feedburner:origLink></item>
	</channel>
</rss>

