<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8587897704769639737</id><updated>2012-02-16T11:21:31.182-08:00</updated><category term='AOP'/><category term='red'/><category term='POI'/><category term='debugging'/><category term='web'/><category term='servidores'/><category term='seguridad'/><category term='pojo'/><category term='junit'/><category term='maven'/><category term='desarrollo'/><category term='presto'/><category term='IDE'/><category term='sed'/><category term='pruebas unitarias'/><category term='arquitectura'/><category term='excel'/><category term='js'/><category term='shell'/><category term='python'/><category term='planning'/><category term='spring'/><category term='email'/><category term='windows'/><category term='metodología'/><category term='jasper'/><category term='mashup'/><category term='autowiring'/><category term='xp'/><category term='apache'/><category term='linux'/><category term='escritorio remoto'/><category term='xml'/><category term='hibernate'/><category term='virtualbox'/><category term='JBoss'/><category term='dbunit'/><category term='hdd'/><category term='datos'/><category term='jsf'/><category term='mysql'/><category term='java'/><category term='php'/><category term='ajax'/><category term='programming'/><category term='programacion'/><category term='dataset'/><category term='xtreme programming'/><category term='book'/><category term='jackbe'/><category term='pdf'/><category term='log4j'/><category term='inalámbrica'/><category term='report'/><category term='annotation'/><category term='unix'/><category term='patrones'/><category term='comando'/><category term='framework'/><category term='testing'/><category term='designing'/><category term='anotacion'/><category term='mapeo'/><title type='text'>micro - How To</title><subtitle type='html'>&amp;lt;-- Where was that issue / code / bug / whatever ? It&amp;#39;s not a match 4 me ! --&amp;gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>64</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-6281377440402179340</id><published>2011-01-31T12:44:00.000-08:00</published><updated>2011-01-31T12:48:31.105-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='anotacion'/><category scheme='http://www.blogger.com/atom/ns#' term='autowiring'/><title type='text'>Autowiring basado en anotaciones con Spring Framework</title><content type='html'>Autowiring se un método que tiene Spring Framework para inyectar de forma automática las dependencias entre clases (servicios, daos, controllers, etc). &lt;br /&gt;Para cada DAO, agrega una anotación de nivel clase &lt;b&gt;@Repository&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Estas anotaciones van en la clase de implementación y no en la intefaz.&lt;br /&gt;import org.sringframework.stereotype.Repository;&lt;br /&gt;&lt;pre class="brush:java;"&gt;@Repository("parametroDao")&lt;br /&gt;public class ParametroDaoImpl implements ParametroDao {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Para cada componente Servicio, agrega una anotacion de nivel clase &lt;b&gt;@Service&lt;/b&gt;.&lt;br /&gt;import org.springframework.stereotype.Service;&lt;br /&gt;&lt;pre class="brush:java;"&gt;@Service("parametroService")&lt;br /&gt;public class ParametroServiceImpl implements ParametroService {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Para cada controller en Spring MVC, agrega una anotacion de nivel clase &lt;b&gt;@Controller&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;No te preocupes de proveer el nombre, no se necesita.&lt;br /&gt;import org.springframework.stereotype.Controller;&lt;br /&gt;&lt;pre class="brush:java;"&gt;@Controller&lt;br /&gt;public class ParametroServiceImpl implements ParametroController {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Hasta ahora no se ha cambiado nada a la aplicación, se pueden seguir teniendo los nombres de beans usados en la configuración manual, pero es recomendable compilar y construir el proyecto para revisar que no se haya afectado algo.&lt;br /&gt;&lt;br /&gt;Una vez hecho lo anterior, hay que decirle a Spring dos cosas: dónde encontrar los nombres para nuestros beans y que estrategia usar para el autowiring.&lt;br /&gt;&lt;br /&gt;Para definir donde encontrar los nombres de beans debemos usar el tag &amp;lt;context:component-scan&amp;gt; en el archivo de configuración del contexto de Spring.&amp;nbsp; Se debe declarar el namespace y schema location:&lt;br /&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;beans xmlns="&lt;a href="http://www.springframework.org/schema/beans"&gt;http://www.springframework.org/schema/beans&lt;/a&gt;"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/a&gt;"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:context="&lt;a href="http://www.springframework.org/schema/context"&gt;http://www.springframework.org/schema/context&lt;/a&gt;"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xsi:schemaLocation="&lt;a href="http://www.springframework.org/schema/aop"&gt;http://www.springframework.org/schema/aop&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;http://www.springframework.org/schema/aop/spring-aop-3.0.xsd&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/beans"&gt;http://www.springframework.org/schema/beans&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"&gt;http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/context"&gt;http://www.springframework.org/schema/context&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;http://www.springframework.org/schema/context/spring-context-3.0.xsd&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/jee"&gt;http://www.springframework.org/schema/jee&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"&gt;http://www.springframework.org/schema/jee/spring-jee-3.0.xsd&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/tx"&gt;http://www.springframework.org/schema/tx&lt;/a&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;a href="http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"&gt;http://www.springframework.org/schema/tx/spring-tx-3.0.xsd&lt;/a&gt;"&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;context:component-scan base-package="x.y.dao"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;context:include-filter type="annotation"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression="org.springframework.stereotype.Repository"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/context:component-scan&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Las piezas importantes del xml anterior son &lt;span style="background-color: #ffff99;"&gt;xmlns:context&lt;/span&gt;, &lt;span style="background-color: #ffff99;"&gt;xsi_schemaLocation&lt;/span&gt; y &lt;span style="background-color: #ffff99;"&gt;&amp;lt;context:component-scan&amp;gt;&lt;/span&gt;.&amp;nbsp; Se le está diciendo a Spring que haga un escaneo (búsqueda) de componentes que tengan la aotación @Repository sobre el paquete x.y.dao y si a la anotacion usada se le coloca un valor textual, como en en nuestros casos anteriores del @Repository y el @Service, ése será el nombre a utlilizar como bean para el autowiring&lt;br /&gt;&lt;br /&gt;Con la anotacion @Autowired aplicada a los atributos de las clases, se pueden evitar tener setters de dicho atributo, pero si tienes clases unitarias, necesitaríamos setter para inyectar mocks u otras implementaciones.&lt;br /&gt;&lt;br /&gt;La convención es utilizar, como nombres de las propiedades que se pretende auto-inyectar, los mismos nombre del componente, lo cual nos permite eliminar los componentes Dao, Service y Controller del archivo de configuracion del contexto de Spring (xml) dado que la configuración ya se está dando en la misma clasa, mediante las anotaciones.&lt;br /&gt;&lt;br /&gt;No obstante, sigue siendo recomendable configurar dentro del XML los objetos DataSource (la configuración del orígen de datos, es decir, la Base de Datos), SessionFactory (Hibernate o algún otro ORM) y TransactioManager (Para el control de las transacciones).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-6281377440402179340?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/6281377440402179340/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2011/01/autowiring-basado-en-anotaciones-con.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6281377440402179340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6281377440402179340'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2011/01/autowiring-basado-en-anotaciones-con.html' title='Autowiring basado en anotaciones con Spring Framework'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-1943133448482837756</id><published>2011-01-04T09:49:00.000-08:00</published><updated>2011-01-31T12:40:41.478-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='pdf'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Referencia del entorno de programación en Unix</title><content type='html'>Resulta que recomendando un libro sobre programación en Unix, me encontré con esta referencia que puedes descargar desde el mediafire.com :&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;a href="http://www.mediafire.com/?hf3zzzmdwt3"&gt;http://www.mediafire.com/?hf3zzzmdwt3&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Como referencia me pareció bastante buena, se las dejo para quien guste descargarla y si en algún momento el enlace está roto, me avisan para ver como repararlo.&lt;br /&gt;&lt;br /&gt;Referencias:&lt;br /&gt;======================= &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.diazdesantos.es/libros/kernighan-brian-w-el-entorno-de-programacion-unix-L0000474300078.html"&gt;&lt;span style="color: #0b5394;"&gt;El entorno de programación UNIX&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: #0b5394;"&gt;Kernighan, Brian W.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0b5394;"&gt;Pike, Rob&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0b5394;"&gt;Editorial Pearson&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Del &lt;a href="http://www.tic.udc.es/%7Efbellas/"&gt;autor del PDF&lt;/a&gt; (Fernando Bellas Permuy).&lt;/li&gt;&lt;li&gt;Descargar capítulos del libro de Kerninghan &lt;a href="http://libros-en-pdf.com/libros/el-entorno-de-programacion-unix.html"&gt;aquí&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-1943133448482837756?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/1943133448482837756/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2011/01/referencia-del-entorno-de-programacion.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1943133448482837756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1943133448482837756'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2011/01/referencia-del-entorno-de-programacion.html' title='Referencia del entorno de programación en Unix'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4153547164214150165</id><published>2011-01-04T08:44:00.000-08:00</published><updated>2011-01-04T08:45:38.507-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comando'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='programacion'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='sed'/><title type='text'>Manual de introducción al comando sed</title><content type='html'>&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Se trata de un editor de cadenas, que deriva directamente del comando ed, por lo cual es fácil de aprender, una vez conocido el propio comando ed.&amp;nbsp; Un editor de cadenas es usado para realizar transformaciones de texto básicas de una cadena de entrada (un archivo o la salida de un pipe). A diferencia de otros editores comunes, sed hace solo una revisión sobre cada entrada, por lo cual es mas eficiente, en especial lo es, cuando filtra texto que pasa por una unión pipe.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Cuando sed filtra un archivo, no altera su contenido, todos los cambios los realiza sobre la salida que imprime. Sed despliega cada renglón automáticamente y por ello &lt;b&gt;p&lt;/b&gt; no se necesita después del comando de sustitución (&lt;b&gt;s&lt;/b&gt;, por ejemplo &lt;b&gt;s/old/new/&lt;/b&gt;). Las comillas son indispensables pues existen metacaracters de sed que tienen significado especial para el shell sobre el cual se ejecuta.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;El comando sed tiene una limitación que no se encuentra en ed: no maneja números relativos de renglón. En particular, + y - no son entendidos como expresiones para indicar números de renglón, por lo cual resulta imposible de retroceder a uno o mas renglones anteriores o hacer direccionamientos relativos hacia adelante. Esto se debe a que una vez leído un renglón, el anterior se pierde para siempre; no hay manera de identificar el penúltimo renglón.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;En la lista de comandos puede existir cualquiera de los listados más adelante. Cuando se hace uso de uno solo, basta con encerrarlo entre comillas simples como sigue:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/old/new/' archivo&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Pero en el caso de que necesitemos ejecutar varios comandos sobre un mismo archivo, es necesario que estos se encuentren en diferentes lineas, por ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/^/ /&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;3q' archivo&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;No hay que olvidar que antes de escribir el primer comando, se deben abrir las comillas simples y las mismas se deben cerrar después de teclear el último comando. También es posible almacenar los comandos dentro de un archivo y llamarlo a la hora de que se ejecute sed con el parámetro -f.&amp;nbsp; Por ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed -f cmdarchivo archivo_texto&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Se pueden utilizar otros selectores o patrones antes de cada comando, por ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/patron/q'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Imprime cada linea de archivo hasta encontrar aquella que contenga el patron&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/patron/d'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Cancela todas las lineas que contengan el patron y no se imprimen&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Incluso si se desea el resultado inverso a lo que realiza un comando, basta con agregar un &lt;b&gt;'!'&lt;/b&gt; antes&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;del comando. Por ejemplo, para los dos ejemplos anteriores se prosigue como sigue:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/patron/!q'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;No imprime c/línea de archivo hasta encontrar aquella que contenga el patron&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/patron/!d'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;No cancela todas las lineas que contengan el patron y no se imprimen&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Sintaxis&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;La sintaxis de sed es la siguiente&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;i&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;i&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; [-n] [-V] [--quiet] [--silent] [--version] [--help]&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;[-e script] [--expression=script]&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;[-f script-file] [--file=script-file]&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;[script-if-no-other-script]&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;[file...]&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-----------------------------------------------------------------------------------------------&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-V ó --version&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Imprime la versiòn de sed y nota de copyright.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-h ó --help&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Imprime un resumen de todas las opciones de sed.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-n ó --quiet ó --silent&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Por defecto, sed imprime cada linea cuando termina de editarla. Esta opciòn deshabilita la impresiòn automàtica y no se produce ninguna salida, excepto que se incluya el comando p.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-e script ó --expression=script&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Agrega los comandos de la cadena script, encerrada entre comillas simples, a la lista de comandos para ser ejecutados mientras se procesa la entrada. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;-f script-file ó --file=script-file&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Agrega los comandos contenidos en el archivo script para ser procesados sobre la entrada.&amp;nbsp; Si ninguno de los dos parámetros anteriores es utilizado, en cualquiera de sus formas, sed tomará como comandos la primer expresión que no sea opción de sed como argumento para ejecutar como si fuera script.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Comandos ================================================&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;A continuación se presenta una lista de comandos que se pueden utilizar para filtrar una entrada con sed, así mismo se incluyen algunos ejemplos para una mayor comprensión.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Sustitución **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Su función es sustituir una cadena old por una nueva new en cada linea que procese. Su sintaxis&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;es la siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;s/old/new/&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/casa/carro/'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&lt;b&gt; contrato.txt&lt;/b&gt; &lt;i&gt;Sustituye la cadena 'casa' por 'carro' en contrato.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/^/.-/' arch.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Agrega la cadena '.-' al inicio de cada linea de arch.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/^/\&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/' arch.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Agrega un salto de linea al final de cada linea de arch.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Otro comando que puede ser útil es y, el cual remplaza cada caracter procedente de old con el caracter correspondiente proveniente de new. Aqui no se admiten rangos. Su sintaxis es:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;y/old/new/&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Borrado **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Su función es borrar a la salida, las lineas que correspondan al patrón escrito. Su sintaxis es la&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/patron/d&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/calvo/d' arch.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Elimina las lineas que contienen la cadena 'calvo' en arch.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/amor/!d' carta.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Elimina las lineas que no tengan la palabra amor en carta.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '3d' forma.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Elimina la linea 3 del archivo forma.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Impresión **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Su función es imprimir la salida de sed. En realidad, sed imprime automáticamente la entrada filtrada, entonces si se agrega el comando &lt;b&gt;p&lt;/b&gt;, cada linea de salida se imprimirá doble. En caso de que se agregue el parámetro -n a sed, pero se quiera imprimir la salida, se agrega el comando p. Su sintaxis es la siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/patron/p&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;who | sed -n '/root/p'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Imprime solamente las sesiones de root&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;who | sed '/root/p'&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Imprime dos veces cada sesion abierta de root&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;who | sed -n '2p'&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; Imprime solamente la segunda sesion que se inició en el sistema&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Abandonar filtrado **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Otro comando útil para imprimir una parte de la entrada es q. Este comando termina inmediatamente las operaciones de sed, en base a la correspondencia del patrón con las líneas que este procesando. Su sintaxis es la siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/patron/q&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '3q' forma.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Imprime hasta la linea 3 del archivo forma.txt&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/clavo/q' arch.txt&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; &lt;i&gt;Imprime desde la línea 1 de arch.txt hasta encontrar aquella que contiene la palabra 'clavo'.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Inserción de texto **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Este comando inserta o agrega texto a cada línea que procesa sed. El texto debe estar localizado&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;en las siguientes lineas que proceden después del caracter '\'. Su sintaxis es la siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;i \ y a\&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;[ texto a agregar ]&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 'i \&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;.' oraciones.txt&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; Agrega un punto final a cada linea de oraciones.txt&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 'a \&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;' doble.txt&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt; Agrega un salto de linea al final de cada linea de doble.txt&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Guardar la entrada filtrada en un archivo **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Este comando permite salvar la entrada filtrada en otro archivo. Su sintaxis es la siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/patron/w archivo&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Ejemplo:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed '/pat/w patos.txt&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/pat/!w otros.txt animales.txt&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Guarda las lineas que concuerden con 'pat' en un archivo llamado patos.txt y los que no&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;concuerden en el archivo otros.txt&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span lang="EN-US" style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed 's/UNIX/UNIX(TM)/gw u.out' libros.txt &amp;gt; salida.out&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Almacena toda la salida en el archivo salida.out, pero las líneas que fueron modificadas, se&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;almacenan en u.out&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Funciones =================================================&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Etiqueta **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Permite identificar una etiqueta label, si se realiza un cambio en la línea actual. Esta es&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;especificada por ':' y seguida del nombre de la etiqueta. Su sintaxis es como sigue:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;: label&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Grupo **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Indica un grupo de comandos, que inicia con un carácter '{' y termina con un '}'.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Lectura de archivos **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Con el comando &lt;b&gt;r&lt;/b&gt;, lee un archivo y agrega todo su contenido al final de cada línea de entrada de&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;sed. Su sintaxis es:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;nr archivo&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;, donde n es el número de línea donde pegar el texto de archivo.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Listar línea **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;El comando es &lt;b&gt;l&lt;/b&gt; y su función es hacer visibles todos los caracteres no imprimibles de cada línea de&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;entrada.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Linea actual **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Se puede imprimir el número de la línea actual, si se agrega el comando '='. Su sintaxis es:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;/patron/=&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;&amp;nbsp;** Salto **&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Permite saltar o ir a la línea donde se encuentra una etiqueta label definida y continuar la ejecución&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;de sed desde ese comando. Su sintaxis es:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;b label&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Conclusión sobre los usos de sed. ==========================================&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;En realidad sed tiene bastante utilidad como la comprobación de condiciones, creación de ciclos y ramificaciones, retención de líneas precedentes y muchos de los comandos de ed. Su uso es&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;similar al que se ha descrito en este manual, comandos sencillos de edición y no tanto de&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;secuencias largas o complejas.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;Sed es adecuado para manejar entradas arbitrariamente grandes de forma rápida, pero ofrece una&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;forma bastante reducida de memoria, puesto que al filtrar una siguiente línea, ya no recuerda la&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;anterior, por lo que no se puede regresar a filtrar la anterior y tampoco proporciona recursos para&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 10pt;"&gt;manipular números. &lt;i&gt;&lt;u&gt;Solo es un editor de texto&lt;/u&gt;&lt;/i&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4153547164214150165?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4153547164214150165/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2011/01/manual-de-introduccion-al-comando-sed.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4153547164214150165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4153547164214150165'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2011/01/manual-de-introduccion-al-comando-sed.html' title='Manual de introducción al comando sed'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4403195221680375226</id><published>2010-12-16T11:22:00.000-08:00</published><updated>2010-12-16T11:25:38.788-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>debugging remoto de scripts Python con winpdb</title><content type='html'>Usando el programa winpdb se pueden debuggear scripts en Python de manera mas intuitiva que con el clásico pdb.&lt;br /&gt;&lt;br /&gt;Una de las ventajas que tiene winpdb es la posibilidad de debuggear scripts que esten ejecutandose en remoto en algun servidor. De esta manera, se pueden debuggear no solo scripts en servidores de producción, por poner un ejemplo, sino también scripts que utilicen curses para manipular la pantalla.&lt;br /&gt;&lt;br /&gt;winpdb se basa en una arquitectura de cliente-servidor que comunica al servidor (el cual ejecuta el script a debuggear en sí) a través de sockets con el cliente (el cual ejecuta la interfaz del debugger).&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;winpdb cuenta con dos programas para poder hacer el debuggeo:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;rpdb2 - que es la interfaz de consola o modo texto, y que puede ser usada como servidor del debugger también.&lt;/li&gt;&lt;li&gt;winpdb - que es la interfaz gráfica&lt;/li&gt;&lt;/ul&gt;Para debuggear un script en remoto, hay que ejecutar lo siguiente en el servidor:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; screen rpdb2 -s -d -r script.py&lt;/blockquote&gt;&lt;br /&gt;El cual utiliza el programa 'screen' para tener la salida del script python a debuggear en una pantalla dedicada.&lt;br /&gt;&lt;br /&gt;El parámetro -s se usa en conjunto con screen.&lt;br /&gt;&lt;br /&gt;El parámetro -d le indica a rpbd2 que se ejecute en modo servidor solamente, esperando a que algún cliente se conecte para poder hacer el debuggeo.&lt;br /&gt;&lt;br /&gt;El parámetro -r permite conexiones remotas.&lt;br /&gt;&lt;br /&gt;script.py es simplemente el path y nombre del script a debuggear.&lt;br /&gt;&lt;br /&gt;Al ejecutar esta línea, el programa rpdb2 solicitará un password que deberá introducir el cliente también, y con eso asegurar la comunicación entre el cliente y el servidor.&lt;br /&gt;&lt;br /&gt;Hecho esto, rpdb2 queda en espera de alguna conexión.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En el lado del cliente, se puede ejecutar rpdb2 para debuggear con la consola, o si se prefiere winpdb para hacerlo con una interfaz gráfica:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;winpdb -oserverhost -a script.py&lt;/blockquote&gt;&lt;br /&gt;El parámetro -o va seguido de la dirección IP o nombre del servidor&lt;br /&gt;&lt;br /&gt;El parámetro -a le indica a winpdb que al conectarse al servidor, adjunte el script script.py que se debe estar ya ejecutando en el servidor para poder debuggear con rpdb2.&lt;br /&gt;&lt;br /&gt;Hecho esto, se solicitará el password que se indicó en rpdb2 y con eso la interfaz inicializará y conectará con el servidor y cargará el código fuente del script solicitado, con lo que ya puede comenzar a debuggearse...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Links:&lt;br /&gt;&lt;a href="http://winpdb.org/"&gt;winpdb&lt;/a&gt; - sitio oficial de winpdb, con el código fuente del programa, para instalarlo, y documentación.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4403195221680375226?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4403195221680375226/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/12/debugging-remoto-de-scripts-python-con.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4403195221680375226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4403195221680375226'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/12/debugging-remoto-de-scripts-python-con.html' title='debugging remoto de scripts Python con winpdb'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4245415715650752681</id><published>2010-12-03T12:17:00.000-08:00</published><updated>2010-12-03T12:29:56.947-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='excel'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='POI'/><title type='text'>Configurar POI en Spring 3 para generar archivos Excel</title><content type='html'>He decidido registrar el proceso de como generar archivos Excel con POI mediante Spring 3 para que no se me olvide (aunque es bastante sencillo).  &lt;font size="1"&gt;&lt;i&gt;Me sorprendí de terminarlo en tan sólo 3 pasos!&lt;/i&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) Generar un controller &lt;/b&gt;que obtiene los valores que se pretenden mostrar en la vista, los agrega al modelmap de MVC que maneja Spring y luego devuelva el nombre de la vista encargada de generar el excel.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java;"&gt;@Controller&lt;br /&gt;@RequestMapping(&amp;quot;/excel&amp;quot;)&lt;br /&gt;public class ExcelController {&lt;br /&gt;&lt;br /&gt;    @Autowired&lt;br /&gt;    private Servicio servicio;&lt;br /&gt;&lt;br /&gt;    @RequestMapping(value = &amp;quot;/{parametro}&amp;quot;, method = RequestMethod.GET)&lt;br /&gt;    public String generarExcelByParametro(&lt;br /&gt;            ModelMap modelMap, HttpServletResponse response,&lt;br /&gt;            @PathVariable(&amp;quot;parametro&amp;quot;) String nombreVista) {&lt;br /&gt;        modelMap.put(&amp;quot;datos&amp;quot;, servicio.obtenerDatos(parametro));&lt;br /&gt;&lt;br /&gt;        response.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/vnd.ms-excel&amp;quot;);&lt;br /&gt;        response.setHeader(&amp;quot;Content-Disposition&amp;quot;,&amp;quot;attachment; filename=\&amp;quot;excel.xls\&amp;quot;&amp;quot;);&lt;br /&gt;        return &amp;quot;reporteExcel&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Observa que el método generarExcelByParametro() del controller responde a una petición http://{servidor:puerto}/{contexto}/excel/{parametro} y realiza algo en un servicio que devuelve cierta información que se espera administrar de lado de la vista (más adelante lo vemos) y lo guarda dentro del ModelMap de spring con el identificador &amp;quot;datos&amp;quot;.&lt;br /&gt;&lt;br /&gt;Los headers que se agregan al response, son solo para asegurar que cuando se genere el archivo .xls, se identifique como tal y se obligue al usuario a descargarlo.&lt;br /&gt;&lt;br /&gt;Finalmente la cadena (&amp;quot;reporteExcel&amp;quot;) que se devuelve determina el nombre de la vista que interpretara los datos para generar el documento.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;2) Configurar la vista&lt;br /&gt;&lt;/b&gt;Es necesario generar un archivo de nombre &lt;i&gt;views.properties&lt;/i&gt; o agregar al que ya exista en el classpath del proyecto, algo como lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:text;"&gt;reporteExcel.(class)=mx.com.empresa.miproyecto.web.view.ExcelView&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La linea comienza con el nombre de la vista, que es el nombre de la cadena que se devuelve en el controller; no olviden encerrar el .class entre paréntesis.  La clase (junto con el paquete) que se asigna como valor indica la ubicacion de la View (o vista), misma que interpretará los datos y los plasmará sobre el Excel.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3) Generar la View (vista)&lt;/b&gt; que interpreta los datos del controller.  Se debe generar una clase que herede de &lt;i&gt;org.springframework.web.servlet.view.document.AbstractExcelView&lt;/i&gt; e implemente el metodo &lt;i&gt;buildExcelDocument()&lt;/i&gt;. En dicho método es donde se debe recuperar los datos que se involucraron en el ModelMap desde el controller.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java;"&gt;public class ExcelView extends AbstractExcelView {&lt;br /&gt;    @Override&lt;br /&gt;    protected void buildExcelDocument(&lt;br /&gt;            Map&amp;lt;String, Object&amp;gt; model, HSSFWorkbook book,&lt;br /&gt;            HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;            throws Exception {&lt;br /&gt;        //recuperar datos&lt;br /&gt;        List reporte = (List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;) model.get(&amp;quot;datos&amp;quot;);&lt;br /&gt;        //crear la hoja&lt;br /&gt;        HSSFSheet hoja = book.createSheet(&amp;quot;nombre de la hoja&amp;quot;);&lt;br /&gt;&lt;br /&gt;        //generar un estilo para la celda&lt;br /&gt;        HSSFCellStyle estiloCelda = obtenerEstiloCelda(book);&lt;br /&gt;&lt;br /&gt;        //guardar valores en toda la hoja&lt;br /&gt;        HSSFCell celda;&lt;br /&gt;        int row = 0;&lt;br /&gt;        int col;&lt;br /&gt;        for (Map m : (List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;) reporte){&lt;br /&gt;            col = 0;&lt;br /&gt;            // guarda valores en una fila de la hoja&lt;br /&gt;            for (Object o : m.keySet()) {&lt;br /&gt;                celda = getCell(hoja, row, col++);&lt;br /&gt;                celda.setCellStyle(estiloCelda);&lt;br /&gt;                setText(celda, null == m.get(o) ? &amp;quot;[nulo]&amp;quot; : m.get(o).toString());&lt;br /&gt;            }&lt;br /&gt;        row++;&lt;br /&gt;        }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La información a utilizar, según el controller que hicimos antes, se obtiene del ModelMap con el identificador &amp;quot;datos&amp;quot;.  Para este caso se está obteniendo una lista de registros devueltos comúnmente por la ejecucion de un &lt;i&gt;jdbcTemplate.queryForList(&amp;quot;... mi query sql ...&amp;quot;)&lt;/i&gt; de Spring.&lt;br /&gt;&lt;br /&gt;Es necesario crerar una hoja mediante &lt;i&gt;createSheet()&lt;/i&gt; y usar el valor devuelto (HSSFSheet) para agregar contenido, diseño, colores de fondo y bordes, agregar registros o contenido en celdas específicas con coordenadas (fila, columna), rotar texto, fuente, tamaño, forma de texto y clasificación de contenido de la celda, entre otros muchos más.&lt;br /&gt;&lt;br /&gt;Por ejemplo puedes utilizar la instancia de la hoja (HSSFSheet) y el metodo &lt;i&gt;autoSizeColumn((short) 1)&lt;/i&gt; para configurar una columna (este caso la B) como autoajustable a lo ancho, de acuerdo al texto que contenga.  Para modificar el alto de la primera fila, hacer:&lt;br /&gt;&lt;pre class="brush:java;"&gt;        HSSFRow primerRegistro = hoja.createRow(0);&lt;br /&gt;        primerRegistro.setHeight((short) 1200);  //es una altura de 60.00 cuando lo ves desde el Excel&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Observa que utilizas dos métodos básicamente: &lt;i&gt;getCell()&lt;/i&gt; para obtener una celda (HSSFCell) de una hoja determinada en una ubicación con la combinación fila, columna; y &lt;i&gt;setText()&lt;/i&gt; para asignarle un valor de texto a dicha celda.&lt;br /&gt;&lt;br /&gt;También puedes crear templates de estilos de celda para luego aplicarlos a un grupo de ellas.  En el código siguiente se esta definiendo un tipo de letra (HSSFFont) de ancho normal, con tamaño 8 y un estilo (HSSFCellStyle) con alineación a la izquierda y borde inferior con pequeños puntos consecutivos(BORDER_DOTTED).&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java;"&gt;    private static HSSFCellStyle obtenerEstiloCelda(HSSFWorkbook book) {&lt;br /&gt;        HSSFFont fuente = book.createFont();&lt;br /&gt;        fuente.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);&lt;br /&gt;        fuente.setFontHeightInPoints((short)8);&lt;br /&gt;        HSSFCellStyle estilo = book.createCellStyle();&lt;br /&gt;        estilo.setFont(fuente);&lt;br /&gt;        //alineacion&lt;br /&gt;        estilo.setAlignment(HSSFCellStyle.ALIGN_LEFT);&lt;br /&gt;        estilo.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);&lt;br /&gt;        //border&lt;br /&gt;        estilo.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);&lt;br /&gt;        return estilo;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Existen muchas más alternativas para los estilos pero para no volver a escribir lo que ya está publicado en otros lados, debes revisar las ligas siguientes para abundar más sobre el tema:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.docstoc.com/docs/271809/Java---C%C3%B3mo-generar-Hojas-de-Excel-con-Apache-POI"&gt;http://www.docstoc.com/docs/271809/Java---C%C3%B3mo-generar-Hojas-de-Excel-con-Apache-POI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://apiconz.wordpress.com/2007/10/22/como-generar-hojas-de-excel-en-una-aplicacion-java-usando-apache-poi/"&gt;http://apiconz.wordpress.com/2007/10/22/como-generar-hojas-de-excel-en-una-aplicacion-java-usando-apache-poi/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Aunque puedes realizar un montón de ajustes en el estilo de tu hoja, básicamente, tu hoja la diseñas en la vista (View) que hereda de la &lt;i&gt;AbstractExcelView&lt;/i&gt; y Spring hace todo el resto del trabajo. Sencillo no ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4245415715650752681?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4245415715650752681/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/12/configurar-poi-en-spring-3-para-generar.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4245415715650752681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4245415715650752681'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/12/configurar-poi-en-spring-3-para-generar.html' title='Configurar POI en Spring 3 para generar archivos Excel'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4129492143159952459</id><published>2010-11-30T11:12:00.000-08:00</published><updated>2010-11-30T14:03:50.055-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='escritorio remoto'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><title type='text'>Servidor VNC para sesiones de escritorios remotos</title><content type='html'>&lt;b&gt;Introducción&lt;/b&gt; &lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/VNC"&gt;VNC (Virtual Network Computer)&lt;/a&gt; es el software a través del cual se puede iniciar sesión en &lt;a href="http://es.wikipedia.org/wiki/Escritorio_remoto"&gt;escritorio remoto&lt;/a&gt; con GNU/Linux.&lt;br /&gt;&lt;br /&gt;Otra opción es el &lt;a href="http://es.wikipedia.org/wiki/Remote_Desktop_Protocol"&gt;RDP&lt;/a&gt; de Windows, sin embargo aquí explicaremos únicamente como configurar el servidor para el caso de VNC.&lt;br /&gt;&lt;br /&gt;Lo primero que hay que saber es que VNC funciona para controlar escritorios remotos que utilizan el servidor gráfico &lt;a href="http://es.wikipedia.org/wiki/X_Window_System"&gt;X-Window&lt;/a&gt; , el default de GNU/Linux hasta ahora. Sin entrar en detalles de cómo funciona X-Window, basta saber que en este tutorial explicaremos dos opciones:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;controlar el escritorio X real que se tenga en el escritorio remoto&lt;/li&gt;&lt;li&gt;controlar un escritorio X virtual que se crea a demanda en dicho escritorio remoto&lt;/li&gt;&lt;/ol&gt;Ambas opciones tienen posibilidades de aplicación.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=8587897704769639737&amp;amp;postID=4129492143159952459" name="more"&gt;&lt;/a&gt;&lt;br /&gt;Por ejemplo, si lo que deseamos es que otras personas vean mi escritorio mientras yo lo manipulo, puedo levantar VNC usando la opción 1 y permitiendo que los demás se conecten sólo en escucha (sin posibilidad de intervenir en mi sesión). Y  de esta manera se pueden impartir cursos o hacer demostraciones en vivo.&lt;br /&gt;&lt;br /&gt;Si lo que deseamos es acceder a sesión remota del escritorio para poder acceder como si se tratara de estar sentado físicamente frente a la máquina, pero sin estarlo, y que no importe (o no se requiera) manipular directametne la terminal real de X, sino sólo iniciar sesión, puedo levantar VNC usando la opción 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Cabe entonces mencionar que en X se tiene siempre asociada una 'pantalla' (display) real con la terminal física. Normalmente se le asigna el número 0 como identificador. A partir de ahí, el programa Xserver permite levantar nuevas 'pantallas' virtuales (displays) no relacionadas con la terminal física. Es decir que si usamos la pantalla #1, al no ser la física, podemos acceder a ella a través de VNC, pero en la pantalla física no se verá nada (pues esta es la 0, no la 1).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Requisitos&lt;/b&gt; &lt;b&gt;previos&lt;/b&gt;&lt;br /&gt;Los programas en cuestión que necesitamos instalar son los siguientes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;opción 1: &lt;a href="http://www.karlrunge.com/x11vnc/"&gt;x11vnc&lt;/a&gt; en el servidor&lt;/li&gt;&lt;li&gt;opción 2: &lt;a href="http://www.tightvnc.com/"&gt;TightVNC&lt;/a&gt; , &lt;a href="http://www.realvnc.com/"&gt;RealVNC&lt;/a&gt;, &lt;a href="http://www.ultravnc.net/"&gt;UltraVNC&lt;/a&gt; o cualquier otro que permita VNC en el servidor&lt;/li&gt;&lt;li&gt;clientes: cualquier visor de VNC, como &lt;a href="http://www.kde.org/applications/internet/krdc/"&gt;krdc&lt;/a&gt;, &lt;a href="http://www.realvnc.com/"&gt;realvnc vncviewer&lt;/a&gt;, etc.  No entraremos en detalle sobre el uso de los clientes, ya que se trata de algo muy intuitivo, bastará conectarse al servidor VNC una vez que esté levantado en el puerto que se haya configurado para lo mismo. Cabe anotar que los clientes pueden correr en cualquier plataforma independientemente de que el servidor sea GNU/Linux u otro. Por ejemplo, se puede iniciar sesión remota con un cliente en Windows, a pesar de que el servidor sea GNU/Linux. Otra anotación interesante sobre los clientes es que algunos servidores de VNC (por ejemplo TightVNC) permiten levantar el servidor a través de una interfaz en Java para que el escritorio remoto pueda ser accedido a través de un navegador web con soporte para Java, utilizando un applet específico para lo mismo.&lt;/li&gt;&lt;li&gt;configurar XDMCP en el escritorio remoto para permitir el incio de sesión.&lt;/li&gt;&lt;/ul&gt;También hay que asegurarse de tener instalado en el servidor el programa Xserver, y de preferencia el superservidor xinetd, que permitirá conectarse a pantallas virtuales sin consumir recursos del servidor cuando no se esté utilizando VNC y a la vez permitir a más de una persona conectarse a su propia sesión con VNC sin que el servidor bloquee puertos ni nada por el estilo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Inicio de sesión remoto&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/XDMCP"&gt;XDMCP&lt;/a&gt; es un protocolo que, en resumen, permite el incio de sesión remoto en terminales X de cualquier índole.&lt;br /&gt;&lt;br /&gt;Si no configuramos XDMCP, entonces solamente podremos acceder a pantallas que ya tengan la sesión iniciada. Puesto que esto sólo es posible en pantallas físicas, nos veríamos restringidos a la opción #1, sin posibilidad de utilizar la pantalla de inicio de sesión de la pantalla que quisiéramos controlar, por lo que sólo sesiones previamente iniciadas podrían ser controladas. Esto no es ni práctico, ni mucho menos seguro, lo recomendable es que podamos iniciar sesión en modo gráfico en el escritorio remoto a partir de un prompt de nombre de usuario y password por validar.&lt;br /&gt;&lt;br /&gt;XDMCP se configura de manera diferente, dependiendo el &lt;a href="http://es.wikipedia.org/wiki/X_Display_Manager"&gt;manejador de pantalla&lt;/a&gt; que estemos utilizando. Físicamente, sin importar el tipo de manejador de escritorio que estemos utilizando (GNOME, KDE, XFCE, etc.), se utiliza un manejador de pantalla para poder iniciar sesión en nuestro escritorio remoto, incluso cuando estamos sentados físicamente frente a él. Las opciones más comunes son: gdm, kdm y xdm. (Normlamente GNOME utiliza gdm, pero podría utilizar otro; KDE utiliza kdm pero podría ser otro, y así...)&lt;br /&gt;&lt;br /&gt;&lt;i&gt;xdm&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Debe abrirse el archivo xdm-config y comentarse la línea con el texto&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DisplayManager.requestPort :0 &lt;/div&gt;&lt;/blockquote&gt;insertando un ! al inicio.&lt;br /&gt;&lt;br /&gt;El usuario 'nobody' debería de tener asociada una terminal shell válida para poder iniciar sesión, por lo que hay que ejecutar:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usermod -s /bin/bash nobody&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;i&gt;gdm&lt;/i&gt;&lt;br /&gt;Debe ejecutarse gdmconfig, encontrar la pestaña llamada 'XDMCP' y habilitar esta opción.&lt;br /&gt;&lt;br /&gt;En escritorios como XFCE, que a veces usan también gdm, la opción se encuentra, dentro del menú 'Configuración', en la pantalla 'Ventana de entrada', en la pestaña 'Remota' hasta abajo se encuentra el botón 'Configurar XDMCP' (obviamente hay que empezar por habilitar la pestaña Remota en los permisos de inicio de sesión dentro de esta misma pantalla).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;kdm&lt;/i&gt;&lt;br /&gt;Debe editarse el archivo kdmrc y habilitar XDMCP en el puerto 177:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;[Xdmcp]&lt;br /&gt;Enable=true&lt;br /&gt;Willing=/etc/X11/xdm/Xwilling&lt;br /&gt;Xaccess=/etc/X11/xdm/Xaccess&lt;br /&gt;Port=177&lt;/pre&gt;&lt;/blockquote&gt;&lt;i&gt; &lt;/i&gt;&lt;br /&gt;&lt;i&gt;seguridad&lt;/i&gt; &lt;br /&gt;En caso de soportarlo, lo recomendable también es configurar quiénes pueden acceder a sesión. Esta configuración depende completamente del manejador de pantalla que se tenga pero no entraremos en detalle en este caso. &lt;br /&gt;&lt;br /&gt;Más información &lt;a href="http://linuxreviews.org/howtos/xvnc/#toc3"&gt;aquí&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Opción 1 (x11vnc , control directo de la terminal física remota)&lt;/b&gt;&lt;br /&gt;Como dijimos, se trata de manipular remotamente la pantalla 0, la cual X asocia por default a la terminal física de la máquina que llamaremos en adelante 'escritorio remoto'.&lt;br /&gt;&lt;br /&gt;En 'escritorio remoto' hay que instalar entonces x11vnc y Xserver.&lt;br /&gt;&lt;br /&gt;Hecho eso, se puede lanzar una línea como la siguiente:&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x11vnc&lt;/blockquote&gt;&lt;br /&gt;Lo cual nos brindará información adicional sobre los parámetros que deberíamos de lanzar para autenticar nuestra sesión, entre otros.&lt;br /&gt;&lt;br /&gt;Yo uso normalmente la siguiente línea:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x11vnc -auth /var/lib/gdm/:0.Xauth -display :0 -shared -forever -ncache -rfbport 5901  -rfbauth ./.vnc/passwd_x11vnc&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;En donde el parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-auth&lt;/span&gt; asocia el archivo :0.Xauth (que hay que localizar en el 'escritorio remoto' para cada caso particular) y de esa manera si mi escritorio remoto se quedó en la pantalla de login, poder hacer uso de la autenticación y así poder iniciar sesión. Si no se usa este parámetro, se tendría que tener la pantalla 0 ya dentro de sesión en el escritorio remoto para poder hacer uso del acceso remoto.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-forever&lt;/span&gt; permite escuchar constantemente conexiones aunque estas se terminen, siempre y cuando no se cierre la sesión gráfica en 0&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-rfbport&lt;/span&gt; indica el número de puerto en que estará escuchando el 'escritorio remoto' para aceptar conexiones. 5901 es el puerto por default para VNC. Por cierto, no hay que olvidar abrir este puerto en el firewall del escritorio remoto.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-rfbauth&lt;/span&gt; apunta a un archvio en el que previamente almacené un password para autenticar el acceso a mi servidor y así evitar que cualquiera que conozca la dirección IP de mi escritorio remoto se pueda conectar a mi terminal gráfica física 0 y por lo tanto ver o intervenir en mis sesiones directamente (este riesgo es MUY REAL, hay que generar el password siempre). Para generar el archivo del password, x11vnc debe ejecutarse con el parámetro -storepassword, por ejemplo:&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x11vnc -storepassword /path/al/archivo_de_password&lt;/blockquote&gt;Aquí no entraremos en detalle para levantar x11vnc usando xinetd, pero el &lt;a href="http://www.karlrunge.com/x11vnc/"&gt;sitio oficial de x11vnc&lt;/a&gt; da más información. Además, traspolando un poco la información que daremos para la opción #2, se puede lograr levantar un servidor así.&lt;br /&gt;&lt;br /&gt;Antes de concluir con x11vnc, hay que aclarar también que para poder inciar sesión remota también es necesario configurar el protocolo XDMCP como se explicó anteriormente...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Opción 2 (vnc, control de pantallas virtuales remotas)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;En este caso se manipularán pantallas virtuales no directamente relacionadas con la terminal física del escritorio remoto. La idea será que dichas pantallas se creen a demanda también.&lt;br /&gt;&lt;br /&gt;En el escritorio remoto habrá que tener instalado tanto el software que se usará como servidor VNC (tightvnc, ultravnc, realvnc, etc.) y Xserver.&lt;br /&gt;&lt;br /&gt;Hecho eso se puede ejecutar la siguiente línea de comandos:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vncserver -query localhost -once -geometry 1024x768 -depth 16 :1&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;Con lo que se tendrá un servidor VNC en la pantalla virtual #1, y si esta no estuviera disponible, buscaría en la 2, y así sucesivamente.&lt;br /&gt;&lt;br /&gt;El parámetro&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; -once&lt;/span&gt; indica que sólo permitirá el inicio de sesión una vez, luego de terminar la cual cerrará el servidor. Esta opción es más útil aún usando un superservidor como se explica más adelante.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-geometry 1024x768&lt;/span&gt; define la resolución que tendrá la sesión en el escritorio remoto.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-depth 16&lt;/span&gt; indica la profundidad de color a obtener en la sesión remota, en este caso a 16 colores.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;:1&lt;/span&gt; indica el número de pantalla virtual que se desea utilizar.&lt;br /&gt;&lt;br /&gt;El parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-query localhost&lt;/span&gt; indica que se desea iniciar sesión en el escritorio remoto a través de XDMCP.&lt;br /&gt;&lt;br /&gt;Para que se autentique a los usuarios, es necesario crear previamente el archivo de passwords con el programa &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vncpasswd&lt;/span&gt;. Por default, vncserver busca en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$HOME/.vnc/passwd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Superservidor xinetd&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Sin embargo, levantar manualmente un servidor de pantallas virtuales VNC no es la forma más óptima, ya que se tienen estos inconvenientes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;hay que levantar nuevamente el servidor cada vez que se termine de usar&lt;/li&gt;&lt;li&gt;solamente podrá entrar a sesión por VNC una persona, y si se tiene más de un usuario que pudiera iniciar sesión en el escritorio remoto (cada uno a su propia sesión), no se les permitiría.&lt;/li&gt;&lt;li&gt;además si no se está utilizando el servicio VNC en un momento dado, aún así se está consumiendo memoria en el servidor, con el programa a la escucha de posibles conexiones. &lt;/li&gt;&lt;/ul&gt;La solución implica levantar algo conocido como un &lt;a href="http://en.wikipedia.org/wiki/Super-server"&gt;superservidor&lt;/a&gt;, de los cuales &lt;a href="http://es.wikipedia.org/wiki/Xinetd"&gt;xinetd&lt;/a&gt; es el más popular en GNU/Linux. El superservidor permite levantar a demanda instancias de los servidores configurados en él. Esto trae ventajas de menor consumo de memoria, además de permitir levantar instancias múltiples del servidor escuchando un sólo puerto (que atiende el superservidor). Y en cuanto se termine de usar el servidor en cuestión, el superservidor sigue atento para nuevas solicitudes. Un superservidor es útil para servidores que no están en constante uso o que no requieren de alta disponibilidad, podría ser (dependiendo las circunstancias, claro): telnet, ftp, o en nuestro caso vnc.&lt;br /&gt;&lt;br /&gt;Una vez instalado xinetd, lo único que debe hacerse es agregar la configuración adecuada para utilizar VNC a través del mismo. Esta configuración se puede escribir en un archivo exclusivo para VNC, pero debe asegurarse de guardarse en donde xinetd lo lea, por lo regular en&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; /etc/xinetd.d&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El siguiente es un ejemplo de un servidor VNC levantado a  través de xinetd:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;service vnc&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{                                                                                                              &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  protocol = tcp&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  socket_type = stream&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  wait = no&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  user = user_name&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  server = /usr/bin/Xvnc&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  server_args = -inetd -query localhost -once -geometry 1024x768 -depth 16 -rfbauth=/home/user_name/.vnc/passwd&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  disable = no&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;Antes de utilizarlo, explicaré algunos detalles:&lt;br /&gt;&lt;br /&gt;-El servidor que se mandó llamar utiliza el programa 'Xvnc', en vez de 'vncserver'. Leyendo la página del manual de vncserver (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;man vncserver&lt;/span&gt;), se puede constatar que en realidad vncserver es un wrapper que manda llamar en el fondo a Xvnc, por lo que este último programa será el indicado para llamar en las instancias que genere el superservidor.&lt;br /&gt;&lt;br /&gt;-Los argumentos incluyen el parámetro &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-inetd&lt;/span&gt; que es necesario para que el servidor VNC sepa que fue mandado llamar desde un superservidor.&lt;br /&gt;&lt;br /&gt;-Se incluye el parámetro&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; -rfbauth=/path/passwd&lt;/span&gt; , el cual es la ruta al archivo de password a utilizar.&lt;br /&gt;&lt;br /&gt;-El nombre de usuario 'user_name' se utilizó en este caso para que el servidor se ejecute a nombre de este usuario. Normalmente se utiliza el usuario 'nobody', pero este debe de tener permisos de lectura al archivo de password, por lo que otra opción implica ejecutar el servidor como otro usuario, con acceso al archivo de password en una ruta particular.&lt;br /&gt;&lt;br /&gt;-Si se utiliza TightVNC, las opciones de configuracion no deben incluir el caracter '=', sino que hay que sustituirlos por espacios &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Una vez configurado el servicio, hay que reiniciar xinetd:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/etc/init.d/xinetd restart&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;(o cualquiera que sea la manera de hacerlo en tu distribución en particular).&lt;br /&gt;&lt;br /&gt;No hay que olvidar abrir el puerto 5901 (que es el default de VNC, en realidad es el puerto 5900 + N, donde N será el número de pantalla virtual que se utilice) para escuchar las peticiones a conectarse.&lt;br /&gt;&lt;br /&gt;Igualmente no olvidar que aunque muchos usuarios se puedan conectar al servidor VNC, sólo una persona a la vez podrá entrar a una sesión en particular. Si hay más de una sesión disponible en el servidor, cada una podrá ser iniciada una vez, pero no pueden entrar a sesión más de una vez por nombre de usuario.&lt;br /&gt;&lt;br /&gt;En &lt;a href="http://linuxreviews.org/howtos/xvnc"&gt;este link&lt;/a&gt;, se da más información y la posibilidad de levantar más de un servidor con xinetd para escuchar en distintos puertos, para tener la posibilidad de conectarse con distintas resoluciones al mismo servidor VNC.&lt;br /&gt;&lt;br /&gt;Algunos servidores VNC (como Tight VNC) permiten conectarse también vía http en un navegador web, utilizando un applet de Java. Hay que consultar la documentación de cada caso particular para poder lograr esto. De entrada, lo que normalmente se hace es utilizar el puerto 5800 + N para obtener esta conexión.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4129492143159952459?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4129492143159952459/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/11/servidor-vnc-para-sesiones-de.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4129492143159952459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4129492143159952459'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/11/servidor-vnc-para-sesiones-de.html' title='Servidor VNC para sesiones de escritorios remotos'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-2110654876249916135</id><published>2010-08-26T01:56:00.000-07:00</published><updated>2010-08-31T09:52:10.786-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dataset'/><category scheme='http://www.blogger.com/atom/ns#' term='dbunit'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><category scheme='http://www.blogger.com/atom/ns#' term='datos'/><title type='text'>DBUnit lo hace facil</title><content type='html'>Dado que he trabajado con JUnit y DBUnit y he encontrado en ellos unas buenas herramientas para probar el codigo de las aplicaciones en java, pues me d&amp;#237; a la tarea de investigar un poquito sobre como obtener datasets desde una BD, y como cargarlos para realizar pruebas espec&amp;#237;ficas.&amp;#160; Fue entonces cuando me encontr&amp;#233; con este art&amp;#237;culo de Bill Siggelkow y me d&amp;#237; a la tarea de traducir una parte, tambi&amp;#233;n he agregado notas m&amp;#237;as, pero pueden encontrar el original en enlace al final del post.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Y dice as&amp;iacute;:&lt;br /&gt;Si desarrollas aplicaciones que acceden a datos relacionales necesitas verificar el c&amp;#243;digo de tu aplicaci&amp;#243;n trabaje con los datos, como fue dise&amp;#241;ado.&amp;#160; Cuando usas Hibernate o alg&amp;#250;n otro framework que implemente JPA, deber&amp;#237;as confirmar que tus mapeos dirijan a Hibernate para almacenar y recuperar la informaci&amp;#243;n correctamente.&amp;#160; Yo implemento este tipo de pruebas usando JUnit.&amp;#160; Nadie puede refutar que las pruebas contra una base de datos activa es fundamental - no hay una mejor forma para verificar tus mapeos.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Pero para probar contra la base de datos se requiere que los datos se encuentren en un estado inicial.&amp;#160; Puedes cargar la base de datos manualmente antes de correr tu prueba pero eso se vuelve monotono y propenso a errores. &lt;a href="http://dbunit.sourceforge.net/"&gt;DBUnit&lt;/a&gt; resuelve este problema.&amp;#160; Este puede precargar la base de datos para cada una de tus pruebas, basado en un grupo de datos dentro de un xml (com&amp;#250;nmente llamado dataset).&amp;#160; El formato de este dataset es sencillo de entender; aqu&amp;#237; hay un ejemplo de tres tablas de una base de datos MySQL.&amp;#160; Los nombres de los elementos empatan con los nombres de las tablas y sus atributos con los nombres de sus columnas. Cada elemento implica un registro en esa tabla.&lt;p&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;dataset&amp;gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;cliente id_cliente=&amp;quot;778899&amp;quot; id_estatus = &amp;quot;1&amp;quot; id_sucursal=&amp;quot;98765&amp;quot;/&amp;gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;banco id_banco=&amp;quot;1&amp;quot; nombre=&amp;quot;BNMX&amp;quot; descripcion=&amp;quot;Banamex&amp;quot; activo=&amp;quot;1&amp;quot;&lt;br /&gt;valor=&amp;quot;0&amp;quot;/&amp;gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;pago id_cliente = &amp;quot;778899&amp;quot; id_estatus = &amp;quot;1&amp;quot; id_tipo_producto =&lt;br /&gt;&amp;quot;1&amp;quot; id_promotor = &amp;quot;1&amp;quot; id_sucursal = &amp;quot;58&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/dataset&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Para una base de datos peque&amp;#241;a donde solo necesitas cargar unas pocas tablas con unos pocos registros puedes crear el dataset manualmente.  Pero seguramente no quer&amp;#225;s hacerlo con una base de datos empresarial compleja que contiene cientos de tablas con nombres de columnas complejas.&amp;#160; Es m&amp;#225;s facil si le permites a DbUnit extraer los datos por ti.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Aqu&amp;#237; esta un proceso t&amp;#237;pico que sigues cuando usas DBUnit:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Poblar las tablas de tu base de datos como sea necesario para ejecutar tu prueba.&lt;br /&gt;Extraer los datos desde esas tablas hacia un dataset XML. En el m&amp;#233;todo setUp de tu prueba unitaria, llamar a DBUnit para cargar la base de datos desde los dataset&amp;#39;s recientement creados.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Puedes extraer los datos usando una clase como esta:&lt;p&gt;&lt;pre class="brush:java;"&gt;import java.io.FileOutputStream;&lt;br /&gt;import java.sql.Connection;&lt;br /&gt;import java.sql.DriverManager;&lt;br /&gt;&lt;br /&gt;import org.dbunit.database.DatabaseConnection;&lt;br /&gt;import org.dbunit.database.IDatabaseConnection;&lt;br /&gt;import org.dbunit.database.QueryDataSet;&lt;br /&gt;import org.dbunit.dataset.IDataSet;&lt;br /&gt;import org.dbunit.dataset.xml.FlatXmlDataSet;&lt;br /&gt;&lt;br /&gt;public class ExtractTestDataSet {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void main(String[] args) throws Exception {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // conexion a la base de datos&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Class driverClass = Class.forName(&amp;quot;com.mysql.jdbc.Driver&amp;quot;);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Connection jdbcConnection = DriverManager.getConnection(&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;jdbc:mysql://localhost/bon_app&amp;quot;, &amp;quot;scott&amp;quot;, &amp;quot;tiger&amp;quot;);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // exportar un dataset parcial&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; QueryDataSet partialDataSet = new QueryDataSet(connection);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partialDataSet.addTable(&amp;quot;recipe&amp;quot;, &amp;quot;SELECT * FROM recipe where&lt;br /&gt;is_deleted != &amp;#39;Y&amp;#39;&amp;quot;);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partialDataSet.addTable(&amp;quot;recipe_ext_xref&amp;quot;);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FlatXmlDataSet.write(partialDataSet,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new FileOutputStream(&amp;quot;partial-dataset.xml&amp;quot;));&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // exportacion de la base de datos completa!!&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IDataSet fullDataSet = connection.createDataSet();&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FlatXmlDataSet.write(fullDataSet, new&lt;br /&gt;FileOutputStream(&amp;quot;full-dataset.xml&amp;quot;));&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;DBUnit puede crear un dataset con todos los datos en tu base de datos configur&amp;#225;ndole solamente una conecci&amp;#243;n JDBC abierta  En la pr&amp;#225;ctica, probablemente quer&amp;#225; limitar el dataset a tablas espec&amp;#237;ficas y datos usados por tu prueba unitaria.  En el ejemplo anterior se esta creando dos archivos dataset.  El primero como partial-dataset.xml, representa solo una porcion de la base de datos. DBUnit pobla el dataset basado en tablas y queries especificados.  Si solo indicas el nombre de una tabla, el dataset se llenar&amp;#225; de todos los registros y columnas en esa tabla.  Especifia una tabla y un query y DBUnit solo extraer&amp;#225; los datos devueltos por el query.  Si quieres la base de datos completa en el dataset, simplemente llama el metodo IDatabaseConnection.createDataSet().&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En el m&amp;#233;todo setUp() de tu prueba unitaria, usas el dataset como entrada para una operacion DBUnit.  DBUnit soporta varias combinaciones de operacion para borrar, insetar y ctualizar la base de datos usando un dataset.  Las operaciones m&amp;#225;s comunes son CLEAN_INSERT (limpia toda la tabla e inserta los registros del dataset) y REFRESH (solo agrega los registros del dataset a la tabla y si estos ya existen, los actualiza - con base en el id de la tabla).  CLEAN_INSERT es la opcion a usar si tienes tu propia instancia de base de datos y no necesitas preocuparte por ponerle el pie a alguien m&amp;#225;s del equipo de desarrollo.  Por otro lado, si compartes tu base de datos con el equipo, tu mejor amigo es REFRESH.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En el siguiente fragmento de una prueba unitaria, se est&amp;#225; usando CLEAN_INSERT para reinicializar la base de datos antes de cada m&amp;#233;todo de prueba.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;pre class="brush:java;"&gt;protected void setUp() throws Exception {&lt;br /&gt;    setUpDatabase();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void setUpDatabase() throws Exception {&lt;br /&gt;    // Inicializa tu base de datos aqu&amp;#237;&lt;br /&gt;    Class driverClass = Class.forName(&amp;quot;com.mysql.jdbc.Driver&amp;quot;);&lt;br /&gt;    Connection jdbcConnection = DriverManager.getConnection(&lt;br /&gt;&amp;quot;jdbc:mysql://localhost/bon_app&amp;quot;, &amp;quot;scott&amp;quot;, &amp;quot;tiger&amp;quot;);&lt;br /&gt;    IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);&lt;br /&gt;&lt;br /&gt;// inicializa tu dataset aqu&amp;#237;&lt;br /&gt;    IDataSet dataSet = new FlatXmlDataSet(new File(&amp;quot;full-dataset.xml&amp;quot;));&lt;br /&gt;    try {&lt;br /&gt;        DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);&lt;br /&gt;    } finally {&lt;br /&gt;        connection.close();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Esta forma trabaja bien pero es algo molesto que tengas que hacer c&amp;#243;digo a  mano y recompilar la clase que extrae cuando sea necesariocambiar como DBUnit crea los dataset.  Usando Spring se le puede delegar el trabajo de configurar la clase de extracci&amp;#243;n de datos y esto salvar&amp;#237;a un mont&amp;#243;n de c&amp;#243;digo hecho a mano.  Esto resulta en la siguiente clase:&lt;p&gt;&lt;pre class="brush:java;"&gt;package com.jadecove.bonappetit.test;&lt;br /&gt;import java.io.FileOutputStream;&lt;br /&gt;import java.sql.Connection;&lt;br /&gt;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import java.util.regex.Matcher;&lt;br /&gt;import java.util.regex.Pattern;&lt;br /&gt;import javax.sql.DataSource;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;import org.dbunit.database.DatabaseConfig;&lt;br /&gt;import org.dbunit.database.DatabaseConnection;&lt;br /&gt;import org.dbunit.database.IDatabaseConnection;&lt;br /&gt;import org.dbunit.database.QueryDataSet;&lt;br /&gt;import org.dbunit.dataset.IDataSet;&lt;br /&gt;import org.dbunit.dataset.xml.FlatXmlDataSet;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Extracts a DBUnit flat XML dataset from a database.&lt;br /&gt;*&lt;br /&gt;* @author Bill Siggelkow&lt;br /&gt;*/&lt;br /&gt;public class DBUnitDataExtractor {&lt;br /&gt;    private DataSource dataSource;&lt;br /&gt;    private String dataSetName = &amp;quot;dbunit-dataset.xml&amp;quot;;&lt;br /&gt;    private List queryList;&lt;br /&gt;    private List tableList;&lt;br /&gt;    private Map dbUnitProperties;&lt;br /&gt;    private Map dbUnitFeatures;&lt;br /&gt;    private String schema;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * A regular expression that is used to get the table name&lt;br /&gt;    * from a SQL &amp;#39;select&amp;#39; statement.&lt;br /&gt;    * This  pattern matches a string that starts with any characters,&lt;br /&gt;    * followed by the case-insensitive word &amp;#39;from&amp;#39;,&lt;br /&gt;    * followed by a table name of the form &amp;#39;foo&amp;#39; or &amp;#39;schema.foo&amp;#39;,&lt;br /&gt;    * followed by any number of remaining characters.&lt;br /&gt;    */&lt;br /&gt;    private static final Pattern TABLE_MATCH_PATTERN = Pattern.compile(&amp;quot;.*\s+from\s+(\w+(\.\w+)?).*&amp;quot;, Pattern.CASE_INSENSITIVE);&lt;br /&gt;    private static final Logger log = Logger.getLogger(DBUnitDataExtractor.class);&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * The data source of the database from which the data will be&lt;br /&gt;    extracted. This property&lt;br /&gt;    * is required.&lt;br /&gt;    *&lt;br /&gt;    * @param ds&lt;br /&gt;    */&lt;br /&gt;    public void setDataSource(DataSource ds) {&lt;br /&gt;        dataSource = ds;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Set the schema.&lt;br /&gt;    * @param schema&lt;br /&gt;    */&lt;br /&gt;    public void setSchema(String schema) {&lt;br /&gt;        this.schema = schema;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Name of the XML file that will be created. Defaults to&lt;br /&gt;    &amp;lt;code&amp;gt;dbunit-dataset.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;    *&lt;br /&gt;    * @param name file name.&lt;br /&gt;    */&lt;br /&gt;    public void setDataSetName(String name) {&lt;br /&gt;        dataSetName = name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Performs the extraction. If no tables or queries are specified,&lt;br /&gt;    data from entire database&lt;br /&gt;    * will be extracted. Otherwise, a partial extraction will be performed.&lt;br /&gt;    * @throws Exception&lt;br /&gt;    */&lt;br /&gt;    public void extract() throws Exception {&lt;br /&gt;        Connection conn = null;&lt;br /&gt;        try {&lt;br /&gt;            conn = dataSource.getConnection();&lt;br /&gt;            log.info(&amp;quot;Beginning extraction from &amp;#39;&amp;quot;+conn.toString()+&amp;quot;&amp;#39;.&amp;quot;);&lt;br /&gt;            IDatabaseConnection connection = new DatabaseConnection(conn, schema);&lt;br /&gt;            configConnection((DatabaseConnection) connection);&lt;br /&gt;            if (tableList != null || queryList != null) {&lt;br /&gt;                // partial database export&lt;br /&gt;                QueryDataSet partialDataSet = new QueryDataSet(connection);&lt;br /&gt;                addTables(partialDataSet);&lt;br /&gt;                addQueries(partialDataSet);&lt;br /&gt;                FlatXmlDataSet.write(partialDataSet, new FileOutputStream(dataSetName));&lt;br /&gt;            } else {&lt;br /&gt;                // full database export&lt;br /&gt;                IDataSet fullDataSet = connection.createDataSet();&lt;br /&gt;                FlatXmlDataSet.write(fullDataSet, new&lt;br /&gt;                FileOutputStream(dataSetName));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        finally {&lt;br /&gt;            if (conn != null) conn.close();&lt;br /&gt;        }&lt;br /&gt;        log.info(&amp;quot;Completed extraction to &amp;#39;&amp;quot;+dataSetName+&amp;quot;&amp;#39;.&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * List of table names to extract data from.&lt;br /&gt;    *&lt;br /&gt;    * @param list of table names.&lt;br /&gt;    */&lt;br /&gt;    public void setTableList(List list) {&lt;br /&gt;        tableList = list;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * List of SQL queries (i.e. &amp;#39;select&amp;#39; statements) that will be used executed to retrieve&lt;br /&gt;    * the data to be extracted. If the table being queried is also specified in the &amp;lt;code&amp;gt;tableList&amp;lt;/code&amp;gt;&lt;br /&gt;    * property, the query will be ignored and all rows will be extracted from that table.&lt;br /&gt;    *&lt;br /&gt;    * @param list of SQL queries.&lt;br /&gt;    */&lt;br /&gt;    public void setQueryList(List list) {&lt;br /&gt;        queryList = list;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setDbUnitFeatures(Map dbUnitFeatures) {&lt;br /&gt;        this.dbUnitFeatures = dbUnitFeatures;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setDbUnitProperties(Map dbUnitProperties) {&lt;br /&gt;        this.dbUnitProperties = dbUnitProperties;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void configConnection(DatabaseConnection conn) {&lt;br /&gt;        DatabaseConfig config = conn.getConfig();&lt;br /&gt;        if (dbUnitProperties != null) {&lt;br /&gt;            for (Iterator k=dbUnitProperties.entrySet().iterator(); k.hasNext(); ) {&lt;br /&gt;                Map.Entry entry = (Map.Entry) k.next();&lt;br /&gt;                String name = (String) entry.getKey();&lt;br /&gt;                Object value = entry.getValue();&lt;br /&gt;                config.setProperty(name, value);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        if (dbUnitFeatures != null) {&lt;br /&gt;            for (Iterator k=dbUnitFeatures.entrySet().iterator(); k.hasNext(); ) {&lt;br /&gt;                Map.Entry entry = (Map.Entry) k.next();&lt;br /&gt;                String name = (String) entry.getKey();&lt;br /&gt;                boolean value = Boolean.valueOf((String)entry.getValue()).booleanValue();&lt;br /&gt;                config.setFeature(name, value);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void addTables(QueryDataSet dataSet) {&lt;br /&gt;        if (tableList == null) return;&lt;br /&gt;        for (Iterator k = tableList.iterator(); k.hasNext(); ) {&lt;br /&gt;            String table = (String) k.next();&lt;br /&gt;            dataSet.addTable(table);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void addQueries(QueryDataSet dataSet) {&lt;br /&gt;        if (queryList == null) return;&lt;br /&gt;        for (Iterator k = queryList.iterator(); k.hasNext(); ) {&lt;br /&gt;            String query = (String) k.next();&lt;br /&gt;            Matcher m = TABLE_MATCH_PATTERN.matcher(query);&lt;br /&gt;            if (!m.matches()) {&lt;br /&gt;                log.warn(&amp;quot;Unable to parse query. Ignoring &amp;#39;&amp;quot; + query +&amp;quot;&amp;#39;.&amp;quot;);&lt;br /&gt;            }&lt;br /&gt;            else {&lt;br /&gt;                String table = m.group(1);&lt;br /&gt;                // only add if the table has not been added&lt;br /&gt;                if (tableList != null &amp;amp;&amp;amp; tableList.contains(table)) {&lt;br /&gt;                    log.warn(&amp;quot;Table &amp;#39;&amp;quot;+table+&amp;quot;&amp;#39; already added. Ignoring &amp;#39;&amp;quot; + query + &amp;quot;&amp;#39;.&amp;quot;);&lt;br /&gt;                } else {&lt;br /&gt;                    dataSet.addTable(table, query);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Esta clase sirve como una envoltura compatible con Spring sobre el proceso de extracci&amp;#243;n de DBUnit, aunque no tenga dependencia con Spring (eso es lo bonito de Spring).  Aqu&amp;#237; esta como puedes configurar el extractor en un archivo de beans de Spring.&lt;p&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE beans PUBLIC &amp;quot;-//SPRING//DTD BEAN//EN&amp;quot; &amp;quot;http://www.springframework.org/dtd/spring-beans.dtd&amp;quot;&amp;gt;&lt;p&gt;&amp;lt;beans&amp;gt;&lt;br /&gt;    &amp;lt;bean id=&amp;quot;dataSource&amp;quot; class=&amp;quot;org.springframework.jdbc.datasource.DriverManagerDataSource&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;driverClassName&amp;quot;&amp;gt;&amp;lt;value&amp;gt;com.mysql.jdbc.Driver&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;url&amp;quot;&amp;gt;&amp;lt;value&amp;gt;jdbc:mysql://localhost/bon_app&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;username&amp;quot;&amp;gt;&amp;lt;value&amp;gt;scott&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;password&amp;quot;&amp;gt;&amp;lt;value&amp;gt;tiger&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;bean id=&amp;quot;dbUnitDataExtractor&amp;quot; class=&amp;quot;com.jadecove.bonappetit.test.DBUnitDataExtractor&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;dataSource&amp;quot; ref=&amp;quot;dataSource&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;dataSetName&amp;quot; value=&amp;quot;dbunit-dataset.xml&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;tableList&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;list&amp;gt;&lt;br /&gt;                &amp;lt;value&amp;gt;recipe&amp;lt;/value&amp;gt;&lt;br /&gt;                &amp;lt;value&amp;gt;recipe_ext_xref&amp;lt;/value&amp;gt;&lt;br /&gt;            &amp;lt;/list&amp;gt;&lt;br /&gt;        &amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name=&amp;quot;queryList&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;list&amp;gt;&lt;br /&gt;                &amp;lt;value&amp;gt;select * from bon_app_ext.person where first_name = &amp;#39;Bill&amp;#39;&amp;lt;/value&amp;gt;&lt;br /&gt;            &amp;lt;/list&amp;gt;&lt;br /&gt;        &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Ahora puedes extraer datasets de DBUnit recuperando un extractor configurado v&amp;#237;a Spring y llamando al m&amp;#233;todo extract().  La &amp;#250;nica propiedad requerida es la fuente de datos. Haciendolo as&amp;#237; puedes obtener la base de datos completa, pero tambi&amp;#233;n puedes listar tablas y queries espec&amp;#237;ficos. Adem&amp;#225;s, la configuraci&amp;#243;n de Spring te permite agregar otros elementos y propiedades que configuren a DBUnit de diferentes maneras, revisa la API de DBUnit para saber qu&amp;#233; m&amp;#225;s cosas puedes usar al respecto.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Cuando estas usando queries, DBUnit requiere que se especifique ambos, el nombre de la tabla y el query  Para hacer una configuraci&amp;#243;n m&amp;#225;s sencilla, este extractor usa una expresi&amp;#243;n regular que determina el nombre de la tabla.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Este extractor se ha usado con una base de datos empresarial compleja local MySQL, pero a trav&amp;#233;s de la configuraci&amp;#243;n de la conexi&amp;#243;n, esquema y caracter&amp;#237;sticas de DBUnit puedes extraer los datos desde la mayor&amp;#237;a de bases de datos.  En mi actual trabajo de consultor&amp;#237;a, yo uso este extractor para obtener datos desde algunas bases de datos complejtas DB2 corriendo en un AS-400 de IBM.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Este ejercicio no solo ayud&amp;#243; a hacer la vida m&amp;#225;s f&amp;#225;cil con DBUnit, esto me ayud&amp;#243; a entender que tan f&amp;#225;cil es delegar estas tareas mundanas a Spring.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Fuente:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/onjava/blog/2005/10/dbunit_made_easy.html"&gt;http://www.oreillynet.com/onjava/blog/2005/10/dbunit_made_easy.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-2110654876249916135?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/2110654876249916135/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/dbunit-lo-hace-facil.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2110654876249916135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2110654876249916135'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/dbunit-lo-hace-facil.html' title='DBUnit lo hace facil'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-8236338058667751026</id><published>2010-08-25T12:59:00.000-07:00</published><updated>2011-10-11T09:03:39.198-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='report'/><category scheme='http://www.blogger.com/atom/ns#' term='jasper'/><title type='text'>Configurar JasperReports en Spring 3.0</title><content type='html'>&lt;div&gt;Cada vez es más sencillo realizar las configuraciones en Spring. &amp;nbsp;A pesar de que la configuración se puede seguir usando de diferentes maneras, en la documentación de referencia de &lt;a href="http://static.springsource.org/spring/docs/3.0.2.RELEASE/spring-framework-reference/" target="_blank"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;spring 3&lt;/span&gt;&lt;/a&gt;&amp;nbsp;indica lo siguiente de forma general:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Agregar dependencias a tu proyecto&lt;/li&gt;&lt;li&gt;Configurar el&amp;nbsp;ViewResolver&lt;/li&gt;&lt;li&gt;Crear el template con iReports&lt;/li&gt;&lt;li&gt;Configurar las vistas&lt;/li&gt;&lt;li&gt;Crear el controller&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ahora vamos a los detalles.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;1. Las dependencias&lt;/span&gt; que nos dice debemos tener son las siguientes:&lt;/div&gt;&lt;div&gt;Obviamente el Jasper&lt;/div&gt;&lt;pre class="brush:xml;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;groupId&amp;gt;jasperreports&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;artifactId&amp;gt;jasperreports&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;version&amp;gt;3.5.3&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;•&amp;nbsp;BeanShell (esta no la ocupe)&lt;/div&gt;&lt;div&gt;• Commons BeanUtils (esta no la ocupe)&lt;/div&gt;&lt;div&gt;• Commons Collections (esta es requerida)&lt;/div&gt;&lt;pre class="brush:xml;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;groupId&amp;gt;commons-collections&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;artifactId&amp;gt;commons-collections&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;version&amp;gt;3.2.1&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;• Commons Digester (esta no la ocupe)&lt;/div&gt;&lt;div&gt;• Commons Logging (esta es para logear, si ya usas otra, puedes omitirla)&lt;/div&gt;&lt;div&gt;• iText (esta es por si generas PDF pero yo no la ocupe)&lt;/div&gt;&lt;div&gt;• POI (esta es para generar archivox XLS)&lt;/div&gt;&lt;/div&gt;&lt;pre class="brush:xml;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;groupId&amp;gt;org.apache.poi&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;artifactId&amp;gt;poi&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;version&amp;gt;3.2-FINAL&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;2. Configurar el ViewResolver&lt;/span&gt; via un &lt;u&gt;properties&lt;/u&gt;&lt;/div&gt;&lt;div&gt;Antes ya lo había hecho mediante la clase de spring XmlViewResolver para configurar las vistas en un archivo xml (views.xml) pero me pareció más sencillo mediante un archivo properties y por eso difundo esta alternativa.&lt;/div&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"&amp;gt;&lt;br /&gt;&amp;lt;property name="basename" value="views"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;Se esta configurando una instancia de ResourceBundleViewResolver que busca por los mapeos de las vistas en un archivo properties con el nombre indicado por la propiedad basename, en este caso views.properties. &amp;nbsp;Donde colocarlo? en el classpath de la aplicación.&lt;/div&gt;&lt;div&gt;&lt;i&gt;El contenido del archivo views.properties se explica en el punto 4.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;3. Crear el Template con &lt;a href="http://jasperforge.org//website/ireportwebsite/IR%20Website/ir_download.html?header=project&amp;amp;target=ireport"&gt;iReports&lt;/a&gt;&lt;/span&gt;&amp;nbsp;(yo trabajé con la version 3.5.3)&lt;/div&gt;&lt;div&gt;Una cosa que se debe tomar en cuenta es que se debe usar la &lt;u&gt;misma version de &lt;b&gt;iReports &lt;/b&gt;que la que se esta usando en el &lt;b&gt;jar&lt;/b&gt;&lt;/u&gt;&lt;b&gt; &lt;/b&gt;como dependencia.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Descarga la aplicacion iReports desde la pagina. &amp;nbsp;Luego instalala y cuando la abras basta con que crees un proyecto en blanco. Este se guarda como un archivo .jrxml que básicamente es un xml plano.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Puedes encontrar un buen manual de uso de iReports &lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=ireport"&gt;aqui&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cuando se compila un archivo jrxml, se genera otro con el mismo nombre .jasper, el cual es necesario indicar en la configuración de spring para que se genere el reporte en el formato deseado.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;4. Configurar las vistas&lt;/span&gt; en el archivo properties.&lt;/div&gt;&lt;div&gt;El framework de spring contiene 5 diferentes implementaciones para crear reportes con Jasper, cuatro de ellas corresponden a formatos específios (csv, pdf, html y xls) y una que permite determinar una de las anteriores en tiempo de ejecución (&lt;i&gt;JasperReportsMultiFormatView&lt;/i&gt;).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Para generar un reporte en pdf, por ejemplo, vamos usar el siguiente contenido en nuestro archivo views.properties:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush:plain;"&gt;reciboPago.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView&lt;br /&gt;reciboPago.url=/WEB-INF/jasperTemplates/recibo.jasper&lt;br /&gt;reciboPago.reportDataKey=reciboKey&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;El nombre de la vista es&amp;nbsp;"&lt;b&gt;reciboPago&lt;/b&gt;", su propiedad &lt;b&gt;class &lt;/b&gt;define la clase de jasper que la mapea, en este caso es la clase que genera PDFs. &amp;nbsp;Es importante que esta propiedad esté configurada como .(class) y no .class debido a que spring busca este valor vía la propiedad y no usando el acostumbrado getter/setter. &amp;nbsp;De esta manera se entiende que si no usamos los paréntesis, spring lo interpreta como el hecho que debe usar el getter/setter de dicha propiedad para acceder a su valor.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La propiedad &lt;b&gt;url &lt;/b&gt;se utiliza para definir la ruta de acceso al archivo compilado por el programa iReports, en este caso se esta colocando dentro de la carpeta WEB-INF de la aplicación.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finalmente &lt;b&gt;reportDataKey &lt;/b&gt;define el nombre llave para obtener de un mapa el POJO o DTO que contiene cada valor a mostrar en el reporte. En este caso, se le esta diciendo a spring que su fuente de datos se encuentra en la llave "reciboKey" del mapa a recibir (ver punto 5, sobre el controller).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;5. Crear el controller.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Es sumamente sencillo generar un controller en spring mediante las anotaciones:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush:java;"&gt;@Controller&lt;br /&gt;@RequestMapping("/pago")&lt;br /&gt;public class PagoController {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@RequestMapping(value="/recibo", method=RequestMethod.GET)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String generarReciboPago(ModelMap modelMap, HttpServletResponse response) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;List&amp;lt;ReciboDTO&amp;gt; lista = new ArrayList&amp;lt;ReciboDTO&amp;gt;(1);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ReciboPagoJasperDTO dto = new ReciboDTO();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;dto.setMonto("6789.0");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;dto.setNombre("Pedro Romero");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;lista.add(dto);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;response.setHeader("Content-type", "application/pdf");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;response.setHeader("Content-Disposition","attachment; filename=\"recibo.pdf\"");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;JRBeanCollectionDataSource jrbean = new JRBeanCollectionDataSource(lista, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;modelMap.put("reciboKey", jrbean);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return("reciboPago");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;@Controller define a la clase como un controller y @RequestMapping define una uri desde la cual se puede acceder a nuestro controller cuando nuesta aplicación ya está montada en un server. &amp;nbsp;Si la aplicacion levanta en un contexto "proyecto" y el servidor levanta en un puerto local 8080, podriamos acceder a nuestro controller anterior como: "&lt;a href="http://localhost:8080/proyecto/pago/recibo"&gt;http://localhost:8080/proyecto/pago/recibo&lt;/a&gt;", aunque esto es asunto de otro tema, basta con observar como se concatenan los valores del contexto de la aplicación, y de las anotaciones @RequestMapping de clase y método usado. &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;En este caso&amp;nbsp;ReciboDTO es el pojo usado para portar los valores que alimentaran el reporte, se inserta en una instancia de JRBeanCollectionDataSource y luego se agrega al mapa del modelo con el key:&amp;nbsp;reciboKey (observa que es el mismo metodo que usamos en el properties.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finalmente se devuelve una cadena que indica el nombre de la vista configurada en el properties, la cual esta mapeada a la clase jasper:&amp;nbsp;JasperReportsPdfView.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Notas importantes:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Spring nos provee de la capacidad de agregar elementos dentro de una Collection, dado que internamente Spring los envuelve dentro de un objeto JRBeanCollecionDataSource &lt;span class="Apple-style-span" style="font-size: x-small;"&gt;(implementa interface JRDataSource)&lt;/span&gt;, también nos da la capacidad de agregar mas beans al modelo en diferentes llaves del mapa, ejemplo:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush:java;"&gt;modelMap.put("reciboKey", jrbean);&lt;br /&gt;modelMap.put("myKey1", jrbean1);&lt;br /&gt;modelMap.put("personal2", jrbean2);&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;El punto está en que si la vista no esta apuntando a uno de estas llaves en particular (mediante la propiedad de la vista:&amp;nbsp;reportDataKey), usará la primera instancia de&amp;nbsp;JRDataSource que encuentre.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-8236338058667751026?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/8236338058667751026/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/configurar-jasperreports-en-spring-30.html#comment-form' title='9 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8236338058667751026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8236338058667751026'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/configurar-jasperreports-en-spring-30.html' title='Configurar JasperReports en Spring 3.0'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3215266206695009247</id><published>2010-08-24T11:38:00.001-07:00</published><updated>2010-08-24T13:27:48.104-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correos personal con postfix - Spambayes</title><content type='html'>Éste es el último post de '&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html"&gt;Servidor de correos personal con postfix&lt;/a&gt;'. Ya configurado el mismo (&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA&lt;/a&gt;, &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html"&gt;MDA&lt;/a&gt;, &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html"&gt;MUA&lt;/a&gt;) y recuperando automáticamente correos con &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_24.html"&gt;Fetchmail&lt;/a&gt;, sólo queda velar por la seguridad del servidor...&lt;br /&gt;&lt;br /&gt;Se llama spam o correo basura a los mensajes no solicitados, no deseados o de remitente desconocido, habitualmente de tipo publicitario, enviados en grandes cantidades (incluso masivas) que perjudican de alguna o varias maneras al receptor.&lt;br /&gt;&lt;br /&gt;El spam se puede convertir en una incidencia de seguridad por varias razones:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ocupa espacio en las bandejas de entrada de los receptores. En los casos de cuentas con tamaño limitado esto es un problema.&lt;/li&gt;&lt;li&gt;en sistemas vulnerables, el spam suele llegar también acompañado de scripts perniciosos, a ejecutar en el sistema receptor, o un link engañoso para infectar la máquina cliente.&lt;/li&gt;&lt;li&gt;también puede incluir información engañosa con la cual realizar un robo de información confidencial, engañando al usuario incauto&lt;/li&gt;&lt;/ul&gt;Claro está, la mejor política de seguridad en estos casos es ser prudente y no dar click y descargar todo lo que llegue a la bandeja de entrada del correo.&lt;br /&gt;&lt;br /&gt;Sin embargo, los servidores de correo también cuentan con protección extra ante esta problemática. En nuestro caso, vamos a configurar Spambayes como detector de spam. Existen muchos otros programas que realizan funciones similares, el más famoso es Spamassasin. Sin embargo en este tutorial nos enfocaremos en Spambayes.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;br /&gt;Spambayes se puede descargar desde su &lt;a href="http://spambayes.sourceforge.net/"&gt;sitio oficial&lt;/a&gt;, o puede instalarse con la distribución. En Debian el paquete se llama &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;spambayes&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuración&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Spambayes es una serie de scripts en Python que utilizan algoritmos de probabilidad para clasificar el correo, si es spam (correo no deseado), ham (correo seguro) o inseguro (no se sabe si es o no spam). Debe entrenarse constantemente la red bayesiana en la que se basa el software para refinar cada vez más su comportamiento.&lt;br /&gt;&lt;br /&gt;En la sección del MDA (Procmail) ya creamos los subdirectorios necesarios para que funcione Spambayes, así que continuaremos con la configuración. Como parte de la configuración, es necesario configurar Spambayes, pero también Procmail para que sepa dónde colocar los correos identificados, y además mutt para agregar unas cuantas utilidades que pueden servir para tratar con los distintos tipos de mensajes.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;1) Spambayes&lt;/b&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;El subdirectorio ~/Mail contendrá nuestro correo seguro.&lt;/li&gt;&lt;li&gt;El subdirectorio ~/.CaughtSpam contendrá el correo que Procmail defina como Spam de acuerdo a lo que Spambayes le indique.&lt;/li&gt;&lt;li&gt;El subdirectorio ~/.Unsure contendrá correo que Spambayes no sepa clasificar.&lt;/li&gt;&lt;li&gt;Para propósitos de entrenamiento, en ~/Mail/.MissedHam y ~/Mail/.MissedSpam iremos colocando correos que lleguen a las bandejas equivocadas, de forma que a la siguiente ronda de entrenamiento de Spambayes, sepa en adelante como clasificar dichos correos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;El script de entrenamiento es el siguiente: ~/Mail/train_spambayes&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;pre&gt;&lt;span style="font-size: small;"&gt;#!/bin/sh&lt;br /&gt;# Script to copy mail missed spam and ham into correct folders&lt;br /&gt;# and run sb_mboxtrain.py to train spambayes&lt;br /&gt;# Training will be done only on missed spam and ham&lt;br /&gt;&lt;br /&gt;# Files we saved or bounced may be in the new directory&lt;br /&gt;# We want them in cur for training&lt;br /&gt;mv /home/usuario/Mail/.MissedSpam/new/* \&lt;br /&gt; /home/usuario/Mail/.MissedSpam/cur 2&amp;gt;/dev/null&lt;br /&gt;mv /home/usuario/Mail/.MissedHam/new/* \&lt;br /&gt; /home/usuario/Mail/.MissedHam/cur 2&amp;gt;/dev/null&lt;br /&gt;/usr/bin/sb_mboxtrain.py -d /home/usuario/.hammie.db \&lt;br /&gt; -g /home/usuario/Mail/.MissedHam \&lt;br /&gt; -s /home/usuario/Mail/.MissedSpam&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;Obviamente, hay que editarlo según la cuenta de usuario y directorios usados en el servidor. Este script debe ser ejecutable:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ chmod +x ~/Mail/train_spambayes &lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Además hay que crear la base de datos en donde Spambayes se entrenará:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ /usr/bin/sb_filter.py -d $HOME/.hammie.db -n      &lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;lo cual creará el archivo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.hammie.db&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Por último, será útil que el servidor se dedique automáticamente a entrenar la red bayesiana cada cierto tiempo sin intervención del usuario, para lo que creamos un cronjob con&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ crontab -e&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;y colocamos el cronjob: &lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;21 3 * * * ~/Mail/train_spambayes&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;que entrenará a las 3:21am de todos los días.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;&lt;i&gt;2) Procmail&lt;/i&gt;&lt;/b&gt;&lt;/blockquote&gt;Ahora hay que decirle a Procmail que, dependiendo lo que diga la base de datos con la red bayesiana entrenada, clasifique los correos entrantes en los subdirectorios que creamos previamente. Editar &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.procmailrc&lt;/span&gt; para que quede así (editarlo para que coincida con los directorios y usuario en el servidor):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;SHELL=/bin/sh&lt;br /&gt;MAILDIR=$HOME/Mail&lt;br /&gt;DEFAULT=$HOME/Mail/&lt;br /&gt;CAUGHT_SPAM=$MAILDIR/.CaughtSpam/&lt;br /&gt;UNSURE=$MAILDIR/.Unsure/&lt;br /&gt;  &lt;br /&gt;#Spambayes process&lt;br /&gt;:0fw:hamlock&lt;br /&gt;| /usr/bin/sb_filter.py -d /home/usuario/.hammie.db&lt;br /&gt;&lt;br /&gt;:0&lt;br /&gt;* ^X-Spambayes-Classification: spam&lt;br /&gt;${CAUGHT_SPAM}&lt;br /&gt;&lt;br /&gt;:0&lt;br /&gt;* ^X-Spambayes-Classification: unsure&lt;br /&gt;${UNSURE}&lt;br /&gt;&lt;br /&gt;# Catches everything else.&lt;br /&gt;# Anything left over goes into the DEFAULT folder&lt;br /&gt;:0:&lt;br /&gt;${DEFAULT}&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;Lo que hicimos fue decirle a Procmail que con el script &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sb_filter.py&lt;/span&gt; clasifique el correo, y lo mande a los directorios de &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CaughtSpam&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Unsure&lt;/span&gt; o el &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Default&lt;/span&gt; (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/Mail&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;3) mutt&lt;/b&gt;&lt;/i&gt;&lt;/blockquote&gt;Por último, si observamos la bandeja de entrada con mutt, es probable que encontremos correo que deseemos clasificar como Spam. La opción manual sería mover manualmente estos correos a los directorios creados, a través de los comandos de mutt.&lt;br /&gt;&lt;br /&gt;Sin embargo, esto no es funcional, por lo que editaremos el archivo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.muttrc&lt;/span&gt; para agregar un poco de automatización que facilite este proceso.Editarlo para que quede así:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set editor="emacs"&lt;/span&gt;&lt;br /&gt;set folder = /home/usuario/Mail&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set signature="~/.signature"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;my_hdr From: Nombre Usuario&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Don't ask to move read message&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set move=no&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Header control   h displays header when in pager&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# I want to only see the unignored by default&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ignore *                                        # weed out all headers&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unignored date from: to cc subject organization  # now show me these...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Setting these macros is going to save us all of that time I was&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  talking about.  Now instead of having to type all of those&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  characters to move the mail around we will can just tag the messages&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  and, for the instance of spam in your inbox, hit 'S'.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Move mail to correct directories&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   S       ";s~/Mail/.MissedSpam\r\r$\r"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   S       ";s~/Mail/.MissedSpam\r\r$\r"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   H       ";C~/Mail/.MissedHam\r\r;s~/Mail\r\r$\r"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   H       ";C~/Mail/.MissedHam\r\r;s~/Mail\r\r$\r"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   M       ";s~/Mail/\r"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   M       ";s~/Mail/\r"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# This is how we are going to move around to the different&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  mailboxes.  Hitting 'alt-1' will take us to our inbox&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  'alt-2' and we are looking at the mail Spambayes classified&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  as spam.  etc.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  The extra mailboxes I have in here are for mailing lists I am on.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  I will show the procmail recipe that automatically puts&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  the mailing list mail into its correct mailbox further down.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Move to mailboxes quickly&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   &lt;esc&gt;1  "c~/Maildir\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   &lt;esc&gt;1  "c~/Maildir\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   &lt;esc&gt;2  "c~/Maildir/.CaughtSpam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   &lt;esc&gt;2  "c~/Maildir/.CaughtSpam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   &lt;esc&gt;3  "c~/Maildir/.Unsure\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   &lt;esc&gt;3  "c~/Maildir/.Unsure\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Training Maildirs for Spam and Ham&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   &lt;esc&gt;8  "c~/Maildir/.MissedSpam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   &lt;esc&gt;8  "c~/Maildir/.MissedSpam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   index   &lt;esc&gt;9  "c~/Maildir/.MissedHam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;macro   pager   &lt;esc&gt;9  "c~/Maildir/.MissedHam\r"&lt;/esc&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Setting these colors makes it easy to tell which emails&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  Spambayes has missed.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Turn spam red and unsure green&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color index red default "~h '^X-Spambayes-Classification: spam'"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color index green default "~h '^X-Spambayes-Classification: unsure'"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Turn gmail mail brightblue&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  (My regular expression is not correct here.  I think that it&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#   is looking anywhere in the header for my gmail address&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#   instead of what I wanted..  Just in the 'To:'.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#   It still works for the most part)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color index brightblue default "~h '(^)*my_name@gmail.com'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Lets set more colors to make things look beautiful.  Judging by&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  my title for this section I must have had bad feelings towards&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#  colors when I added this.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#Color crap&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color index brightwhite default ~N       # color for new messages&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color status black yellow&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color attachment brightyellow default    # file attachments&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color search brightred default           # search matches&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color quoted brightyellow default        # quoted text in replies&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color quoted1 magenta default            # quoted text in replies&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color body cyan default "((ftp|http|https)://|news:)[^ &amp;gt;)\"\t]+"   # URLs&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;color body cyan default "[-a-z_0-9.+]+@[-a-z_0-9.]+"               # email&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Con esto conseguimos que mutt nos proporcione lo siguiente:&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Si estamos ante un mensaje que debió clasificarse como Spam y no lo fue (en la bandeja de entrada o en Unsure), tecleando '&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;S&lt;/span&gt;' se mueve a los directorios correctos (CaughtSpam y MissedSpam) en espera del siguiente entrenamiento.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Si estamos ante un mensaje que debió clasificarse como Ham y no lo fue (en la bandeja de Spam o en Unsure), tecleando '&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;H&lt;/span&gt;' se mueve a los directorios correcots (bandeja de entrada y MissedHam) en espera del siguiente entrenamiento.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Podemos seleccionar varios mensajes a la vez con el comando &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;'&lt;/span&gt;t&lt;/span&gt;'. &lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Esc + 1&lt;/span&gt; nos lleva directamente a la bandeja de entrada.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Esc + 2&lt;/span&gt; al spam&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Esc + 3&lt;/span&gt; a Unsure&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Esc + 8&lt;/span&gt; a MissedSpam&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Esc + 9&lt;/span&gt; a MissedHam&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Además, dependiendo el tipo de correo, mutt utilizará colores (si la consola los soporta) para mostrar los distintos tipos de mensajes.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt; &lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;/ul&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Spambayes es una herramienta bastante poderosa, que también permite entrenar para clasificar correos con base en otros criterios, por ejemplo si estuviéramos suscritos a un mailing list, colocar los correos de dicha lista de correos en un directorio particular; o si recibiéramos correos de ofertas de trabajo para colocar todos ellos en otro subdirectorio, etc. &lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;br /&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;br /&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;br /&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;b&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Notas Finales&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/b&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Con esto damos por terminado el tutorial para levantar un servidor de correos personal utilizando Postfix.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;br /&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Aún quedan detalles por afinar, que podrían investigarse. Si algún día tengo el tiempo, tal vez haga tutoriales para los mismos:&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Levantar un servidor de correos que pueda usar en una organización, a través de una LAN o internet, es cuestión que debe configurarse en Postfix. La documentación del sitio oficial de este programa ofrece varios escenarios para lograr distintas configuraciones deseadas.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Levantar servidores POP e IMAP, con Courier por ejemplo, para poder leer los correos que lleguen a la cuenta en el servidor a través de internet, con Squirrelmail, con un dispositivo móvil, con un cliente convencional en otra máquina, o con Fetchmail en otra máquina cliente.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;li&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Ampliar el funcionamiento de Spambayes para que clasifique correos con base en criterios como el uso de mailing lists o aquellos que pertenezcan a mis búsquedas de empleo, por ejemplo.&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/li&gt;&lt;/ul&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;br /&gt;&lt;br /&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;&lt;esc&gt;Espero hayas disfrutado siguiendo este tutorial, como yo haciéndolo. Y sobre todo, levantando tu propio servidor de correos. A mi me llevó meses enterarme bien de cómo funciona todo esto, y lograr que funcionara correctamente. Ojalá esta pequeña guía sirva de ayuda para el que se aventure en un camino similar...&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;/esc&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-3215266206695009247?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/3215266206695009247/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_9803.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3215266206695009247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3215266206695009247'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_9803.html' title='Servidor de correos personal con postfix - Spambayes'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-1404924402978019601</id><published>2010-08-24T11:38:00.000-07:00</published><updated>2010-08-24T13:27:48.105-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correos personal con postfix - Fetchmail</title><content type='html'>Con este post continuamos con el '&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html"&gt;Servidor de correos personal con postfix&lt;/a&gt;'. Una vez configurados el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA&lt;/a&gt;, el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html"&gt;MDA&lt;/a&gt; y el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html"&gt;MUA&lt;/a&gt;, quedan detalles por afinar...&lt;br /&gt;&lt;br /&gt;Fetchmail es un programa para recuperar correos desde servidores remotos. En realidad no es más que un cliente para los protocolos POP, IMAP, entre otros, que en lugar de desplegar los mensajes de correo (como cualquier cliente convencional de estos protocolos) los descarga para que sean recibidos en la máquina especificada y leídos posteriormente.&lt;br /&gt;&lt;br /&gt;Es útil para conexiones de internet intermitentes (que no siempre están en línea), o para mantener una bandeja de entrada sincronizada con un servicio de correo remoto, como será el caso de este tutorial. &lt;br /&gt;&lt;br /&gt;Obra del renombrado hacker Eric S. Raymond, Fetchmail es incluso el ejemplo clásico utilizado en su escrito 'La Catedral y el Bazar' para ilustrar cómo el proceso de desarrollo open source es un éxito, y no un caso aislado como se pensaba hasta el momento del kernel Linux. Este escrito fue de hecho la chispa que encendió el furor por el open source en el mundo empresarial, con lo que Netscape liberó el código fuente de su navegador (del que Mozilla Firefox es su heredero), y demás aventuras y desventuras del mundo del open source y el software libre desde entonces (1998)...&lt;br /&gt;&lt;br /&gt;Aquí lo vamos a utilizar para recuperar los correos de una cuenta de Gmail (aunque podría ser cualquier otra, ¡o varias! siempre y cuando acepten los protocolos POP, IMAP o similares) cada cierto tiempo.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;br /&gt;Fetchmail se puede descargar desde su &lt;a href="http://fetchmail.berlios.de/"&gt;sitio oficial&lt;/a&gt;. O como siempre, puede instalarse desde la distribución de GNU/Linux que se tenga. En el caso de Debian el paquete es &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fetchmail&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Si se desea también se puede instalar el paquete &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fetchmailconf&lt;/span&gt; que es un script en Python, modo gráfico, para configurar fácilmente el programa.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuración&lt;/b&gt;&lt;br /&gt;Aunque se utilice fetchmailconf, aquí describiremos el tras bambalinas de la configuración de Fetchmail, para entender cómo funciona.&lt;br /&gt;&lt;br /&gt;Todo se hace en archivos RC, que pueden ser por usuario (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.fetchmailrc&lt;/span&gt;) o de todo el sistema (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/etc/fetchmailrc&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;El archivo deberá contener las siguientes líneas:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set postmaster "postmaster"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set bouncemail&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set no spambounce&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set properties ""&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set daemon 600&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;poll pop.gmail.com with proto POP3 port 995&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; user 'gmailuser@gmail.com' there with ssl with&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; password 'password' is 'usuarioservidor' here options &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; keep&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;Obviamente, hay que editar la información pertinente para la cuenta de Gmail, el password y el nombre de usuario del sistema.&lt;br /&gt;&lt;br /&gt;La línea &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;daemon&lt;/span&gt; establece que fetchmail quedará ejecutándose en segundo plano, y que revisará por nuevos correos en la o las cuentas especificadas cada 600 segundos (10 minutos).&lt;br /&gt;&lt;br /&gt;Se pueden tener tantas líneas &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;poll&lt;/span&gt; como se desee, una por cuenta de correo que se desee sincronizar.&lt;br /&gt;&lt;br /&gt;Más información se encuentra en la documentación de Fetchmail.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Uso&lt;/b&gt;&lt;br /&gt;Bastará habilitar el script de inicio del servicio de Fetchmail en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/etc/init.d&lt;/span&gt; para comenzar a ejecutarlo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;¡Listo! el servidor de correo personal ya está tomando forma. Cada 600 segundos (o el tiempo que se hubiera especifidado), Fetchmail debería de revisar la bandeja de la cuenta establecida, y en caso de encontrar nuevos correos, descargarlos. De hecho en el archivo de log de Postfix (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/var/log/mail.info&lt;/span&gt;) debería de observarse actividad, cada 600 segundos cuando se despierte Fetchmail y se vuelva a dormir, además de cuando llegue a descargar correos.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Por último, vamos a enfocarnos en la seguridad, en el caso particular de este tutorial, a &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_9803.html"&gt;protegernos del spam&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-1404924402978019601?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/1404924402978019601/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_24.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1404924402978019601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1404924402978019601'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_24.html' title='Servidor de correos personal con postfix - Fetchmail'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-2517629732287405323</id><published>2010-08-24T11:37:00.002-07:00</published><updated>2010-08-24T13:27:48.106-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correos personal con postfix - MUA</title><content type='html'>Continuamos con los posts dedicados a configurar un '&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html"&gt;Servidor de correo personal con postfix&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;Previamente ya configuramos el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA, Mail Transfer Agent&lt;/a&gt; y el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html"&gt;MDA, Mail Delivery Agent&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ahora vamos por el MUA, Mail User Agent, el cliente para leer y enviar correos. Normalmente esta parte es la que la gente toma como si fuera todo el sistema de correo, pero como ya hemos podido ver se trata de toda una infraestructura de sistemas.&lt;br /&gt;&lt;br /&gt;En este tutorial vamos a configurar mutt como cliente de correo. Se trata de un cliente de consola muy sencillo pero muy completo a la vez. La razón es que su configuración es sencilla para los propósitos de este tutorial. Además, su sencillez permite entender un poco más cómo funciona el correo electrónico, que es de lo que se trata aquí.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Si lo que se pretende es utilizar algún otro software como cliente de email, habrá que hacer un poco de investigación para, por ejemplo, acceder al buzón desde Thunderbird, Evolution, Outlook, etc. Sin embargo, el proceso no debe de ser complicado.&lt;br /&gt;&lt;br /&gt;En algún tutorial posterior, hablaremos de los protocolos POP e IMAP, que permitirán ver el correo de nuestro servidor personal desde cualquier cliente conectado a internet, desde clientes web (como Squirrelmail) hasta el uso de cualquier cliente que soporte estos protocolos (como en un dispositivo móvil), pasando también, claro, por los clientes convencionales ya mencionados, pero conectándose vía internet al servidor.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;br /&gt;mutt se instala en Debian con el paquete &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mutt&lt;/span&gt;. También puede descargarse desde su &lt;a href="http://www.mutt.org/"&gt;sitio oficial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuración&lt;/b&gt;&lt;br /&gt;Lo primero es establecer una variable de entorno para que mutt sepa en donde buscar el email a leer:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ export MAIL='~/Mail'&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;obviamente, el nombre del subdirectorio cambia de acuerdo a lo configurado en Postfix. Esta línea no basta con ejecutarla y ya, debería de colocarse en algún script, como &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.bashrc&lt;/span&gt; para que se ejecute cada vez que se inicia una nueva sesión de consola, de lo contrario sólo durará mientras dure la sesión actual.&lt;br /&gt;&lt;br /&gt;Otra manera de configurarlo es através de un archivo de configuración por usuario: ~/.muttrc&lt;br /&gt;que debería de incluir esta línea:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set folder = /home/jstitch/Mail&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;Si somos usuarios adictos a la consola, seguramente tendremos un editor de preferencia... En mi caso uso Emacs. El editor de preferencia se configura con la siguiente línea: &lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set editor=emacs&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Esto es importante: como todos los buenos programas que siguen la filosofía Unix, mutt se especializa en una sola cosa: es un MUA, un cliente de correo. ¡Ni siquiera cuenta con su propio editor de texto! De esta forma delega la responsabilidad de redactar un correo al editor que se defina, o al que esté definido por defecto en el sistema. Con esto además, el usuario será libre de elegir su propio editor, para que se sienta más a gusto. En un cliente de correo convencional por lo general se cuenta con el editor que proporcione el cliente, ¡que poca libertad de elección!&lt;br /&gt;&lt;br /&gt;Otras configuraciones interesantes para mutt (¡y hay muchas más! basta ver la documentación en el sitio oficial...)&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;set signature="~/.signature"&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;establece el archivo que contiene la firma predefinida para los correos enviados. Habrá que crear dicho archivo y ponerle algún contenido. Como todos los verdaderos buenos clientes de correo, mutt agrega un par de guiones '--' antes de la firma para que quien lea los correos sepa que se trata de la firma, y no más del cuerpo del correo.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;my_hdr From: Javier Novoa C. &lt;jstitch@invernalia.homelinux.net&gt;&lt;/jstitch@invernalia.homelinux.net&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;establece el header From que llevarán los correos a enviar con mutt&lt;br /&gt;&lt;br /&gt;Además, mutt puede utilizar con el archivo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.muttprintrc&lt;/span&gt; que permite definir instrucciones para imprimir los correos.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Uso&lt;/b&gt;&lt;br /&gt;mutt se ejecuta en consola. Para lanzarlo hay que teclear&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mutt&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;aparecerá una pantalla ocupando toda la consola, pues mutt utiliza &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ncurses&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Los comandos que acepta mutt son básicamente letras para realizar acciones.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;m&lt;/span&gt; permite enviar un mail, solicitará el destino, el asunto y luego abrirá el editor para redactar el mensaje. Basta guardarlo en donde lo haya solicitado mutt y salir para que se tenga el email redactado. Luego con &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Y&lt;/span&gt; se enviará el correo.&lt;br /&gt;&lt;br /&gt;La pantalla está casi totalmente ocupada por la bandeja de entrada en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/Mail&lt;/span&gt; (o donde sea que se haya configurado). Si hay correos, estos aparecerán aquí. Con las flechas se puede navegar para seleccionar un mensaje, y con INTRO para verlo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;D&lt;/span&gt; permite borrar el mensaje seleccionado&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;q&lt;/span&gt; permite salir&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;?&lt;/span&gt; proporciona la ayuda, más completa que esta, del programa.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Notas finales&lt;/b&gt;&lt;br /&gt;Y ahora es tiempo de terminar de configurar el MTA, como se había dicho en el post correspondiente. Aún faltaba el detalle de permitir que Gmail enviara correos a nombre del servidor, sin usar el remitente con la dirección de Gmail.&lt;br /&gt;&lt;br /&gt;Ya se explicó cómo configurar Gmail para esto, pero faltaba validar el proceso.&lt;br /&gt;Si todo se realizó correctamente, tuvo que haber llegado a la bandeja de entrada un correo de parte de Gmail para validar. Habrá que acceder a una URL para terminar la validación, o copiar un código de verificación y usarlo en la misma configuración de Gmail para terminar.&lt;br /&gt;&lt;br /&gt;Hecho esto, la dirección de correo especificada, usuario@dominio, deberá de aparecer en la lista de orígenes válidos de Gmail, y en adelante los correos enviados desde el servidor deberían de llegar a sus destinos como proviniendo del servidor, no de Gmail (aún cuando Gmail se siga usando como relay para poder enviar dichos correos).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Y listo, con esto ya se tiene un sistema de correo funcional para enviar y recibir correos. Aún vamos a configurar un par de programas que resultarán muy útiles para terminar este tutorial.&lt;br /&gt;&lt;br /&gt;Empecemos con &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_24.html"&gt;Fetchmail&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-2517629732287405323?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/2517629732287405323/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2517629732287405323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2517629732287405323'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html' title='Servidor de correos personal con postfix - MUA'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-5715925596205702807</id><published>2010-08-24T11:37:00.001-07:00</published><updated>2010-08-24T13:27:48.108-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correo personal con postfix - MDA</title><content type='html'>Continuamos con los posts dedicados a configurar un '&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html"&gt;Servidor de correo personal con postfix&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;Previamente ya configuramos el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA, Mail Transfer Agent&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Toca el turno del MDA, Mail Delivery Agent, el cual cumple las funciones de un 'cartero' al que la central de correos (el MTA) le entrega el correo a ser entregado en los buzones correctos.&lt;br /&gt;&lt;br /&gt;En la configuración del MTA se especificó que se usaría el programa Procmail para realizar las labores de entrega, y es el software que vamos a instalar y configurar a continuación.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;Procmail puede descargarse desde su &lt;a href="http://www.procmail.org/"&gt;sitio oficial&lt;/a&gt;, o instalarse con las utilidades de la distribución de GNU/Linux en uso. Para Debian, el paquete se llama &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;procmail&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;La configuración no se lleva mucho. En realidad implica crear unos subdirectorios, un archivo de configuración y el de logging. Y además, mucha de esta configuración es en parte un preparar terreno para los siguientes programas que vamos a configurar.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Subdirectorios para recibir el correo&lt;/li&gt;&lt;/ul&gt;En primer lugar, nos aseguramos de que exista el subdirectorio &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$HOME/Mail&lt;/span&gt; (o como le hayamos puesto en la configuración de Postfix).&lt;br /&gt;&lt;br /&gt;Posteriormente, hay que crear unos subdirectorios aquí, para que el cliente de correo (mutt) sepa si el correo es nuevo, o si ya fue leído, y para tener un directorio de trabajo temporal:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ mkdir -p ~/Mail/{new, cur, tmp}&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Hecho eso, vamos a preparar el terreno para Spambayes, que utilizará algunos subdirectorios para almacenar el correo dependiendo el tipo de correo que llegue (seguro, spam o inseguro):&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mkdir -p ~/Mail/{.MissedSpam, .MissedHam, .CaughtSpam, .Unsure}&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mkdir -p ~/Mail/.MissedSpam/{new, cur, tmp}&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mkdir -p ~/Mail/.MissedHam/{new, cur, tmp}&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mkdir -p ~/Mail/.CaughtSpam/{new, cur, tmp}&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mkdir -p ~/Mail/.Unsure/{new, cur, tmp}&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Archivo de configuración&lt;/li&gt;&lt;/ul&gt;Lo siguiente es crear el archivo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.procmailrc&lt;/span&gt; para configurar Procmail. Nótese que este archivo es personal, por cuenta de correo, pues cada uno tiene una cuenta de correo personal. Sin embargo, debe de ser posible definir alguna configuración global, siempre cuidando que se apunte a los directorios apropiados para cada usuario y su cuenta de correo, evitando problemas de privacidad.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SHELL=/bin/sh&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;MAILDIR=$HOME/Mail/&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DEFAULT=$HOME/Mail/&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VERBOSE=on&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LOGFILE=/var/log/procmail&lt;/span&gt;&lt;br /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;:0:&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;${DEFAULT}&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;Lo que estamos diciendo es, simplemente, definir el directorio en el que reside el correo para el usuario. Nótese que para &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;MAILDIR&lt;/span&gt; y &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DEFAULT&lt;/span&gt; el nombre del subdirectorio termina con &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/&lt;/span&gt; . Si no terminara así, Procmail asume que se trata de un archivo, y entonces busca colocar los correos todos dentro de un mismo archivo (al estilo del viejo comando &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail&lt;/span&gt;). Sin embargo, con la notación de la &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/&lt;/span&gt; al final, se logra que Procmail deposite los correos en el subdirectorio indicado, con los subdirectorios &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cur&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;new&lt;/span&gt; y &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;tmp&lt;/span&gt; previamente creados.&lt;br /&gt;&lt;br /&gt;El último par de líneas le indican a Procmail que deposite todos los correos que lleguen en el subdirectorio marcado como &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DEFAULT&lt;/span&gt;. Posteriormente cuando configuremos Spambayes haremos una modificación aquí, para que Procmail sepa diferenciar entre spam y correo seguro (utilizando los subdirectorios que ya creamos aquí mismo).&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Archivo de registro (logging)&lt;/li&gt;&lt;/ul&gt;La línea &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LOGFILE&lt;/span&gt; del archivo .procmailrc define el archivo de logging. Hay que crear previamente este archivo, y en caso de ser un archivo de sistema, cuidar que los permisos sean los adecuados para que el proceso de Procmail escriba en ellos, de lo contrario el log de Postfix indicará un error de que Procmail no pudo escribir sobre el archivo de log, situación que debe corregirse.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Prueba&lt;/b&gt;&lt;br /&gt;Hecho esto ya podríamos probar la recepción de correos, aunque sin MUA todavía, sería difícil y complicado revisar el correo de esta manera:&lt;br /&gt;&lt;br /&gt;Desde alguna dirección de prueba, enviarnos un correo a nuestra dirección de correo del servidor, nombreusuario@dominio .&lt;br /&gt;&lt;br /&gt;Si todo quedó bien configurado, Postfix debería de recibir el correo, entregárselo a Procmail y este depositarlo en el directorio ~/Mail/new&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Breve nota cultural&lt;/b&gt;&lt;br /&gt;Todo el correo electrónico y los protocolos para el mismo se basan en archivos de texto plano, por lo que aunque el correo incluyera attachments o código HTML, podría abrirse en cualquier editor de texto.&lt;br /&gt;&lt;br /&gt;¿Cómo le hacen los clientes para desplegar el correo cuando existen archivos adjuntos o código HTML?&lt;br /&gt;&lt;br /&gt;Todo esto tiene que ver con los protocolos definidos por la IETF (Internet Engineering Task Force) para el correo electrónico, en algunos documentos RFC. Desde mi punto de vista son muy interesantes y accesibles (aunque en inglés):&lt;br /&gt;&lt;br /&gt;Por ejemplo, el correo electrónico per se original se define en el &lt;a href="http://www.rfc-editor.org/rfc/rfc2822.txt"&gt;RFC 2822&lt;/a&gt;&lt;br /&gt;El uso de archivos adjuntos en realidad se logra gracias al uso de MIME: RFCs &lt;a href="http://www.rfc-editor.org/rfc/rfc2045.txt"&gt;2045&lt;/a&gt; a &lt;a href="http://www.rfc-editor.org/rfc/rfc2049.txt"&gt;2049&lt;/a&gt;&lt;br /&gt;El uso de código HTML es parte de la definición del correo electrónico: RFC2822&lt;br /&gt;Otros RFC de interés:&lt;br /&gt;Protocolo SMTP: &lt;a href="http://www.rfc-editor.org/rfc/rfc2821.txt"&gt;RFC 2821&lt;/a&gt;&lt;br /&gt;Protocolo original de email, que duró casi 20 años: &lt;a href="http://www.rfc-editor.org/rfc/rfc822.txt"&gt;RFC 822&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dicho esto, continuemos con el cliente de correo, el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html"&gt;MUA&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-5715925596205702807?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/5715925596205702807/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5715925596205702807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5715925596205702807'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html' title='Servidor de correo personal con postfix - MDA'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3633141288026557733</id><published>2010-08-24T11:37:00.000-07:00</published><updated>2010-08-24T13:27:48.109-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correo personal con postfix - MTA</title><content type='html'>Esta es la parte 1 de una serie de posts que vienen de '&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html"&gt;Servidor de correo personal con postfix&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;Para configurar el servidor, vamos a asumir que, teniendo una dirección IP dinámica, se cuenta con un nombre de dominio dinámico, por ejemplo como el que ofrece DynDNS. &lt;br /&gt;&lt;br /&gt;Recordar que el MTA, Mail Transfer Agent es el encargado de mandar los mensajes de correo que salgan del servidor, así como de recibir en primer instancia los mismos para entregárselos al MDA que los debe dejar en los buzones correctos.&lt;br /&gt;&lt;br /&gt;Como MTA utilizaremos Postfix, un MTA bastante popular hoy en día en servidores GNU/Linux.&lt;br /&gt;Cabe decir que si no se tiene MTA, el comando &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail&lt;/span&gt; nativo de GNU/Linux permite enviar emails únicamente a los usuarios de la misma máquina que funge como servidor. Fuera de eso no se puede enviar ningún tipo de correo (ni en la misma LAN ni por internet a otros dominios de correo): se necesita configurar el MTA (además de que para usar solamente &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail&lt;/span&gt; este tutorial pierde todo su sentido...)&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;br /&gt;El primer paso será instalar Postfix.&lt;br /&gt;Se puede descargar el código fuente del &lt;a href="http://www.postfix.org/"&gt;sitio oficial&lt;/a&gt;, o se puede instalar la versión que venga en la distribución GNU/Linux que se esté utilizando.&lt;br /&gt;&lt;br /&gt;En el caso de Debian Lenny, se debe instalar el paquete llamado &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;postfix&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En esta distribución, esto instala por default también &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;libsasl2-2&lt;/span&gt;, paquete necesario para la autenticación con gmail que se pretende instalar.&lt;br /&gt;&lt;br /&gt;En otras palabras, la instalación requiere de instalar Postfix con soporte para SASL.&lt;br /&gt;&lt;br /&gt;Además, para los certificados públicos de autenticación, se requerirá instalar OpenSSL (paquete &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;openssl&lt;/span&gt;), que incluya los certificados Thawte y Equifax. Estos se encuentran en el paquete &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ca-certificates&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuración&lt;/b&gt;&lt;br /&gt;El siguiente paso es configurar el software.&lt;br /&gt;&lt;br /&gt;Postfix se configura en los archivos del directorio /etc/postfix (o al menos ahí es por default en Debian)&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;main.cf&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Este archivo contiene las configuraciones principales de Postfix.&lt;br /&gt;Las configuraciones principales son:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#poner aqui el nombre de tu dominio&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;myorigin = nombredominio.homelinux.net&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#autenticación para Gmail&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;smtp_use_tls=yes&lt;br /&gt;smtp_tls_session_cache_database = btree:${data_directory}/smtpd_scache&lt;br /&gt;smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache&lt;br /&gt;&lt;br /&gt;#mas abajo explicamos como generar el archivo cacert.pem &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;smtp_tls_CAfile = /etc/postfix/cacert.pem&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#SASL para autenticación con Gmail&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;smtp_sasl_auth_enable = yes&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;#mas abajo explicamos sobre el archivo passwd &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;smtp_sasl_password_maps = hash:/etc/postfix/sasl/passwd&lt;br /&gt;&lt;br /&gt;smtp_sasl_security_options = noanonymous&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#nombre del dominio, con que coincida con myorigin basta&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mydomain = $myorigin&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#el nombre del host seria el nombre de la maquina servidor &lt;br /&gt;#que tenga tu servidor cuando instalaste GNU/Linux y el &lt;br /&gt;#nombre de tu dominio &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;myhostname = nombremaquinaservidor.$mydomain&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#con que nombres se identifica tu destino de correo local &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mydestination = $mydomain, $myhostname, localhost.$mydomain, localhost&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#quienes pueden enviar correos usando este servidor. es &lt;br /&gt;#MUY importante ajustar esta opcion a lo que se quiera. Yo &lt;br /&gt;#lo tengo asi (valor 'host') para solo enviar desde mi &lt;br /&gt;#maquina servidor. El valor 'subnet' (default) permite que &lt;br /&gt;#maquinas en la misma subred del servidor envien correos &lt;br /&gt;#desde el server. El valor 'class' permite que el server &lt;br /&gt;#envie correos desde cualquier máquina en la misma clase &lt;br /&gt;#de red (A,B,C) en que se esté - con una máquina con IP&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;#dinámica proporcionada por un ISP provocaría que todas &lt;br /&gt;#las máquinas de la subred del ISP envíen correos desde el &lt;br /&gt;#servidor, MUCHO CUIDADO CON ESTO!&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mynetworks_style = host&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;#si se quiere que otras maquinas puedan enviar correos &lt;br /&gt;#desde este servidor, tambien se puede establecer la &lt;br /&gt;#opcion mynetworks a un rango de IPs (en notación CIDR). &lt;br /&gt;#MUCHO CUIDADO con esto, no dejarlo abierto a todo el &lt;br /&gt;#internet, o los spammers abusarán de tu servidor para &lt;br /&gt;#enviar correos desde aquí. Esto además seguro que &lt;br /&gt;#provocará la cancelación de tu servicio con tu ISP...&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#este es importante: con el se le dice a postfix que se &lt;br /&gt;#conecte al relay de gmail para enviar correos &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;relayhost = [smtp.gmail.com]:587&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#que tipo de mensajes loggeara postfix. Yo lo deje asi por &lt;br /&gt;#hacer pruebas, pero no tiene que ser tan detallado &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;notify_classes = 2bounce, delay, policy, protocol, resource, software&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#desde que interfaces de red de tu maquina se puede enviar &lt;br /&gt;#correos...&lt;br /&gt;inet_interfaces = all&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#en donde estaran los alias para usar en las direcciones &lt;br /&gt;#de correo usuario@dominio (se explica mas adelante)&lt;br /&gt;alias_maps = hash:/etc/aliases&lt;br /&gt;alias_database = hash:/etc/aliases&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;#postfix debe saber como acceder al MDA. En este caso &lt;br /&gt;#usamos procmail... &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mailbox_command = procmail -a "$EXTENSION"&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;#otras opciones... &lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;mailbox_size_limit = 0&lt;br /&gt;recipient_delimiter = +&lt;br /&gt;html_directory = /usr/share/doc/postfix/html&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;#con esta opcion le decimos a Postfix que queremos que los &lt;br /&gt;#mails se reciban en un directorio Mail dentro del &lt;br /&gt;#directorio $HOME del usuario... podriamos especificar un &lt;br /&gt;#archivo estilo /var/mail (sin / al final) para que &lt;br /&gt;#coloque todos los emails en un solo archivo. Pero para &lt;br /&gt;#configurar correcta y facilmente procmail y sobre todo &lt;br /&gt;#spambayes, y para tener mejor control, va a ir todo en un&lt;br /&gt;#directorio especificado aqui...&lt;/span&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;home_mailbox = Mail/&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;sasl/passwd&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;En este archivo se colocará la autenticación al relay (Gmail) que usará nuestro servidor:&lt;br /&gt;&lt;blockquote&gt;&lt;pre style="background-color: #eeeeee;"&gt;&lt;span style="font-size: small;"&gt;[smtp.gmail.com]:587    unacuenta@gmail.com:unacontraseña&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;Es importante proteger este archivo correctamente, cambiando sus permisos:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;pre&gt;&lt;span style="font-size: small;"&gt;$ chmod 600 /etc/postfix/sasl/passwd&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;Por último, hay que convertir el archivo a un formato adecuado para Postfix, para lo cual existe la utilidad postmap:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;pre&gt;&lt;span style="font-size: small;"&gt;$ postmap /etc/postfix/sasl/passwd&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;cacert.pem&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Para autenticarse correctamente con Gmail, además del usuario y password, es importante utilizar un certificado público de seguridad válido. Según la fuente en que me basé, son necesarios los certificados de Thawte y/o Equifax, que se colocan en este archivo de la siguiente manera:&lt;br /&gt;&lt;blockquote&gt;&lt;pre style="background-color: #eeeeee;"&gt;&lt;span style="font-size: small;"&gt;$ cat /etc/ssl/certs/Thawte_Premium_Server_CA.pem &amp;gt;&amp;gt; /etc/postfix/cacert.pem&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="background-color: #eeeeee; font-size: small;"&gt;$ cat /etc/ssl/certs/Equifax_Secure_CA.pem &amp;gt;&amp;gt; /etc/postfix/cacert.pem&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Obviamente, es importante localizar los archivos origen *.pem en la instalación que se tenga.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;/etc/aliases&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Este archivo contiene los alias que Postfix reconocerá para sus usuarios especiales, de forma que sepa a qué buzón real redireccionar los mensajes que vayan a estos usuarios... En este archivo colocar entonces:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;pre&gt;&lt;span style="font-size: small;"&gt;root: nombreusuario&lt;br /&gt;spam: nombreusuario&lt;br /&gt;ham:  nombreusuario&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;El primer alias es para los correos que se dirijan a la cuenta root del sistema. Los otros dos se usarán para spambayes. Podría haber otros alias también, como postmaster, entre otros. Lo mejor por ahora es no moverlos y dejarlos tal como estén.&lt;br /&gt;&lt;br /&gt;Por último hay que dejar el archivo de alias en un formato que Postfix pueda usar:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ postalias aliases&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;firewall&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Y para terminar, no hay que olvidar abrir los puertos pertinentes para que Postfix se pueda comunicar con otros servidores de correo. En particular, el puerto a abrir es el TCP 25, el puerto por default del protocolo SMTP.&lt;br /&gt;&lt;br /&gt;Aquí cabe hacer una aclaración. Mi ISP es Prodigy Infinitum, y luego de unos quebraderos de cabeza, me di cuenta utilizando &lt;a href="http://nmap.org/"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;nmap&lt;/span&gt;&lt;/a&gt; que el puerto 25 lo podía tener abierto en mi servidor, pero visto desde afuera parecía como si estuviera cerrado (con lo que podría tener un servidor de correo para mi LAN, pero no más). Investigando supe que Telmex, la compañía que lleva el servicio de Prodigy Infinitum en México, cierra por defecto a sus usuarios de domicilio particular el puerto 25, para evitar abusos y spam y demás. Lo que tuve que hacer (quien sabe si tu lo tengas que hacer también, dependerá de tus condiciones) fue interactuar con ellos, así que tuve que salirme de mi segura consola dentro de mi servidor, llamar por teléfono a Telmex y pedir que me abrieran el puerto 25. Según lo que estipula la medida es posible hacer esto para que se abra el puerto 25. Aclaré que sería para propósitos de 'mi trabajo' y de uso particular exclusivamente. Prometiendo no solamente no mandar spam ni abusar del servicio, sino también configurar correctamente mi máquina (jamás dije que era un servidor, no fueran a sospechar equivocadamente que haría otra cosa) para que nadie abusara del servicio (recuerda la configuración &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;my_networks_style&lt;/span&gt; y &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;my_networks&lt;/span&gt; en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;main.cf&lt;/span&gt;). Y está claro que no abuso del servicio... el sistema de correo electrónico es muy quisquilloso (y con razón), y es capaz de detectar la fuente de spam fácilmente, etiquetar a los servidores que son fuente del mismo, y si se reporta esto a Telmex, bien podría cerrarme el puerto, o cancelarme el servicio! incluso si no soy yo la fuente del spam, bastará que lo configure mal para provocar esto...&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;Gmail&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Como parte de la configuración del servidor, puesto que se va a usar Gmail como el relay para enviar correos, es necesario configurar este servicio para poder obtener un servidor completo. A lo que me refiero con esto es que, ya configurado Postfix, el servidor, en teoría, ya puede enviar correos (cosa que se probará un poco más adelante), pero aún así los correos irían con el remitente de la cuenta de Gmail usada como relay. Lo ideal sería que aparecieran los correos como si vinieran del servidor (con el nombre de usuario y dominio del mismo), no de Gmail.&lt;br /&gt;&lt;br /&gt;Para ello, se tiene que acceder a la cuenta de Gmail, acceder a Configuración y ahí a la pestaña de Cuentas e Importación. Agregar la cuenta del servidor y realizar el proceso de verificación, que consiste en introducir un código de verificación que debe llegar al correo indicado... ups, aún falta configurar el correo entrante para hacer esto. Volveremos a ello hasta el final, pero más valía anotarlo aquí para saber que aún es parte de la configuración del MTA y que queda pendiente a que podamos recibir correos...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Uso del MTA&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Postfix ya puede usarse, y de hecho vamos a probarlo en breve. &lt;br /&gt;&lt;br /&gt;Por ahora resumiremos los comandos de Postfix más importantes.&lt;br /&gt;&lt;br /&gt;En primera instancia, una vez configurado todo, debe reiniciarse el servicio de Postfix, lo cual puede hacerse con&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ /etc/init.d/postfix restart&lt;/span&gt;&lt;/blockquote&gt;(o donde quiera que residan los scripts que dan inicio a los servicios del sistema). Pero en vez de ello, Postfix también cuenta con una opción que permite reinciar&amp;nbsp; y cargar las configuraciones de nueva cuenta, sin necesidad de reiniciar el servicio del sistema:&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ postfix reload&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Si existen correos en cola de espera para ser enviados, puede pedírsele a Postfix que los envíe, vaciando la cola, con:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ postfix flush&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Para ver la mencionada cola de salida de correos se utiliza el comando&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mailq&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Así mismo, es importante saber en donde se almacenan los logs del sistema. Postfix genera por default tres archivos de históricos en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/var/log&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail.error&lt;/span&gt; : con los errores que hubiera encontrado&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail.warn&lt;/span&gt; : con las advertencias que hubieran surgido&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail.info&lt;/span&gt; : con el resto de información de logging que se hubiera presentado&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Prueba del MTA&lt;/b&gt;&lt;br /&gt;Para probar Postfix, podemos hacer uso, por ahora, del comando &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail&lt;/span&gt; de GNU/Linux.&lt;br /&gt;&lt;br /&gt;Previamente debemos crear el subdirectorio &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$HOME/Mail&lt;/span&gt; (o donde quiera que lo hayamos configurado en el archivo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;main.cf&lt;/span&gt; de Postfix).&lt;br /&gt;&lt;br /&gt;Hecho eso usamos:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="background-color: #eeeeee; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;$ mail direcciondestino@dominio.com&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Con direcciondestino alguna cuenta de correo de prueba fuera del servidor.&lt;br /&gt;&lt;br /&gt;Luego ponemos el subject, INTRO, y escribimos el correo. Al terminar tecleamos ^D (Ctrl + D) y nada en el campo Cc: y el correo debería de llegar a la dirección especificada.&lt;br /&gt;&lt;br /&gt;Hay que monitorear los logs para checar y corregir cualquier problema que pudiera surgir.&lt;br /&gt;&lt;br /&gt;Claro está, si no se ha configurado Gmail, el correo parecerá venir de parte de la cuenta de Gmail.&lt;br /&gt;&lt;br /&gt;Otra forma de probar el servidor es mediante una sesión en Telnet, sabiendo previamente como funciona el protocolo SMTP...&lt;br /&gt;&lt;br /&gt;Y obviamente, aún queda configurar la recepción de correos, para poder recibir respuesta...&lt;br /&gt;&lt;br /&gt;Continuamos entonces con el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html"&gt;MDA&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-3633141288026557733?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/3633141288026557733/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3633141288026557733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3633141288026557733'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html' title='Servidor de correo personal con postfix - MTA'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3944153894882877491</id><published>2010-08-24T11:36:00.000-07:00</published><updated>2010-08-24T13:27:48.110-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Servidor de correo personal con postfix</title><content type='html'>En mi opinión un sistema de correo electrónico es de los que pueden llegar a tornarse más complicados de configurar. Al contrario de otros tipos de servidores que sólo requieren configurar un programa, y los puertos apropiados en el firewall, un sistema de correo requiere configurar varias cosas en diversos lugares.&lt;br /&gt;&lt;br /&gt;Ésto último es debido a que un sistema de correo está en realidad compuesto no por uno sino por varios programas o sistemas que interactúan entre sí, completando y complementando sus funciones para dar lugar al sistema de correo electrónico como lo conocemos hoy: eficiente, robusto, sencillo si se sabe comprender...&lt;br /&gt;&lt;br /&gt;Esta división de un sistema en pequeños subsistemas que cumplen funciones específicas es en realidad producto de la filosofía en sistemas como Unix de hacer las cosas bien y una sola vez. Así, por ejemplo el sistema que entrega el correo electrónico se dedica única y exclusivamente a eso, especializándose en ello y con eso no embotando su propio código fuente con funcionalidades para las que existen otros programas especializados, como el sistema que se encarga de obtener el correo a leer, o el que lo envía...&lt;br /&gt;&lt;br /&gt;Un sistema de correo puede, en términos generales, dividirse en 3 partes principales, a saber, de afuera hacia adentro:&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;El MUA, Mail User Agent. Es el que se encarga de mostrar el correo en su bandeja al usuario. En otras palabras, el programa utilizado para leer el correo electrónico. Por ejemplo mutt, Mozilla Thunderbird, Evolution, MS Outlook, etc. También puede ser un cliente web, por ejemplo Squirrelmail. El análogo con el correo postal es que el MUA es la persona que recibe y lee sus cartas.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;El MDA, Mail Delivery Agent. Es el que se encarga de repartir el correo a las distintas bandejas o cuentas que existan. Normalmente ya no se 've' este programa, pero está ahí ejecutando su labor conforme se lo solicita el último componente. Un ejemplo de este tipo de programas es Procmail. Un análogo con la realidad del correo postal, sería que el MDA desempeña la labor del cartero que toma las cartas de la oficina de correos y las lleva a los buzones de los usuarios correctos.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;El MTA, Mail Transfer Agent. Es el núcleo de un sistema de correo electrónico. Se encarga de, por un lado, tomar los mensajes de las bandejas de salida de los usuarios y enviarlos a los destinatarios, utilizando por ejemplo el protocolo SMTP. Por otro lado, se encarga de recibir los correos entrantes del exterior (o los que vengan del propio sistema) y decidir qué hacer con ellos, en particular entregarlos al MDA para que los deposite en las bandejas adecuadas. Ejemplos de este tipo de programas son Sendmail y Postfix. El análogo con el sistema de correo postal es que el MTA es como la oficina de correos local, que recibe las cartas a ser enviadas por parte de los usuarios y que se comunica con otras oficinas para enviar los correos a los destinos adecuados.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Existen además otros componentes que se relacionan en algún punto del sistema. Por ejemplo, hay programas dedicados a leer constantemente las entradas de correo de servidores externos para así solicitar su llegada. Por ejemplo, Fetchmail. Otro ejemplo son los detectores de spam, tan importantes para evitar saturar las bandejas de entrada de los usuarios con correo basura o incluso peligroso. Por ejemplo, Spamassasin o Spambayes.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;También existen otros protocolos que se relacionan con el correo, como POP e IMAP que permiten obtener el correo electrónico desde un servidor para leerlo en otros lugares (algo como lo que se logra configurando gmail para ser leido en Thunderbird o en un dispositivo móvil, y de hecho es en lo que se basa Fetchmail). Para levantar un servidor usando estos protocolos existen otros programas también. Por ejemplo Courier.&lt;/li&gt;&lt;/ul&gt;El siguiente diagrama muestra de manera muy general como se conformaría un sistema de correo personal como el que vamos a armar en este tutorial: &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_XrECR80gtTI/TG7HfflwOZI/AAAAAAAAAJI/Bl58oMkUvs0/s1600/mail_system.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_XrECR80gtTI/TG7HfflwOZI/AAAAAAAAAJI/Bl58oMkUvs0/s400/mail_system.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Para el presente tutorial, vamos a configurar entonces el sistema de correo con el siguiente software:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;sobre GNU/Linux, distribución Debian Lenny (en realidad con un poco de investigación se puede instalar en cualquier otra distribución)&lt;/li&gt;&lt;li&gt;MTA: Postfix, conectado via una cuenta de gmail para poder conectarnos desde una IP dinámica&lt;/li&gt;&lt;li&gt;MDA: Procmail&lt;/li&gt;&lt;li&gt;MUA: mutt (cliente de correo en consola, modo texto, sencillo pero útil para este ejemplo, ¡y para leer rápidamente correo común también!)&lt;/li&gt;&lt;li&gt;Fetchmail para leer constantemente una cuenta de gmail y obtener así los correos entrantes&lt;/li&gt;&lt;li&gt;Spambayes para detección de spam&lt;/li&gt;&lt;li&gt;por ahora no vamos a configurar Courier para utilizar los protocolos POP e IMAP, lo dejamos para otro tutorial&lt;/li&gt;&lt;/ul&gt;Con esto lograremos un servidor de correo en nuestra máquina con IP dinámica, para poder enviar y recibir correos, con una dirección de correo personal (con todo y dominio personal si contamos con un servicio como el que da DynDNS). Los correos enviados desde el sistema parecerán venir de parte de la cuenta de Gmail, requisito necesario ya que los ISPs que dan IPs dinámicas no permite enviar correos así nada más, justamente para evitar abusos. Así mismo, será posible recibir correos en nuestra dirección con domino personal (de nuevo, siempre y cuando contemos con un servicio como el que da DynDNS).&lt;br /&gt;&lt;br /&gt;Cabe la pregunta de por qué usar una cuenta de Gmail para el envío real de los correos. La razón es que la mayoría de los servidores de correo actuales están configurados para evitar la recepción de correos que vengan de dominios que mapeen con direcciones IPs definidas como dinámicas. Por ello, se necesita hacer relay con un servidor 'válido' para dichos servidores para evitar que los correos sean rechazados. Si contáramos con una dirección IP estática, es probable que no necesitemos usar Gmail como relay, pero como este tutorial está basado en esa supocisión, lo dejaremos como parte del diseño del sistema...&lt;br /&gt;&lt;br /&gt;Para fines prácticos, puesto que este sería un post muy largo si lo dejamos todo en una sola entrada, vamos a subdividirlo en partes...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_9223.html"&gt;MDA&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con.html"&gt;MUA&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_24.html"&gt;Fetchmail&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correos-personal-con_9803.html"&gt;Spambayes&lt;/a&gt; y algunas notas finales&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Como referencia, el presente tutorial lo base en: &lt;a href="http://www.hypexr.org/linux_mail_server.php"&gt;http://www.hypexr.org/linux_mail_server.php&lt;/a&gt;&lt;br /&gt;y en &lt;a href="http://albertomolina.wordpress.com/2009/01/04/configurar-postfix-a-traves-de-un-relay-host-autenticado-gmail/"&gt;http://albertomolina.wordpress.com/2009/01/04/configurar-postfix-a-traves-de-un-relay-host-autenticado-gmail/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Comencemos con el &lt;a href="http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix_24.html"&gt;MTA&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-3944153894882877491?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/3944153894882877491/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3944153894882877491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3944153894882877491'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/08/servidor-de-correo-personal-con-postfix.html' title='Servidor de correo personal con postfix'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XrECR80gtTI/TG7HfflwOZI/AAAAAAAAAJI/Bl58oMkUvs0/s72-c/mail_system.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-7655358137466153286</id><published>2010-04-27T10:54:00.000-07:00</published><updated>2010-04-27T10:54:10.703-07:00</updated><title type='text'>Compilando FFmpeg para convertir formatos de archivos de medios</title><content type='html'>FFmpeg es una suite de programas para manipulación de medios. Su sitio oficial es &lt;a href="http://ffmpeg.org/"&gt;http://ffmpeg.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La mayoria de las distribuciones Linux ya incluyen los paquetes para poder utilizar FFmpeg, sin embargo a veces es necesario recompilar el programa para que soporte algunos codecs que no vienen por default en el programa que incluye la distribucion.&lt;br /&gt;&lt;br /&gt;El codigo fuente de FFmpeg se baja del sitio oficial. Se puede bajar la ultima version estable o sincronizar con el repositorio SVN o GIT para tener la version de desarrollo mas reciente.&lt;br /&gt;&lt;br /&gt;Una vez con el codigo fuente, se aplica la clásica serie de pasos:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;configure&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;make&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;make install&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;(este último al menos, requiere de permisos de superusuario)&lt;br /&gt;&lt;br /&gt;Ahora bien, para que FFmpeg soporte otros formatos, se deben habilitar en el configure.&lt;br /&gt;Por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--enable-libopencore-amrnb&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp; permite soporte para videos 3GP&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;--enable-libvorbis&lt;/span&gt;&amp;nbsp;&amp;nbsp; permite soporte para Vorbis&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--enable-libmp3lame&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp; permite soporte para audio MP3&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;--enable-libxvid&lt;/span&gt;&amp;nbsp;&amp;nbsp; permite soporte para AVI&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--enable-libfaac&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp; permite soporte para audio AAC&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Una vez compilado e instalado, ffmpeg se utiliza para convertir formatos.&lt;br /&gt;Por ejemplo,&lt;br /&gt;&lt;br /&gt;de FLV a 3GP:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;ffmpeg -i origen.flv -s qcif -vcodec h263 -acodec aac -ac 1 -ar 8000 -r 25 -ab 32k -y destino.3gp&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;de MOV a FLV&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;ffmpeg -i origen.mov -ar 22050 -ab 128k -b 400k -s 320x240 -aspect 4:3 -f flv destino.flv&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Notese que los parametros que definen las caracteristicas del video (bitrate, etc.) deberian cambiar segun el video origen y el resultado deseado en el destino.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-7655358137466153286?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/7655358137466153286/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/04/compilando-ffmpeg-para-convertir.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7655358137466153286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7655358137466153286'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/04/compilando-ffmpeg-para-convertir.html' title='Compilando FFmpeg para convertir formatos de archivos de medios'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-6770582304970892699</id><published>2010-02-27T00:07:00.000-08:00</published><updated>2010-02-27T00:07:28.690-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arquitectura'/><title type='text'>¿Eres un arquitecto de software?</title><content type='html'>&lt;div style="text-align: right;"&gt;&lt;i&gt;Tomado del original (en inglés) en &lt;a href="http://www.infoq.com/articles/brown-are-you-a-software-architect" target="_blank"&gt;infoq.com&lt;/a&gt;.&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;La linea que divide el desarrollo de software y su arquitectura es engañosa.&amp;nbsp; Algunos dirán que esta no existe y que la arquitectura es simplemente una extensión del proceso de diseño hecho por los desarrolladores.&amp;nbsp; Otros harán de esto un enorme abismo que solo puede ser crusado por desarrolladores avanzados que creen que debes resumir los componentes fundamentales en lugar de detenerte en esos detalles molestos de implementación. Como siempre, hay un balance pragmático en algún lado a mitad del camino, lo cual hace surgir una pregunta interesante sobre como moverte de un lado a otro.&lt;br /&gt;&lt;br /&gt;Algunos de los factores clave que a menudo se utilizan para diferenciar la arquitectura del software de su diseño y su desarrollo incluyen un aumento de la escala, un aumento en el nivel de abstracción y un aumento en la importancia de la toma de decisones correctas en el diseño.&lt;br /&gt;La arquitectura del software es acerca de tener visiones holísticas y teniendo una vista general para entender como el sistema trabaja como un todo.&amp;nbsp; Mientras esto puede ayudar a difrenciar el desarrollo de la arquitectura de software, no necesariamente permite entender como alguien cambia de actividades de desarrollo a las de arquitectura. Tampoco ayuda a identificar quién hará un buen trabajo de arquitectura, ¿como harás para contratar a la gente correcta o sabrás si &lt;i&gt;tu eres &lt;/i&gt;un arquitecto de software?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: medium;"&gt;&lt;b&gt;La experiencia es una buena referencia pero necesitas profundizar más&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Llegar a ser un arquitecto de software no es algo que simplemente pase de la noche a la mañana o con un ascenso. Es una función, no un rango.&amp;nbsp; &lt;u&gt;Es un proceso evolutivo donde gradualmente ganarás la experiencia y confianza que necesitas para ejecutar tu función&lt;/u&gt;.&lt;br /&gt;&lt;br /&gt;Hay un número de cualidades que puedes buscar en un arquitecto de software y su experiencia pasada es a menudo un buen puntaje para calificar su habilidad en el desempeño de su papel.&amp;nbsp; Aunque la función de un arquitecto de software es muy variado, se necesita profundizar para entender el nivel de participación, la influencia, el liderazgo y la responsabilidad que ha sido demostrada a través de un número de ámbitos diferentes. Hablando ampliamente, la arquitectura de software en la mayoría de los proyectos puede ser dividida en dos fases; la arquitectura es &lt;b&gt;definida &lt;/b&gt;y luego es &lt;b&gt;liberada&lt;/b&gt;.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_813bkGL_8xA/S4jOJu1sOtI/AAAAAAAAA7E/A0wVA3MfHxo/s1600-h/role-definition.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_813bkGL_8xA/S4jOJu1sOtI/AAAAAAAAA7E/A0wVA3MfHxo/s320/role-definition.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: medium;"&gt;&lt;b&gt;Definición de la arquitectura del software&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El proceso de definición de la arquitectura parece bastante simple.&amp;nbsp; Todo lo que tienes que hacer es identificar cuáles son los requerimientos y diseñar un sistema que los satisfaga.&amp;nbsp; Pero en realidad no es tan simple y el papel de arquitectura de software puede varia ampliamente dependiendo de que tan comprometido estas y que tan seriamente visualizas tu papel.&amp;nbsp; Como el siguiente diagrama muestra, la parte de la definición de la arquitectura puede ser dividida en un número de elementos diferentes.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;1. Manejo de requerimientos no-funcionales: &lt;/b&gt;Los proyectos de software a menudo quedan atrapados con los usuarios que preguntan sobre las características que desean, pero rara vez se les pregunta que requerimientos no-funcionales (o cualidades del sistema) necesitan.&amp;nbsp; Algunas veces los actores dirán que "el sistema debe ser rápido", pero eso es muy subjetivo.&amp;nbsp;&lt;u&gt; Los requerimientos no-funcionales necesitan ser específicos, medibles, alcanzables y capaces de ser probados si vamos a cumplirlos.&lt;/u&gt;&amp;nbsp; La mayoría de los requerimientos no-funcionales son técnicos por naturaleza y a menudo tienen una alta influencia sobre la arquitectura del sofware.&amp;nbsp; Entender los requerimientos no-funcionales es una parte crucial, pero hay una diferencia entre asumir cuáles son los requerimeintos y llevarlos a cabo.&amp;nbsp; Después de todo, ¿Cuántos sistemas has visto que genuinamente necesiten ser operacionales 24x7?&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_813bkGL_8xA/S4jPQh-w6aI/AAAAAAAAA7M/cVUxnD68IW0/s1600-h/architecture-definition-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://1.bp.blogspot.com/_813bkGL_8xA/S4jPQh-w6aI/AAAAAAAAA7M/cVUxnD68IW0/s400/architecture-definition-1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;2. Definición de la arquitectura: &lt;/b&gt;Con los requerimientos no-funcionales capturados, el siguiente paso es empezar a pensar sobre como vas a solucionar los problemas indicados por los actores y definir la arquitectura.&amp;nbsp; Se puede decir que cada sistema tiene una arquitectura, pero no que cada sistema tiene una arquitectura definida.&amp;nbsp; Y ese realmente es el punto aquí. El proceso de la definición de la arquitectura te permite pensar sobre como vas a tomar los requerimientos junto con las restricciones impuestas y resolver el problema.&amp;nbsp; &lt;u&gt;La definición de la arquitectura es sobre introducir estructura, directrices, principios y ligerazgo a los aspectos técnicos del proyecto de sofware&lt;/u&gt;.&amp;nbsp; Definir la arquitectura es tu trabajo como arquitecto pero hay una gran diferencia entre diseñar un sistema desde cero y extender uno ya existente.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPhAXBNvI/AAAAAAAAA7U/6MHtsXN8sEs/s1600-h/architecture-definition-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPhAXBNvI/AAAAAAAAA7U/6MHtsXN8sEs/s320/architecture-definition-2.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Selección de la tecnología: &lt;/b&gt;La selección de la tecnología es típicamente un ejercicio divertido pero tiene su lista justa de retos cuando te fijas en el costo, licenciamiento, relación con proveedores, estrategia de tecnología, compatibilidad, interoperabilidad, soporte, desarrollo, politicas de actualización, entornos de usuario final y aún mas.&amp;nbsp; La suma de estos factores puede a menudo hacer una tarea simple y convertirla en una completa pesadilla.&amp;nbsp; Y ahí está la pregunta de si las tecnologías en realidad funcionan.&amp;nbsp; &lt;u&gt;La seleccion de tecnologías es todo sobre manejar riesgos; reducir riesgos donde existe alta complejidad o incertidumbre e introducir riesgos donde hay beneficios que obtener&lt;/u&gt;.&amp;nbsp; Las decisiones de tecnología se necesitan hacer tomando en cuenta todos los factores, y todas las decisiones deben ser revisadas y vueltas a evaluar.&amp;nbsp; Esto incluye los principales bloques de construcción para un proyecto de software hasta las librerias y frameworks que están siendo introducidos durante el desarrollo.&amp;nbsp; Si estás definiendo una arquitectura, también necesitas estar seguro que las elecciones que estan siendo tomadas son las correctas.&amp;nbsp; Otra vez hay una gran diferencia entre evaluar una tecnología para un nuevo sistema y agregar una tecnología a un sistema que ya existe.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_813bkGL_8xA/S4jPjUKfQbI/AAAAAAAAA7c/ZS1r4gSW7sQ/s1600-h/architecture-definition-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://3.bp.blogspot.com/_813bkGL_8xA/S4jPjUKfQbI/AAAAAAAAA7c/ZS1r4gSW7sQ/s400/architecture-definition-3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Evaluación de la arquitectura: &lt;/b&gt;Si estas diseñando software, necesitas preguntarte a tí mismo si tu arquitectura funcionará.&amp;nbsp; Para mí, &lt;u&gt;una arquitectura funciona si esta satisface los requerimientos no funcionales, provee los fundamentos necesarios para el resto del codigo y provee una plataforma suficiente para resolver los problemas de negocio &lt;/u&gt;subyacentes. Uno de los más grandes problemas con el software es que es complejo y abstracto, lo cual hace difícil visualizar las características en tiempo de ejecución desde diagramas UML o el código mismo.&amp;nbsp; Tenemos un número diferente de pruebas de todo el ciclo de vida de desarrollo del software que nos da la confianza de que el sistema que estamos liberando funcionará cuando sea mostrado. Entonces ¿por qué no hacemos lo mismo para nuestras arquitecturas? si puedes probar tu arquitectura, entonces puedes probar que esta funciona.&amp;nbsp; Y si puedes hacer eso tan pronto como sea posible, puedes reducir el total de riesgos de que el proyecto falle mas que simplemente esperar por lo mejor.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPk_OmtnI/AAAAAAAAA7k/l2tGKM_s_i0/s1600-h/architecture-definition-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPk_OmtnI/AAAAAAAAA7k/l2tGKM_s_i0/s320/architecture-definition-4.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Colaboración de la arquitectua: &lt;/b&gt;Es inusual para un sistema que viva aislado y existe un par de personas que necesitan entender esto.&amp;nbsp; Esto va desde el equipo de desarrollo inmediato que necesitan entender la arquitectura hasta los actores que tienen un interes como seguridad, base de datos, operaciones, mantenimineto, soporte y más puntos de vista.&amp;nbsp; Para que un proyecto de sofware sea exitoso, necesitan colaborar muy de cerca con los encargados de sistemas para asegurar que la arquitectura se integrara satisfactoriamente con su entorno.&amp;nbsp; Desafortunadamente, la colaboracion en la arquitectura en el equipo de desarrollo rara vez ocurre, por no hablar de los actores externos.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPmlALVdI/AAAAAAAAA7s/o-xG4VrlKds/s1600-h/architecture-definition-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPmlALVdI/AAAAAAAAA7s/o-xG4VrlKds/s400/architecture-definition-5.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_813bkGL_8xA/S4jP1vQwp-I/AAAAAAAAA8c/MPc1WECVhDg/s1600-h/role-delivery.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_813bkGL_8xA/S4jP1vQwp-I/AAAAAAAAA8c/MPc1WECVhDg/s320/role-delivery.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: medium;"&gt;&lt;b&gt;Liberación de la arquitectura del software&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;También es la misma historia con la entrega de la arquitectura, donde el papel de la arquitectura del software puede variar dependiendo del nivel de compromiso a través de los elementos que contribuyen a un proyecto exitoso.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;1. Apropiarse del panorama completo:&lt;/b&gt; Con el fin de llevar la arquitectura hacia una conclusión exitosa, es importante que &lt;u&gt;alguien tenga el panorama completo y que venda la visión a lo largo del ciclo de vida del desarrollo de software&lt;/u&gt;, que evolucione a lo largo del proyecto si es necesario y que tome la responsabilidad de asegurarse que será entregado correctamente.&amp;nbsp; Si has definido una arquitectura, hace sentido permanecer continuamente comprometido y evolucionarla más que solamente dejarla en manos de un "equipo de implementación".&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPoyECcjI/AAAAAAAAA70/BLjFrPRcIKc/s1600-h/architecture-delivery-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPoyECcjI/AAAAAAAAA70/BLjFrPRcIKc/s400/architecture-delivery-1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Liderazgo: &lt;/b&gt;Apropiarse del panorama completo es un especto técnico del liderazgo, pero hay otras cosas que necesitamos que esten hechas durante la fase de liberación de un proyecto.&amp;nbsp; Estas incluyen tomar responsabilidades, proveer orientación técnica, tomar decisiones técnicas y tener la autoridad para tomarl dichas decisiones.&amp;nbsp; Como el arquitecto, necesitas &lt;u&gt;tener el liderazgo técnico para asegurar que todo esté caminando perfecto y que el equipo esté siendo dirigido en la dirección correcta y continuamente&lt;/u&gt;.&amp;nbsp; La posición del arquitecto es inherentemente sobre liderazgo y aunque esto suene obvio, muchos equipos que realizan proyectos no tienen el liderazgo técnico que necesitan, con arquitectos asumiendo que una liberación exitosa no es necesariamente su problema.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPrW4UXWI/AAAAAAAAA78/6xlocBCPv-k/s1600-h/architecture-delivery-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://4.bp.blogspot.com/_813bkGL_8xA/S4jPrW4UXWI/AAAAAAAAA78/6xlocBCPv-k/s400/architecture-delivery-2.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Entrenar y guiar: &lt;/b&gt;El entrenamiento y la guianza es una actividad que se suele pasar por alto en la mayoría de proyectos de desarrollo, con muchos miembros en el equipo sin el soporte que requieren.&amp;nbsp; Mientras el líder técnico intenta dirigir el proyecto como un todo, hay ocasiones en que &lt;u&gt;ciertas personas necesitan asistencia&lt;/u&gt;.&amp;nbsp; Además de esto, &lt;u&gt;entrenar y guiar provee una forma de mejorar las habilidades de la gente &lt;/u&gt;y ayudarlas a mejorar sus propias carreras profesionales. Esto es algo que recae directamente como un mandato para el arquitecto, pero claramente hay una gran diferencia entre entrenar a tu equipo en arquitectura/diseño y ayudarlos con sus problemas de codificación.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_813bkGL_8xA/S4jPtEpqnKI/AAAAAAAAA8E/e7CuylW9NbE/s1600-h/architecture-delivery-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://1.bp.blogspot.com/_813bkGL_8xA/S4jPtEpqnKI/AAAAAAAAA8E/e7CuylW9NbE/s400/architecture-delivery-3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Asegurar la calidad: &lt;/b&gt;Incluso con la mejor arquitectura y liderazgo en el mundo, una liberación pobre puede causar que un proyecto de la vuelta del éxito al fracaso.&amp;nbsp; Asegurar la calidad &lt;u&gt;es una parte amplia de la función de un arquitecto&lt;/u&gt;, pero esto es mas que solo hacer revisiones de código.&amp;nbsp; Por ejemplo, necesitas una linea de referencia como defensa para asegurarte, y esto significa la &lt;u&gt;introducción de estándares y prácticas de trabajo&lt;/u&gt;.&amp;nbsp; Desde una persepectiva de desarrollo de software, estas pudieran incluir &lt;span style="color: #000099;"&gt;estándares de codificación, principios de diseño y herramientas de análisis de código fuente a través de una contínua integración, pruebas unitarias automatizadas y herramientas de cobertura de código&lt;/span&gt;.&amp;nbsp; Se puede decir que la mayoría de los proyectos no aseguran la calidad lo suficiente, por tanto necesitan imaginarse que es lo importante y garantizarlo suficientemente.&amp;nbsp; Para mí, las partes importantes de un proyecto son todas aquellas significativas arquitectónicamente, con lógica de negocios crítica, complejas y altamente visibles.&amp;nbsp; Solo necesitas ser pragmático y darte cuenta que no puedes necesariamente asegurar todo, de hacer algo más que no hacer nada.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_813bkGL_8xA/S4jPvaM-bcI/AAAAAAAAA8M/MbYrKLQ970Y/s1600-h/architecture-delivery-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://2.bp.blogspot.com/_813bkGL_8xA/S4jPvaM-bcI/AAAAAAAAA8M/MbYrKLQ970Y/s400/architecture-delivery-4.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Diseño, desarrollo y pruebas: &lt;/b&gt;La última cosa que recae sobre la función de un arquitecto es el diseño, el desarrollo y las pruebas.&amp;nbsp; Ser un arquitecto práctico no significa necesariamente que te tienes que involucrar en el día a día con las tareas de codificar, pero si implica que estes &lt;u&gt;contínuamente involucrado en el proyecto, ayudando activamente a darle forma y a liberarlo&lt;/u&gt;.&amp;nbsp; Dicho esto, ¿porque las actividades diarias de codificar no son parte de la función del arquitecto? La mayoría de los arquitectos tienen bastante experiencia, entonces tiene sentido mantener esas habilidades actualizadas.&amp;nbsp; Además, el arquitecto puede experimentar el mismo dolor que todos los demás en el equipo, que a su vez ayuda a entender mejor como es vista su arquitectura desde la perspectiva de los desarrolladores.&amp;nbsp; Muchas compañías tienen políticas que previenen a los arquitectos de escribir código porque sus arquitectos son "tan valiosos como para ejecutar este trabajo cómodo".&lt;br /&gt;Claramente es una actitud incorrecta ... ¿por qué dejar que tus arquitectos pongan todo su esfuerzo en definir la arquitectura si no vas a dejar que contribuyan a su liberación exitosa? Por su puesto que hay situaciones donde no es práctico que se involucren a nivel código.&amp;nbsp; Por ejemplo, un proyecto grande generalmente significa un panorama más amplio que cuidar y puede haber ocasiones donde simplemente no tengas el tiempo.&amp;nbsp; Pero generalmente hablando, un arquitecto que codifica es más efectivo y más feliz que un arquitecto que solo mira desde un extremo.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_813bkGL_8xA/S4jPwwfZupI/AAAAAAAAA8U/i6OR2nt08-k/s1600-h/architecture-delivery-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="http://3.bp.blogspot.com/_813bkGL_8xA/S4jPwwfZupI/AAAAAAAAA8U/i6OR2nt08-k/s400/architecture-delivery-5.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: medium;"&gt;&lt;b&gt;¿Eres un arquitecto de software?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A menos de que veas la linea entre el desarrollo de software y arquitectura como mítico o un amplio abismo, los elementos arriba resaltan que los niveles de experiencia de la gente con la función de arquitectura de software varía considerablemente dependiendo de que tan comprometidos están y que tan seriamente ven su papel.&amp;nbsp; La mayoría de los desarrolladores no despiertan en un Lunes por la mañana y se declaran a sí mismos ser arquitectos de software. Ciertamente no y mi camino en la arquitectura de software fue en gran medida un proceso evolutivo.&amp;nbsp; Habiendo dicho este pensamiento, hay una alta probabilidad de que los propios desarrolladores ya estén tomando en cuenta las partes que conforman la arquitectura de software, independientemente de su título laboral.&lt;br /&gt;&lt;br /&gt;Hay una gran diferencia entre contribuir a la arquitectura de un sistema y ser el responsable de definirla tu mismo; con una continuidad de habilidades, conocimiento y experiencia necesaria a través de las diferentes áreas que forman la función de un arquitecto. Cruzar la línea entre el desarrollador y el arquitecto es tu decisión, pero entender tu propio nivel de experiencia es el primer paso en la jornada.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/simonbrown" target="_blank"&gt;SimonBrown&lt;/a&gt; | &lt;a href="http://www.codingthearchitecture.com/" target="_blank"&gt;Codificando la arquitectura&lt;/a&gt; (ingles) |&lt;br /&gt;&amp;nbsp;&lt;a href="http://www.softwarearchitecturefordevelopers.com/" target="_blank"&gt;Arquitectura de sofware para desarrolladores&lt;/a&gt; (ingles)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-6770582304970892699?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/6770582304970892699/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/02/eres-un-arquitecto-de-software.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6770582304970892699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6770582304970892699'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/02/eres-un-arquitecto-de-software.html' title='¿Eres un arquitecto de software?'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_813bkGL_8xA/S4jOJu1sOtI/AAAAAAAAA7E/A0wVA3MfHxo/s72-c/role-definition.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-2369171986791611180</id><published>2010-02-18T14:32:00.000-08:00</published><updated>2010-02-27T07:09:26.572-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Instalando most como pager en Linux</title><content type='html'>Casi todos estamos familiarizados con los paginadores más famosos en GNU/Linux, con los cuales un texto largo en consola puede verse tranquilamente pantalla a pantalla...&lt;br /&gt;&lt;br /&gt;Puede ser que usemos el clásico &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;more(1)&lt;/span&gt;&lt;/b&gt;, o que por otro lado utilicemos &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;less&lt;/b&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;(1)&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;¿Tenemos más opciones? La respuesta es sí...&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="" name="more"&gt;&lt;/a&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;more&lt;/b&gt; debe su nombre (que significa '&lt;i&gt;más&lt;/i&gt;') a la pequeña línea al final de cada pantalla con la indicación de que, presionando cualquier tecla, podemos ver más del texto que estamos visualizando.&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;less&lt;/b&gt;, por su parte, pretende ser un complemento a &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;more&lt;/b&gt;, ya que este último no permite 'navegar' hacia arriba y abajo del texto visualizado, mientras que &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;less&lt;/b&gt; si lo permite. Su nombre es en realidad una broma, pues '&lt;i&gt;less es más que more&lt;/i&gt;' (&lt;i&gt;less is more than more&lt;/i&gt;). less significa, literalmente, 'menos'.&lt;br /&gt;&lt;br /&gt;Por su parte, &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;most&lt;/b&gt; es otro paginador para sistemas GNU/Linux. No suele ser parte de alguna distribución en particular, pero presenta características que lo hacen aún más útil que &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;less&lt;/b&gt;. Además de la navegación vertical, también se permite la navegación horizontal (evitando que las líneas de más de 80 caracteres de longitud se regresen al inicio, confundiendo al lector). Igualmente, permite búsquedas, entre otras características. En este sentido, '&lt;i&gt;most es lo que un paginador debe de ser&lt;/i&gt;' (&lt;i&gt;most is what a pager must be&lt;/i&gt;). most significa 'mas que cualquiera', y must significa 'debe de'.&lt;br /&gt;&lt;br /&gt;Para instalar most, debe bajarse el código de su sitio oficial:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Georgia,&amp;quot;Times New Roman&amp;quot;,serif; text-align: center;"&gt;&lt;a href="http://www.jedsoft.org/most"&gt;http://www.jedsoft.org/most&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Se puede bajar la última versión en un archivo tar.gz, o por su lado hacer un checkout del repositorio del código, para tener la última versión con Subversion:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;svn co http://opensvn.csie.org/jedsoft/most/trunk most&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Una vez con el código fuente, hay que seguir los clásicos pasos de instalación en software GNU:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;./configure&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;make&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;make install&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;El proceso puede llegar a marcar algún error si no se cuenta con todas las librerías necesarias. El caso es que normalmente suelen requerirse las librerías de S-Lang, las cuales normalmente sí están incluidas en las distribuciones Linux (hay que tomar en cuenta que se debe instalar el paquete de desarrollo de S-Lang, para instalar las cabeceras de código necesarias). Si no, en jedsoft.org también se puede conseguir esta librería.&lt;br /&gt;&lt;br /&gt;Hecho esto, most ya puede utilizarse para paginar textos con:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;most archivo&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;(Nótese la salida con colores y todo lo demás).&lt;br /&gt;&lt;br /&gt;Si lo que se desea es que &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;most&lt;/b&gt; sea el paginador por defecto, hay que sobreescribir la variable de entorno &lt;b&gt;PAGER&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;export PAGER=most&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Haciendo esto en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.bashrc&lt;/span&gt; o en el archivo de incio de sesión apropiado, se puede hacer este cambio permanente.&lt;br /&gt;&lt;br /&gt;Con esto, cabe aclarar, ahora incluso las páginas del manual &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;man&lt;/b&gt; que se consulten utilizarán &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;most&lt;/span&gt;&lt;/b&gt; para desplegarse, pues &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;man&lt;/b&gt; utiliza el &lt;b&gt;PAGER&lt;/b&gt; para mostrar las páginas solicitadas. Nótese también que la salida de &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;man&lt;/b&gt; utilizando &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;most&lt;/span&gt;&lt;/b&gt; está bastante más estilizada que con &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;less&lt;/span&gt;&lt;/b&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-2369171986791611180?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/2369171986791611180/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/02/instalando-most-como-pager-en-linux.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2369171986791611180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2369171986791611180'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/02/instalando-most-como-pager-en-linux.html' title='Instalando most como pager en Linux'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-1884773038066124357</id><published>2010-02-11T19:14:00.000-08:00</published><updated>2010-02-11T19:27:45.847-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Construye tu propio servidor LAMP</title><content type='html'>Vamos a instalar varios servidores que en conjunto se suelen conocer como LAMP (&lt;span style="color: #ff6600;"&gt;Linux&lt;/span&gt;-&lt;span style="color: #990000;"&gt;Apache&lt;/span&gt;-&lt;span style="color: #000099;"&gt;MySQL&lt;/span&gt;-&lt;b&gt;&lt;span style="color: #330099;"&gt;PHP&lt;/span&gt;&lt;/b&gt;), básicamente necesitamos Apache para poder montar nuestras paginas web, php para poder programarlas y mysql para almacenar nuestros datos pero como ya deben saber para que funciona cada una, voy a enfocarme más a la instalación propiamente sobre un linux ubuntu 9.10.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalar Apache2&lt;/b&gt;&lt;b&gt; y configurar PHP5&lt;/b&gt;&lt;br /&gt;Debemos descargar los paquetes desde el repositorio de ubuntu usando apt-get de la siguiente forma:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo apt-get install apache2 php5 libapache2-mod-php5&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;El comando sudo te permitirá ejecutar los comandos como administrador, esto es muy común en ubuntu, la única diferencia de hacerlo sin el comando sudo es que te pedirá tu contraseña y listo, te mostrará algo como la siguiente imagen.&amp;nbsp; Debes responder 'Y' a la pregunta y empezará a descargar primero los paquetes, luego a instalarlos automáticamente.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss62p31iI/AAAAAAAAA58/zjQnjSOU1BI/s1600/installingApache2_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="195" src="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss62p31iI/AAAAAAAAA58/zjQnjSOU1BI/s400/installingApache2_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Prepara tu café porque se va a descargar como de 7 a 10MB.&lt;/i&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;El paquete apache2 instalara el servidor web, php5 instalará el core para interpretar los scripts php y el utlimo: libapache2-mod-php5 configurará a php como módulo del servidor web.&amp;nbsp; Si quisieras usar la version 4 de php, debes indicar en el comando anterior los siguientes paquetes: php4 y libapache2-mod-php4.&lt;br /&gt;&lt;br /&gt;Por default, el archivo de configuración de apache se ubicará en /etc/apache2/apache2.conf y la ruta donde debemos ubicar nuestras páginas es en /var/www que a su vez se mapea a &lt;span style="background-color: #00cccc;"&gt;&lt;a href="http://localhost/"&gt;http://localhost&lt;/a&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Para poder manipular nuestro servidor web apache2 recientemente instalado podemos utilizar el siguiente comando con las instrucciones start, stop, restart y status, por ejemplo, para conocer el estatus haremos:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;/etc/init.d/apache2 status&lt;br /&gt;* apache is running (pid 2575)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para probar que efectivamente este corriendo, podemos ir a nuestro browser y la página: &lt;span style="background-color: #00cccc;"&gt;&lt;a href="http://localhost/"&gt;http://localhost&lt;/a&gt;&lt;/span&gt;, si todo corrió como se era esperado veremos un resultado como la siguiente imagen.&amp;nbsp; Recuerda que si piensas utilizar esta forma para parar, iniciar o reiniciar los servicios, debes utilizar sudo.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh6.ggpht.com/_813bkGL_8xA/S3S5y9cWItI/AAAAAAAAA6M/HeztU1BV9Ik/s1600/resultingApache2_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="282" src="http://lh6.ggpht.com/_813bkGL_8xA/S3S5y9cWItI/AAAAAAAAA6M/HeztU1BV9Ik/s400/resultingApache2_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Para comprobar que se esta ejecutando correctamente el modulo php sobre apache, podemos hacer un script de prueba php. Ejecuta:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo nano /var/www/test.php&lt;br /&gt;&lt;/pre&gt;(abrirá el editor de textos llamado nano y copia el siguiente texto)&lt;br /&gt;&lt;pre class="brush:php;gutter:false;toolbar:false;"&gt;&amp;lt;?php phpinfo(); ?&amp;gt;&lt;br /&gt;&lt;/pre&gt;Luego aprieta CTL+X para salir y luego Y para indicar que se guarde el archivo y finalmente ENTER para confirmar el nombre del archivo (debe ser test.php)&lt;br /&gt;Para comprobar que se haya escrito el archivo, ejecuta lo siguiente para ver su contenido:&lt;br /&gt;sudo cat test.php&lt;br /&gt;Si aparece la linea de phpinfo() ahora si puedes probar en &lt;span style="background-color: #00cccc;"&gt;&lt;a href="http://localhost/test.php"&gt;http://localhost/test.php&lt;/a&gt; &lt;/span&gt;y verás algo como en la imagen abajo.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh4.ggpht.com/_813bkGL_8xA/S3S5y_mUtlI/AAAAAAAAA6U/8Bp-l67iMhs/s1600/testing_php_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="305" src="http://lh4.ggpht.com/_813bkGL_8xA/S3S5y_mUtlI/AAAAAAAAA6U/8Bp-l67iMhs/s400/testing_php_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalar MySQL 5&lt;/b&gt;&lt;br /&gt;Instalemos ahora el motor de base de datos MySQL, para ello, ejecutemos el siguiente comando:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo apt-get install mysql-server mysql-client php5-mysql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Igual que antes, solicitará nuestra contraseña, respondemos con 'Y' a la pregunta "Do you want to continue [Y/n]?" e instalará el paquete mysql-server para el servidor de base de datos, mysql-client para el cliente tipo consola que más adelante ocuparemos y php5-mysql para configurar el core de php con el fin de que pueda consultar los datos a una base de datos mysql.&amp;nbsp; Si escogimos instalar la version 4 de php, debes instalar php4-mysql en lugar del anterior.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss6w2nK5I/AAAAAAAAA6A/Qo2ciOlgy5E/s1600/installingMySQL_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="252" src="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss6w2nK5I/AAAAAAAAA6A/Qo2ciOlgy5E/s400/installingMySQL_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Ahora sí tómate tu café porque se van a descargar como 59MB.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;El archivo de configuracion de mysql por defecto se encuentra en /etc/mysql/my.cnf.&amp;nbsp; Aunque en mi caso particular; luego de descargar los paquetes e instalar el servidor de mysql; me pidió en la consola que cambiara el password para root, por defecto el servidor se instala con el usuario root sin contraseña, no obstante esto se puede cambiar (y es recomendable hacerlo a la brevedad) haciendo lo siguiente:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh6.ggpht.com/_813bkGL_8xA/S3Ss6f24lNI/AAAAAAAAA50/fOqvEFo7eq4/s1600/configuringMySQL5.1_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="150" src="http://lh6.ggpht.com/_813bkGL_8xA/S3Ss6f24lNI/AAAAAAAAA50/fOqvEFo7eq4/s400/configuringMySQL5.1_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;&amp;gt;mysql -u root&lt;br /&gt;mysql&amp;gt; use mysql (para usar la base de datos mysql)&lt;br /&gt;mysql&amp;gt; update user set password=password('aqui escribe tu nuevo password') WHERE user='root';&lt;br /&gt;mysql&amp;gt; flush privileges&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La instrucción final es para que aplique nuestros cambios.&amp;nbsp; Por último, se puede indicar al servidor que se levante, se pare o reinicie, mediante start, stop o restart, respectivamente y de la misma manera que se hacía con apache:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo /etc/init.d/mysql status&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;* Instalar un gestor web para mysql: phpmyadmin&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Esto es &lt;b&gt;opcional&lt;/b&gt;, pues solo se trata de un cliente web para mysql, puedes usar en su lugar cualquier aplicación de escritorio para conectarse al servidor como por ejemplo: &lt;a href="http://www.navicat.com/"&gt;Navicat&lt;/a&gt; .&amp;nbsp; &lt;b&gt;phpMyAdmin &lt;/b&gt;es una aplicación web muy utilizada, fácil de configurar y sencilla de usar para administrar nuestras bases de datos en mysql.&amp;nbsp; Se pueden administrar privilegios, usuarios y bases de datos con tan solo unos clics. Se le pueden instalar &lt;a href="http://www.phpmyadmin.net/home_page/themes.php"&gt;temas &lt;/a&gt;para cambiar su vista, existe bastante &lt;a href="http://www.phpmyadmin.net/home_page/docs.php"&gt;documentación&lt;/a&gt; (aunque en inglés), sin embargo hay un &lt;a href="http://www.packtpub.com/dominary-phpMyAdmin-es"&gt;libro en español&lt;/a&gt; y ha ganado diversos premios&lt;a href="http://www.phpmyadmin.net/home_page/awards.php"&gt; &lt;/a&gt;como mejor herramienta para desarrolladores y administración de sistemas, por mencionar un par. Antes de instalarlo, puedes probarlo &lt;a href="http://demo.phpmyadmin.net/trunk-config/"&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Si te has decidido a instalarlo, ejecuta lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo apt-get install phpmyadmin&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh4.ggpht.com/_813bkGL_8xA/S3Ss6_2wMOI/AAAAAAAAA6E/Vd0GlLrWScw/s1600/installingPHPmyAdmin_mini.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://lh4.ggpht.com/_813bkGL_8xA/S3Ss6_2wMOI/AAAAAAAAA6E/Vd0GlLrWScw/s400/installingPHPmyAdmin_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Se va a descargar otros 5MB, tu eliges si vas por otro cafe o mejor por un te.&lt;/i&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh6.ggpht.com/_813bkGL_8xA/S3S5yqRTo-I/AAAAAAAAA6I/qA7-mRi2PYE/s1600/phpmyadminBD_mini.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="193" src="http://lh6.ggpht.com/_813bkGL_8xA/S3S5yqRTo-I/AAAAAAAAA6I/qA7-mRi2PYE/s400/phpmyadminBD_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss6tcATyI/AAAAAAAAA54/rloZxa0oO1Y/s1600/configuringphpmyadminaccount_mini.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="107" src="http://lh3.ggpht.com/_813bkGL_8xA/S3Ss6tcATyI/AAAAAAAAA54/rloZxa0oO1Y/s400/configuringphpmyadminaccount_mini.JPG" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Luego de la instalación, intentará configurarlo, pedirá la contraseña de la cuenta de root de mysql que anteriormente dimos de alta y también preguntará si quieres configurar mediante dbconfig-common, a lo cual respondemos con Yes.&amp;nbsp; Si lo queremos hacer a mano, también podemos decir que No para saltarnos este paso y listo.&lt;br /&gt;&lt;br /&gt;Los archivos de configuracion se ubicarán por defecto en /etc/phpmyadmin pero para poder usarlo con el servidor apache que acabamos de instalar debemos editar /etc/apache/apache2.conf y agregar la siguiente linea:&lt;br /&gt;&lt;br /&gt;Include /etc/phpmyadmin/apache.conf&lt;br /&gt;&lt;br /&gt;luego reiniciemos el servidor apache para que tome en cuenta los cambios.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:shell;gutter:false;toolbar:false;"&gt;sudo /etc/init.d/apache restart&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_813bkGL_8xA/S3S5y-zOQGI/AAAAAAAAA6Q/g_fRxOpMnHo/s1600/runningphpmyadmin_mini.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="153" src="http://lh6.ggpht.com/_813bkGL_8xA/S3S5y-zOQGI/AAAAAAAAA6Q/g_fRxOpMnHo/s200/runningphpmyadmin_mini.JPG" width="200" /&gt;&lt;/a&gt;Una vez que se reinicie y si todo corrió perfecto, podemos ir a &lt;span style="background-color: #00cccc;"&gt;&lt;a href="http://localhost/phpmyadmin"&gt;http://localhost/phpmyadmin&lt;/a&gt;&lt;/span&gt;, nos pedirá los datos del usuario root y contraseña de mysql que recientemente cambiamos mediante el cliente mysql de consola.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Otras alternativa con XAMPP para linux:&lt;/b&gt;&lt;br /&gt;Resulta que al terminar este blog me encontré con &lt;a href="http://www.apachefriends.org/en/xampp-linux.html"&gt;XAMPP para linux &lt;/a&gt;y parece muy prometedor, lo he visto corriendo en windows pero en linux no parece existir mucha diferencia, salvo que al momento de este post, la versión mas actual es 0.9.5 y tiene algunas fallas en seguridad, por lo que solo te recomiendo instalarlo en un entorno de red controlado, normalmente local para pruebas.&amp;nbsp; Aquí hay unas ligas para que le hechen un ojo y me parece todavía mucho más sencillo de instalar con esta herramienta.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.apachefriends.org/en/xampp-linux.html"&gt;Instrucciones de instalación &lt;/a&gt;(son 4 pasos nadamás)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Revisa los &lt;a href="http://www.apachefriends.org/en/xampp-linux-screenshots.html"&gt;screenshots &lt;/a&gt;y date cuenta que es muy amigable.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Referencias:&lt;/b&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.howtoforge.com/ubuntu_debian_lamp_server"&gt;http://www.howtoforge.com/ubuntu_debian_lamp_server&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://packages.debian.org/sid/libapache2-mod-php5"&gt;http://packages.debian.org/sid/libapache2-mod-php5&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.phpmyadmin.net/"&gt;http://www.phpmyadmin.net&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;Otros enlaces relacionados:&lt;/b&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.webmin.com/"&gt;http://www.webmin.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mysql-apache-php.com/"&gt;http://www.mysql-apache-php.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.easyphp.org/index.php"&gt;http://www.easyphp.org/index.php&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.apachefriends.org/en/xampp-linux.html"&gt;http://www.apachefriends.org/en/xampp-linux.html&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-1884773038066124357?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/1884773038066124357/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/02/construye-tu-propio-servidor-lamp.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1884773038066124357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/1884773038066124357'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/02/construye-tu-propio-servidor-lamp.html' title='Construye tu propio servidor LAMP'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_813bkGL_8xA/S3Ss62p31iI/AAAAAAAAA58/zjQnjSOU1BI/s72-c/installingApache2_mini.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-5805879340332207687</id><published>2010-02-05T18:51:00.000-08:00</published><updated>2010-02-05T18:51:19.715-08:00</updated><title type='text'>Uso del comando awk en linux</title><content type='html'>Algunas de las limitaciones del comando sed se remedian por medio del comando &lt;b&gt;awk&lt;/b&gt;, pues aunque se parece mucho a sed, los detalles se basan más en el lenguaje de programación C que un solo editor de textos. Uso:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk 'programa' archivos&lt;/span&gt;&lt;br /&gt;Sin embargo, la constitución del programa es distinta:&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;patron { acción }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;patrón { acción }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;patrón { acción }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;... &lt;span style="font-size: x-small;"&gt;(mas patrones y acciones)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A semejanza del comando sed, awk tampoco modifica los archivos de entrada, solamente la salida que imprime. El comando awk lee la entrada de un archivo &lt;b&gt;un renglón a la vez&lt;/b&gt;, para el cual &lt;b&gt;compara con cada patrón en orden&lt;/b&gt;, de esta manera, para cada patrón que concuerde se efectúa la acción correspondiente.&lt;br /&gt;&lt;br /&gt;Los patrones son expresiones regulares como en el comando egrep o condiciones complicadas como en el lenguaje C. Por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;awk '/expresión regular/' { print }' archivos&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;awk '/expresión regular/' archivos&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esta instrucción consiste en imprimir aquellas líneas que concuerden con la expresión regular, &lt;b&gt;si se omite una acción, se imprime&lt;/b&gt;, por lo que ambas líneas muestran el mismo resultado. En caso de omitir el patrón, la parte de la acción se ejecuta a cada línea de entrada.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;También es posible, al igual que sed, indicar el programa a awk en forma de archivo como sigue:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk -f archprog archivos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A diferencia del shell, en awk, sólo los &lt;b&gt;campos empiezan con un $&lt;/b&gt;, las variables no tienen adornos, por ejemplo, awk reconoce los campos $1, $2 y así sucesivamente hasta $NF, donde NF es una variable igual al total de campos. En el ejemplo de abajo, NF es igual a 5, pero $1 representa a cada usuario en sesión, por línea procesada.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# who&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;root pts/0 Dec 25 10:30&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;margo pts/1 Dec 25 13:37&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wendy pts/2 Dec 25 16:36&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;De manera que podemos imprimir solo la hora en que entró en sesión cada usuario:&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# who | awk '{ print $1,$5 }'&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;root pts/0 Dec 25 10:30&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;margo pts/1 Dec 25 13:37&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wendy pts/2 Dec 25 16:36&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Awk supone que el espacio en blanco (ya sea un número de espacios o de tabuladores) separa los campos, a excepción del que se encuentra al principio. Los espacios al principio de línea se consideran elementos del primer campo. Pero el separador puede cambiarse por cualquier otro caracter por medio de la opción &lt;b&gt;-Fc&lt;/b&gt;, donde &lt;b&gt;c&lt;/b&gt; es el caracter que usará awk como separador. Por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;#sed 3q /etc/passwd | awk -F: '{ print $1 }'&lt;/span&gt;&lt;span style="font-size: x-small;"&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;root&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bin&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;daemon&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Awk es más fácil de utilizar que sed en operaciones como la anterior pero es mas lento al iniciar y ejecutar cuando existe mucho texto a la entrada.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Impresión&lt;/b&gt;&lt;br /&gt;Además de reconocer los campos $1, $2, etc. awk reconoce&lt;b&gt; $0&lt;/b&gt; como el conjunto de campos que se encuentran en la línea, es decir, la línea entera sin cambios. También la variable &lt;b&gt;NR &lt;/b&gt;que indica el número de línea actual y &lt;b&gt;NF &lt;/b&gt;el número de campos por cada línea. A la salida, cuando se imprimen varios campos, el separador por defecto que se utiliza es un espacio en blanco; sin embargo, este puede cambiar a través de otra proposición llamada printf que controla por completo la salida. Ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk '{ printf "%4d %s\n", NR, $0 }'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La instrucción anterior debería imprimir el número de línea dentro de un campo con 4 espacios. Los caracteres %4d especifican un entero decimal dentro de un campo de cuatro dígitos de ancho, mientras que %s especifica una cadena y por último \n representa una linea nueva al final de cada renglón, por lo que cada línea de entrada procesada se imprimirá en un renglón nuevo, de lo contrario se sobreescribiría cada línea.&lt;br /&gt;&lt;br /&gt;También se puede redireccionar la salida de print o printf hacia archivos e interconexiones, pero debe estar acompañada de &lt;b&gt;'&amp;gt;' &lt;/b&gt;y un nombre de archivo entre comillas simples; de igual manera, con &lt;b&gt;'&amp;gt;&amp;gt;'&lt;/b&gt; se anexa en vez de sobreescribir en el archivo indicado entre comillas. Para las interconexiones se utiliza el símbolo pipe &lt;b&gt;'|'&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Patrones&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Para preguntar si hay una similitud con un patrón, se hace uso, básicamente, de una sentencia de control (if en lenguaje C), esta permite hacer uso de operadores de comparación y concordancia para identificar un patrón dentro de una linea, además de otras funciones predefinidas como length() que obtiene la longitud de una cadena situada entre sus parétesis.&lt;br /&gt;&lt;br /&gt;Por ejemplo, para una concordancia se utiliza el signo &lt;b&gt;'~'&lt;/b&gt;, pero requiere que la expresión regular se encuentre encerrada entre diagonales. También a un patrón puede anteponérsele el símbolo &lt;b&gt;'!'&lt;/b&gt; para negarlo. Ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;!($2 == "x") &lt;/span&gt;Pregunta en c/línea si el campo 2 es una 'x'&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;length($2) == 0&lt;/span&gt; Pregunta si la longitud del campo 2 es cero&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;$2 !~ /./&lt;/span&gt; Pregunta si el campo 2 no concuerda con una texto que contenga cualquier caracter&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;$2 ~ /user/&lt;/span&gt; Pregunta si el campo 2 concuerda con el patron 'user'&lt;br /&gt;&lt;br /&gt;También se puede enviar a la salida, algunos comentarios más informativos que expresen cuando existió un error o simplemente notificar que algo sucedió, por ejemplo, para indicar que un renglón es demasiado largo:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk 'length($0) &amp;gt; 60 { print "Linea", NR, "muy larga:", substr ($0,1,60) }'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esta acción impide que se impriman líneas mayores a 60 caracteres, en lugar de eso, imprime un mensaje notificando que la línea es muy larga y también incluye la función substr que produce que solo se imprima la subcadena del caracter 1 al 60 de la actual que representa $0, es decir, aquella que es muy larga. Si se hubiera omitido el 60, el cual marca el final de la subcadena, se imprimiría toda la línea.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Usos de las secciones BEGIN y END&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;AWK facilita los patrones especiales BEGIN y END, los cuales se refieren a las acciones a ejecutar antes de leer el primer renglón de entrada y después de leer el último. Generalmente son empleados para inicializar variables, imprimir encabezados o posicionar separadores de campo por medio de la variable FS:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk 'BEGIN { FS = ":" }&lt;br /&gt;&amp;gt; $2 == "" ' /etc/passwd&lt;/span&gt;&lt;br /&gt;ò&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk 'END { print NR }' /etc/passwd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Operaciones&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;La verdadera fuerza de awk se entra en su capacidad de hacer cálculos sobre los datos de entrada. Se facilita el conteo, sumar y promediar, entre otras. Por ejemplo, para sumar columnas de números:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ s= s + $1 }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;END { print s }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Este programa debería encontrarse en un archivo (prog.txt) y en otro se debería encontrar una serie de números en la primer columna (num.txt). Al final, la instrucción desde el shell sería:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk -f prog.txt num.txt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lo mejor de todo es que respeta los números decimales, a diferencia de las operaciones que se realizan directamente sobre el shell.&amp;nbsp; AWK ofrece los mismos operadores aritméticos que el lenguaje C, de manera que en el ejemplo anterior s = s + $1 será lo mismo que s += $1. Todos los operadores aritméticos y lógicos se muestran a continuación por orden creciente de precedencia:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;= += -= *= /= %= Asignación&lt;/li&gt;&lt;li&gt;|| Comparación OR&lt;/li&gt;&lt;li&gt;&amp;amp;&amp;amp; Comparación AND&lt;/li&gt;&lt;li&gt;! Negación&lt;/li&gt;&lt;li&gt;&amp;gt; &amp;gt;= &amp;lt; &amp;lt;= == != ~ !~ Operadores relacionales&lt;/li&gt;&lt;li&gt;nothing Concatenación de cadenas&lt;/li&gt;&lt;li&gt;+ - más, menos&lt;/li&gt;&lt;li&gt;* / % multiplicar, dividir, residuo&lt;/li&gt;&lt;li&gt;++ -- incrementar, decrementar (prefijo ó posfijo)&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Funciones predefinidas&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Existen un conjunto de funciones predefinidas en awk, las cuales se listan a continuación y pueden ser utilizadas de una manera muy simple.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;cos (expr) Obtiene el coseno de expr&lt;/li&gt;&lt;li&gt;exp (expr) Obtiene el exponencial, es decir e^expr&lt;/li&gt;&lt;li&gt;getline () Lee la siguiente linea de entrada, devuelve 0 si es fin de archivo y 1 si no.&lt;/li&gt;&lt;li&gt;index (s1, s2) Devuelve la posición de la cadena s2 en s1, pero 0 si no la encuentra&lt;/li&gt;&lt;li&gt;int (expr) Realiza un cast como en lenguaje C para que expr sea considerado entero&lt;/li&gt;&lt;li&gt;length (s) Obtiene la longitud de la cadena s&lt;/li&gt;&lt;li&gt;log (expr) Obtiene el logaritmo de expr&lt;/li&gt;&lt;li&gt;sin (expr) Obtiene el seno de expr&lt;/li&gt;&lt;li&gt;split (s, a, c) Divide s en elementos del arreglo a, utilizando el separador c&lt;/li&gt;&lt;li&gt;sprintf (fmt, ...) Da formato a ... según la espedificación fmt&lt;/li&gt;&lt;li&gt;substr (s, m, n) Substrae una cadena dentro de otra s, iniciando en m y terminando en n&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Variables y arreglos&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Las variables se definen al utilizarse, se inicializan a cero por defecto pero no se declaran previamente. Las variables en awk también guardan tanto números como cadenas de caracteres, la diferencia depende del contexto a tratar. En termino generales, una expresión aritmético como s+=$1 permitirá almacenar un valor numérico en s, mientras que otro contexto cmo s="abc", almacenará una cadena en la misma variable.&lt;br /&gt;&lt;br /&gt;En casos ambiguos como x&amp;gt;y se utiliza el valor de cadena a menos que los operandos sean totalmente numéricos. Las variables de cadenas se inicializan a la cadena vacía. En awk existen también, variables predefinidas que utiliza el comando para su funcionamiento general, estas se listan a continuación:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;FILENAME Nombre del archivo de entrada actual&lt;/li&gt;&lt;li&gt;FS Caracter separador de campo&lt;/li&gt;&lt;li&gt;NF Numero de campos en cada registro o línea&lt;/li&gt;&lt;li&gt;NR Numero de línea actual&lt;/li&gt;&lt;li&gt;OFMT Formato de salida para números (%g por defecto, según printf())&lt;/li&gt;&lt;li&gt;OFS Cadena separadora de campo de salida (defecto: espacio)&lt;/li&gt;&lt;li&gt;ORS Cadena separadora de línea (defecto: nueva línea)&lt;/li&gt;&lt;li&gt;RS Caracter separador de línea de entrada (defecto: nueva línea)&lt;/li&gt;&lt;/ol&gt;Los arreglos, mientras tanto, son parecidos al lenguaje C y otros lenguajes de programación. Como las variables, no necesitan ser declarados; el tamaño de un arreglo está limitado por la memoria de la máquina. Por ello, si un archivo muy extenso se está transfiriendo a un arreglo, probablemente se agotaría la memoria rápidamente.&lt;br /&gt;De la misma manera en que el procesamiento normal de la entrada divide cada renglón de entrada en campos, es posible efectuar la misma operación para la separación de campos y almacenar el resultado en un arreglo, por medio de la función &lt;b&gt;split (s, arr, sep),&lt;/b&gt; donde s representa la cadena original, arr el arreglo donde se almacenará cada campo, sep el separador de campos, el cual es opcional, pues el defecto es el espacio. Por último, el valor que devuelve la función split es el total de elementos almacenados en arr. Ejemplo:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;arr[1] = "lola"&lt;br /&gt;arr[2] = "beltran"&lt;/span&gt;&lt;br /&gt;ó&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;s = "lola beltrán"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;n = split ( s, arr )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#sed 1q /etc/passwd | awk '{split ($0,a,":"); print a[1]}'&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;root&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;wdonet&lt;br /&gt;luis&lt;br /&gt;maotse&lt;br /&gt;&lt;br /&gt;También existen los arreglos asociativos, puesto que uno de los problemas ordinarios consiste en acumular un conjunto de valores para un conjunto de nombres. Esto es, que en lugar de índices numéricos, también se pueden utilizar cadenas aleatorias. Ejemplo:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;honor[susana] = 10&lt;br /&gt;honor[felipe] = 9.8&lt;br /&gt;honor[marco] = 9.5&lt;br /&gt;honor [patricia] = 9.2&lt;/span&gt;&lt;br /&gt;AWKofrece una manera adecuada de manipular este tipo de arreglos, por medio de una variación del for, que se puede ver en el apartado de control de flujo. La realización de la memoria asociativa se vale de un esquema de hashing para garantizar que el acceso a cualquier elemento tarde el mismo tiempo aproximado que las demás y que por lo menos, el tiempo no depende de cuántos elementos contenga el areglo. La memoria asociativa es eficiente en tareas como contar todas las palabras de una entrada.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Cadenas&lt;/b&gt;&lt;/span&gt;La diferencia entre sed y awk, es que sed se utiliza mayormente para editar o filtrar algún texto de entrada, es decir, es un sistema simple de entrada-proceso-salida; mientras que awk se utiliza en tareas que de verdad requieren programación. Es por eso que hace uso de sentencias de control de flujo.&amp;nbsp; En awk no hay operadores explícitos de concatenación de cadenas; éstas se concatenan cuando están contiguas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Shell&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Como ya se vió anteriormente y al igual que la creación de scripts de shell, en awk se pueden identificar los campos de una entrada (salida de algún comando del shell actual), por medio del número de campo, precedido por '$', es decir, para el campo uno, será $1, para el segundo, $2 y así sucesivamente. Sin embargo, en el caso de que se deseen pasar parámetros del shell a un programa awk, se puede realizar por medio de un uso correcto de las comillas.&lt;br /&gt;&lt;br /&gt;Por ejemplo, suponiendo que field es un programa de awk que consiste en imprimir solo una columna de cada registro, para ello, se le necesita indicar con un parámetro, el número de columna. El comando tecleado en el shell, es de la siguiente forma:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;# who | field 1&lt;/span&gt;&lt;br /&gt;Para pasar el argumento como 1 al comando awk, se hace lo siguiente:&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&lt;span style="color: #741b47;"&gt;'{ print $'&lt;/span&gt; &lt;span style="color: red;"&gt;$1&lt;/span&gt; &lt;span style="color: #741b47;"&gt;' }'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;De esta manera el &lt;span style="color: red;"&gt;$1&lt;/span&gt; que se refiere al parámetro del shell, se mantiene fuera de las comillas simples y se remplaza su valor correcto. Otra forma es:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;# awk "{ print \$&lt;span style="color: red;"&gt;$1&lt;/span&gt; }"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El problema no estriba en llevar el control de si uno está dentro o no de las comillas, sino en el hecho de que, en su redacción actual, tales programas no pueden leer más que su entrada estándar; no hay manera de pasarles el parámetro n y una lista arbitrariamente larga de nombres de archivo. Esto requiere programación con shell.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Control de flujo&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Awk permite controlar el flujo de la programación para tratar una entrada, básicamente son los mismos ciclos de cualquier lenguaje de programación, pero se asemeja mas al lenguaje C, como en muchas otras cosas. A continuación se presenta cada sentencia:&lt;br /&gt;Sentencia &lt;b&gt;IF-ELSE&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (condición)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; proposición 1&lt;br /&gt;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; proposición 2&lt;/span&gt;&lt;br /&gt;Sentencia &lt;b&gt;FOR&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;for (expresión1; condición; expresión2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; proposición&lt;/span&gt;&lt;br /&gt;Sentencia &lt;b&gt;FOR &lt;/b&gt;para arreglos &lt;b&gt;asociativos&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;for (var in array)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; proposición&lt;/span&gt;&lt;br /&gt;Sentencia &lt;b&gt;WHILE-DO&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;expresión 1&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;while (condición){&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; proposición&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expresión 2&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Por ejemplo1:&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt; awk ' BEGIN { NR = 1 }&lt;/span&gt;&lt;br /&gt;Por ejemplo2:&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;while ( NR != 5 ){&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( i == NF )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print "Se llegó al límite"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print i, $0&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NR+=1&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}' $*&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Este pequeño programa de awk, lee las primeras 5 líneas de una entrada dada, y cuando llega a la fila o línea 5, indica que se ha llegado al límite.&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;awk ' { line[ NR ] = $0}&lt;br /&gt;END { for (i = NR; i&amp;gt; 0; i--) print [ i ] } ' $*&lt;/span&gt;&lt;br /&gt;Ahora, este programa de awk, imprime las líneas de una entrada en orden inverso.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Usos de awk&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;El uso común de patrones se refiere a la validación de datos, puesto que la mayoría de ellas consiste en buscar los renglones que cumplen o no con un criterio en específico.&amp;nbsp; Awk tiene la convención de que los comentarios inician después de un '#' y toma el resto de la línea como comentario.&lt;br /&gt;&lt;br /&gt;Los usos de awk sonsisten en programas de una o dos líneas que actúan como filtros dentro de una interconexión mayor. De estar manera, la mayoría de problemas se resuelve aplicando un solo filtro para cada interconexión, es decir, subdividiendo el problema mayor. Sin embargo, el concepto resulta restricto.&lt;br /&gt;&lt;br /&gt;La salida producida por los programas escritos en UNIX, está en un formato reconocido como entrada por otros programas. Los archivos filtrables contienen líneas de texto sin encabezados decorativos, terminadores, ni líneas en blanco,. Cada renglón es un objeto de interés, de ahí que programas como &lt;b&gt;wc &lt;/b&gt;y &lt;b&gt;grep&lt;/b&gt; puedan contar elementos interesantes o buscarlos por nombre. Al momento de que se cuenta con mas imformación para cada objeto, el archivo permanece en su formato pero ahora agregando la división por columnas con campos separados mediante blancos o tabuladores, de esa manera programas como awk pueden seleccionar, procesar o rearreglar la información de manera sencilla.&lt;br /&gt;&lt;br /&gt;Cada filtro escribe sobre su salida estándar el resultado de procesar los archivos dados como argumentos o la entrada estándar si no se dan argumentos. Estos especifican la entrada pero nunca la salida, de esta manera, la salida de un comando puede introducirse en una interconexión. Los argumentos opcionales preceden a cualquier nombre de archivo y por último, los mensajes de error se escriben sobre el error estándar, por lo que no desaparecen a lo largo de las interconexiones.&amp;nbsp; Los comandos individuales, difícilmente, pueden hacer uso de tan sencilla estructura.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-5805879340332207687?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/5805879340332207687/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/02/uso-del-comando-awk-en-linux.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5805879340332207687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5805879340332207687'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/02/uso-del-comando-awk-en-linux.html' title='Uso del comando awk en linux'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-374994647395555536</id><published>2010-01-29T17:56:00.000-08:00</published><updated>2010-01-29T17:56:48.878-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='jsf'/><title type='text'>Ciclo de vida en JSF</title><content type='html'>&lt;div&gt;JSF (Java Server Faces) es un framework de desarrollo basado en el patrón MVC (Modelo Vista Control), su intención es estandarizar el desarrollo de aplicaciones web similar al estilo de Swing o Delphi, donde la interfaz se realiza mediante componentes y basada en eventos, esto permite que sea bastante flexible y sencillo, especialmente para quienes ya están acostumbrados a los componentes y eventos. &amp;nbsp;No obstante aún no tiene la experiencia de otros frameworks y es importante entender como trabaja.&lt;br /&gt;&lt;br /&gt;Algunos conceptos que debemos tener en mente son:&lt;br /&gt;&lt;b&gt;Managed Bea&lt;/b&gt;n (o Backing Bean) . Es un pojo que se asocia con los componentes de la interfaz de usuario (UIComponent), dentro de sus funciones está&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Almacenar referencias a los componentes de la vista y ponerlos a la disposición del controller (durante el ciclo de vida JSF).&lt;/li&gt;&lt;li&gt;Proveer de las propiedades necesarias para la vista, como el comportamiento de la pantalla, la información que se presenta e inclusive hasta algunos elementos del diseño gráfico.&lt;/li&gt;&lt;li&gt;Exponer los métodos que pueden ser usados por los componentes para comunicar al servidor de la iteracción con el usuario.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Binding&lt;/b&gt;, es el acceso programático a los componentes de la vista, mismos que heredan del árbol jerárquico de componentes con la raíz UIviewroot.&lt;/div&gt;&lt;div&gt; &lt;b&gt;Convertidores&lt;/b&gt;, son parte de la vista y es un proceso que transforma una cadena del lado de la vista a un tipo de dato Java en el lado del servidor y así mismo de regreso.&lt;/div&gt;&lt;div&gt;&lt;b&gt;Validaciones&lt;/b&gt;, son usadas para validar los datos de los componentes de acuerdo al uso de la vista o las reglas de negocio.&lt;/div&gt;&lt;div&gt;&lt;b&gt;Method expressions&lt;/b&gt;, son usados para comunicar eventos de la vista al modelo de presentación como ActionEvent, ValueChangeEvent, PhaseEvente.&amp;nbsp; Soportan invocaciones arbitrarias a métodos públicos del managed bean.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Ahora describiremos las 6 fases del ciclo de vida en JSF.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;1. Restaurar vista &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Restore View&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;En esta etapa se crea la vista con la información desde cero o la ya existente en los componentes si fue redireccionada desde otro control de jsf.&lt;/div&gt;&lt;div&gt;Si no encuentra datos enviados por método POST, se salta directamente a la etapa de producir respuesta.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;2. Aplicar valores a petición&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt; &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Apply Request Values&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Se invocan los convertidores definidos, si falla alguno, se marca el componente &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;UIComponent&lt;/span&gt; como erróneo con &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;setValid(true)&lt;/span&gt; y se agrega un mensaje al contexto de faces con &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;addMessage()&lt;/span&gt;, luego se va directamente a producir respuesta.&lt;/div&gt;&lt;div&gt;La funcionalidad del convertidor es transformar el dato &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;String&lt;/span&gt; de la forma a uno de tipo Java y viceversa, también mantiene el dato&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;String&lt;/span&gt;&amp;nbsp;para seguirlo&amp;nbsp;presentando&amp;nbsp;en pantalla en la etapa de producir respuesta.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finalmente se guardan&amp;nbsp;los valores enviados por la forma como cadenas dentro del componente&amp;nbsp;(&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;setters&lt;/span&gt; del &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;UIComponent&lt;/span&gt;). Cadena es lo único que pueden devolver la forma java: &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;HttpServletRequest.getParameter()&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Se puede usar el atributo &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;immediate&lt;/span&gt; para saltar el proceso de conversión y validación de datos. &amp;nbsp;Generalmente es usado para botones como Cancelar.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;3. Procesar validaciones&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt; &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Process Validation&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Se llama a los validadores de cada componente: &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;validate()&lt;/span&gt;, con la regla de profundidad primero, se usan los valores enviados por la fase de aplicación de valores, si alguna validación falla, se marca el componente como&amp;nbsp;erróneo&amp;nbsp;con&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;setValid(true)&lt;/span&gt;&amp;nbsp;y se agrega un mensaje con&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;addMessage()&lt;/span&gt;&amp;nbsp;, después salta directamente a la fase producir respuesta.&lt;/div&gt;&lt;div&gt;Aunque se pueden ejecutar validaciones de todo tipo, se recomienda que en esta fase se manejen solo aquellas que dicten el uso de la vista.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;4. Actualizar modelo&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt; &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Update Model&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Actualiza los beans&amp;nbsp;(mediante los&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;setters&lt;/span&gt;&amp;nbsp;del&amp;nbsp;ManagedBean) del modelo asociados al componente. &amp;nbsp;Esta asociación es generalmente usada con el atributo &lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;value&lt;/span&gt; del componente jsf.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;5. Invocar la aplicación&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt; &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Invoke Application&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Se ejecutan los eventos encolados y pendientes (&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;actionEvent&lt;/span&gt;).&lt;/div&gt;&lt;div&gt;En esta fase se ejecuta la lógica de negocio y es recomendable implementar aquí las validaciones del modelo de domino o procesos de negocio necesarios.&lt;/div&gt;&lt;div&gt;Como resultado de estas validaciones y/o procesos de negocio, se manipula la navegación entre las pantallas.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;6. Producir respuesta (final)&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt; &lt;span class="Apple-style-span" style="color: #3333ff;"&gt;:: Render Response&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Se genera la respuesta HTML, cada componente pregunta al modelo de presentación para recuperar los datos que necesita mostrar&amp;nbsp;(g&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;etters&lt;/span&gt;&amp;nbsp;del&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'courier new',monospace;"&gt;UIComponent&lt;/span&gt;).&lt;/div&gt;&lt;div&gt;Utiliza un kit de rendereo (o renderkit) que puede ser modificado para presentar la respuesta en xml, por ejemplo para un browser tipo wap.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Este ciclo de fases se repite&amp;nbsp;continuamente en cada petición que se hace al servidor. &amp;nbsp;Si se realizan peticiones parciales como en ICEfaces, también se produce el mismo ciclo con leves modificaciones para evitar ejecutar las conversiones y validaciones en campos que aún no han sido llenados por ejemplo.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;En resumen podríamos decir que por cada petición al servidor, las fases producen los siguientes pasos sobre los datos de las formas enviadas: convertir valores de la forma, validarlos, se generan eventos de cambio de valor (valueChangeListener), ejecuta setters en modelo de dominio (ManagedBean) y setters en modelo de presentación (UIComponent).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Notas finales&lt;/b&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cuando se usa el atributo immediate y la directiva renderResponse con programación pero se quiere guardar cualquier dato alterado en la forma, entonces se necesita usar ValueChangeEvent para actualizar manualmente el modelo de dominio.&lt;/li&gt;&lt;li&gt;ResponseComplete es una directiva similar al renderResponse, la diferencia radica en que el primero obliga a terminar el ciclo de vida del JSF y puede ser usado en procesos de lado del cliente para eventos AJAX, pero no se desea actualizar completamente la vista o intentar obtener datos binarios desde la vista.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Referencias&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.jsfcentral.com/articles/storyboard_2.html"&gt;Steven L. Murray&lt;/a&gt; | &lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=GuiaJSF"&gt;Iván Zaera Avellón&lt;/a&gt; |&lt;/div&gt;&lt;div&gt;Especificaciones &lt;a href="http://www.jcp.org/en/jsr/detail?id=127"&gt;JSR127&lt;/a&gt; | &lt;a href="http://www.jcp.org/en/jsr/detail?id=252"&gt;JSR252&lt;/a&gt; | &lt;a href="http://www.jcp.org/en/jsr/detail?id=276"&gt;JSR276&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-374994647395555536?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/374994647395555536/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/01/ciclo-de-vida-en-jsf.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/374994647395555536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/374994647395555536'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/01/ciclo-de-vida-en-jsf.html' title='Ciclo de vida en JSF'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-2500073042049584274</id><published>2010-01-26T23:28:00.001-08:00</published><updated>2010-01-26T23:29:36.529-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='presto'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>Mashups con Presto</title><content type='html'>&lt;div&gt;Después del curso de Presto, hice unas pequeñas anotaciones que me interesó compartir (antes que se queden como borrador en mi correo por una eternidad).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Un &lt;span style="font-style: italic;"&gt;portlet &lt;/span&gt;es una sección en la pagina web que permite ejecutar transacciones de forma separada, como una mini-aplicación independiente. De esta manera si se conjunta varios para visualizarlos como uno solo, se le llama &lt;span style="font-style: italic;"&gt;Orquestación&lt;/span&gt;.&lt;/div&gt;   &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Con Presto, la orquestación la realiza '&lt;span style="font-weight: bold;"&gt;Mashup engine&lt;/span&gt;' y para enlazar los servicios graficamente se hace con '&lt;span style="font-weight: bold;"&gt;Mashup Composer&lt;/span&gt;'. Ambos son parte de los servicios que proporciona Presto.&lt;br /&gt;&lt;/div&gt;  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Presto utiliza Mashlets, Mashups y Servicios, usando el &lt;span style="font-size:x-small;"&gt;Jackbe Universal Mashup Protocol &lt;/span&gt;(JUMP) y para producir salidas en formato &lt;span style="font-style: italic;"&gt;xml&lt;/span&gt; o &lt;span style="font-style: italic;"&gt;json&lt;/span&gt;. Los servicios se registran en '&lt;span style="font-weight: bold;"&gt;Service Explorer&lt;/span&gt;'.&lt;/div&gt;   &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;EMML &lt;/span&gt;es un lenguaje de programación que utiliza Presto para crear mashups. Algunos tags que utiliza son los que siguen.&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt; &amp;lt;mashup&amp;gt; - inicia el xml para crear un mashup&lt;/li&gt;&lt;li&gt;&amp;lt;foreach&amp;gt; - para generar un ciclo&lt;/li&gt;&lt;li&gt;&amp;lt;display&amp;gt; - para desplegar el contenido de una variable&lt;/li&gt;&lt;li&gt;&amp;lt;constructor&amp;gt; - permite construir la estructura raíz de la salida&lt;/li&gt;   &lt;li&gt;&amp;lt;operation&amp;gt; - define una operación a ejecutar&lt;/li&gt;&lt;li&gt;&amp;lt;annotate&amp;gt; - permite agregar elementos a un xml&lt;/li&gt;&lt;li&gt;&amp;lt;invoke&amp;gt; - permite invoca servicios publicados por Presto&lt;/li&gt;&lt;li&gt;&amp;lt;directinvoke&amp;gt; - sirve para invocar servicios que no son de Presto&lt;/li&gt;   &lt;li&gt;&amp;lt;merge&amp;gt; - se usa para hacer una mezcla de los valores de dos o mas variables&lt;/li&gt;&lt;li&gt;&amp;lt;filter&amp;gt; - permite filtrar contenido&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Presto también usa estos &lt;span style="font-weight: bold;"&gt;conectores &lt;/span&gt;para invocar servicios de Presto desde &lt;span style="font-style: italic;"&gt;Excel&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;JS&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;Java &lt;/span&gt;y &lt;span style="font-style: italic;"&gt;Csharp&lt;/span&gt;, entre otros.&lt;/div&gt;   &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;Glosario&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://es.wikipedia.org/wiki/XPath" target="_blank"&gt;xpath&lt;/a&gt; es una forma de recorrer la estructura xml&lt;/li&gt;&lt;li&gt;&lt;a href="http://es.wikipedia.org/wiki/XQuery" target="_blank"&gt;xquery&lt;/a&gt; es equivalente a SQL pero para datos que vienen en formato XML.&lt;/li&gt;   &lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;Ejemplos en la red&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Mashups no empresariales &lt;a href="http://pipes.yahoo.com/pipes/" target="_blank"&gt;Yahoo Pipes&lt;/a&gt; , &lt;a href="http://www.netvibes.com/" target="_blank"&gt;netvibes&lt;/a&gt; , &lt;/li&gt;   &lt;li&gt;Mashups empresariales &lt;a href="http://www.jackbe.com/products/index.php" target="_blank"&gt;Presto&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-2500073042049584274?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/2500073042049584274/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/01/mashups-con-presto.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2500073042049584274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/2500073042049584274'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/01/mashups-con-presto.html' title='Mashups con Presto'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-564468015543165796</id><published>2010-01-22T19:10:00.000-08:00</published><updated>2010-01-22T19:13:54.257-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='presto'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>Publicar Mashup por linea de comandos</title><content type='html'>Por si necesitan instalar mashups mediante la linea de comandos (sin necesidad del Eclipse y el plugin de Presto) debes hacer lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;En la carpeta &lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;\Presto2.7.0\mashupclient\bin&lt;/span&gt;&lt;/span&gt; dejar el archivo emml (o en tu caso tener identificada la ruta del emml)&lt;/li&gt;&lt;li&gt;Abrir una línea de comandos&lt;/li&gt;&lt;li&gt;Ir a la ruta &lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;\Presto2.7.0\mashupclient\bin&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Ejecutar la siguiente línea:&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;emmlpub -f mashup-script-filename -u user-name -p password [-desc description -t tag [...] -app application [...] -P provider -url presto-url]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;por ejemplo&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;emmlpub -f c:/miaplicacion/mashup/fgdasfad.emml -u admin -p adminadmin -url http://localhost:7070/presto/edge/api&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Obviamente en la URL debe ser la del server en donde vas a publicar el servicio.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-564468015543165796?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/564468015543165796/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/01/publicar-mashup-por-linea-de-comandos.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/564468015543165796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/564468015543165796'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/01/publicar-mashup-por-linea-de-comandos.html' title='Publicar Mashup por linea de comandos'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-7972114476263282178</id><published>2010-01-20T20:38:00.000-08:00</published><updated>2010-01-29T10:31:52.635-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Instalando e iniciandose con Symfony 1.4</title><content type='html'>&lt;a href="http://www.symfony-project.org/"&gt;Symfony&lt;/a&gt; es un framework para desarrollar aplicaciones web de manera rápida bajo &lt;a href="http://www.php.net/"&gt;PHP&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Actualmente se encuentra en su versión 1.4, y a la fecha es uno de los frameworks más populares para desarrollar con PHP (junto con &lt;a href="http://cakephp.org/"&gt;CakePHP&lt;/a&gt; y el &lt;a href="http://framework.zend.com/"&gt;Zend Framework&lt;/a&gt;...)&lt;br /&gt;&lt;br /&gt;El sitio web de Symfony presume su framework como uno de los más rápidos, no sólo para desarrollar, sino también para aprender. Según ellos, siguiendo sus tutoriales en un programa sencillo de aprendizaje, se podría decir que se toman exactamente 2 días (48 horas) en aprender Symfony. En realidad se podría llevar un poco más, dependiendo el tiempo libre que se tenga (además de que hay que dormir, comer y demás...)&lt;br /&gt;&lt;br /&gt;La instalación, configuración y levantamiento de un primer proyecto en Symfony es, en realidad, sencillo:&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Requisitos previos&lt;/b&gt;&lt;br /&gt;Un entorno LAMP podría ser suficiente (GNU/Linux&amp;nbsp; /&amp;nbsp; Apache&amp;nbsp; /&amp;nbsp; MySQL&amp;nbsp; /&amp;nbsp; PHP), o WAMP si se prefiere. En vez de MySQL, Symfony también puede trabajar, gracias a Doctrine, su ORM por defecto, con PostgreSQL, SQLite entre otros.&lt;br /&gt;&lt;br /&gt;El script localizado en:&lt;br /&gt;&lt;br /&gt;&lt;pre class="url"&gt;&lt;code&gt;&lt;a href="http://sf-to.org/1.4/check.php"&gt;http://sf-to.org/1.4/check.php&lt;/a&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Permite verificar si las características de la máquina corresponden con las necesarias para instalar y utilizar Symfony. Se baja el script y se ejecuta en el equipo con:&lt;br /&gt;&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;php check_configuration.php&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;br /&gt;Lo primero es descargar Symfony. En &lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif; font-size: x-small;"&gt;&lt;a href="http://www.symfony-project.org/installation"&gt;http://www.symfony-project.org/installation&lt;/a&gt;&lt;/span&gt; se encuentra una pequeña guía para bajar la versión que se desee instalar.&lt;br /&gt;&lt;br /&gt;Una vez con el paquete, debe descomprimirse (con &lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif; font-size: x-small;"&gt;tar -xzvf archivo.tar.gz&lt;/span&gt;) El directorio en donde se descomprime el paquete será el lugar en donde los proyectos de Symfony consultarán para los archivos que comparten dichos proyectos. El directorio en donde queda descomprimido Symfony se puede renombrar a &lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif; font-size: x-small;"&gt;symfony&lt;/span&gt; para simplificar.&lt;br /&gt;&lt;br /&gt;Hecha la instalación, se puede verificar que todo está en orden con:&lt;br /&gt;&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;php ruta_donde_se_descomprimio_symfony/symfony/data/bin/symfony -V&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;lo cual debe mostrar la versión instalada de Symfony.&lt;br /&gt;&lt;br /&gt;Si no se le pasan parámetros a symfony, se muestran todos los comandos disponibles para Symfony.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Creación de un proyecto&lt;/b&gt;&lt;br /&gt;Ubicados ya en el lugar en donde se desea crear el proyecto Symfony, se escribe:&lt;br /&gt;&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;php ruta_donde_se_descomprimio_symfony/symfony/data/bin/symfony generate:project NOMBRE_PROYECTO&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Lo cual creará dentro del directorio actual la estructura de un proyecto Symfony, que incluye varios directorios, utilizados por el framework para acceder a los recursos: la aplicación, el MVC, la base de datos, etc.&lt;br /&gt;&lt;br /&gt;También se crea un acceso directo a symfony, para no tener que teclear toda la ruta donde se descomprimió el framework. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Configuración de la Base de Datos&lt;/i&gt;&lt;br /&gt;La conexión a la Base de Datos se configura con un simple comando de Symfony:&lt;br /&gt;&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;php symfony configure:database "mysql:host=localhost;dbname=nombrebd" usuario password&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Por default, Symfony utiliza &lt;a href="http://www.doctrine-project.org/"&gt;Doctrine&lt;/a&gt; como ORM. Aunque también se puede utilizar &lt;a href="http://propel.phpdb.org/trac/"&gt;Propel&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Creación de una aplicación&lt;/i&gt;&lt;br /&gt;En Symfony, los proyectos se componen de aplicaciones (que a su vez se componen de módulos, y estos de tareas -o tasks-).&lt;br /&gt;&lt;br /&gt;La aplicación principal, el portal por así decirlo, se llama frontend (mientras que la aplicación de administración se llama backend). La creación de una aplicación es un proceso sencillo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;php symfony generate:app frontend&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Esto creará, dentro del directorio del proyecto, en el subdirectorio apps, un subdirectorio llamado frontend, con la estructura que el framework utiliza para sus aplicaciones.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Otras configuraciones&lt;/i&gt;&lt;br /&gt;Hay algo que debe tenerse en cuenta también, y es que los subdirectorios cache y log del proyecto deben poder ser vistos y escritos por cualquier usuario del sistema. En GNU/Linux:&lt;br /&gt;&lt;pre class="command-line"&gt;&lt;code&gt;chmod 777 cache/ log/&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;Configuración del servidor web&lt;/i&gt;&lt;br /&gt;Para poder acceder al proyecto, ya sea en desarrollo o en producción, el servidor web debe configurarse para que se pueda ver dicho proyecto. Una forma sencilla, pero poco elegante, es crear el proyecto directamente en el directorio en donde el servidor web publica, por ejemplo /var/www. Sin embargo, la mejor manera es utilizando VirtualHosts:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;NameVirtualHost 127.0.0.1:8080&lt;br /&gt;Listen 127.0.0.1:8080&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;br /&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;code&gt;&amp;lt;VirtualHost 127.0.0.1:8080&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;  DocumentRoot "ruta_al_proyecto/web"&lt;br /&gt;  DirectoryIndex index.php&lt;br /&gt;&lt;directory ruta_al_proyecto="" web=""&gt;&lt;/directory&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;code&gt;  &amp;lt;Directory "ruta_al_proyecto/web"&amp;gt;&lt;/code&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;directory ruta_al_proyecto="" web=""&gt;&lt;br /&gt;&lt;/directory&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;directory ruta_al_proyecto="" web=""&gt;    AllowOverride All&lt;br /&gt;    Allow from All&amp;nbsp;&lt;/directory&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;  &amp;lt;/Directory&amp;gt;&lt;/code&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;directory ruta_al_proyecto="" web=""&gt;&lt;br /&gt;&lt;/directory&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;directory ruta_al_proyecto="" web=""&gt;&lt;/directory&gt;  Alias /sf ruta_donde_se_descomprimio_symfony/symfony/data/web/sf&amp;nbsp;&lt;/virtualhost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;  &amp;lt;Directory "&lt;virtualhost 127.0.0.1:8080=""&gt;&lt;directory&gt;&lt;/directory&gt;&lt;/virtualhost&gt;&lt;/code&gt;&lt;code&gt;ruta_donde_se_descomprimio_symfony&lt;/code&gt;&lt;code&gt;/symfony/data/web/sf"&amp;gt;&lt;br /&gt;    AllowOverride All&lt;br /&gt;    Allow from All  &lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;  &amp;lt;/Directory&amp;gt;&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Con lo cual, se podrá acceder a la aplicación en http://localhost:8080. Obviamente, se puede configurar otro puerto, y los directorios deben apuntar a donde se encuentre en realidad el proyecto. Nótese el segundo alias, el que dice /sf, este apunta a donde se instaló Symfony. Esto se debe a que todo proyecto espera encontrar en su ruta /sf todo aquello que Symfony pone a disposición de todos los proyectos. En vez de descromprimir Symfony intacto proyecto por proyecto, un Alias simplifica esta labor.&lt;br /&gt;&lt;br /&gt;Y precisamente, lo único que queda es probar.&lt;br /&gt;&lt;br /&gt;Accediendo a:&lt;br /&gt;&lt;a href="http://localhost:8080/index.php/"&gt;&lt;code&gt;http://localhost:8080/index.php/&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Se debe de poder ver la pantalla de bienvenida por default que Symfony le pone a todos sus proyectos.&lt;br /&gt;&lt;br /&gt;En:&lt;br /&gt;&lt;br /&gt;&lt;pre class="url"&gt;&lt;code&gt;&lt;a href="http://localhost:8080/frontend_dev.php/"&gt;http://localhost:8080/frontend_dev.php/&lt;/a&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;se accede a la misma aplicación pero en la versión de desarrollo. Podrán notarse (si se configuró correctamente el VirtualHost), que aparecen en la parte superior derecha los iconos para diversa información útil a un desarrollador.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Symfony tiene muchas características interesantes. Es un framework que puede dar mucho de sí mismo, sólo es cosa de ponerse a aprenderlo, en un proceso que de por sí no es complicado. Una buena guía se puede encontrar en el tutorial &lt;a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/"&gt;Jobeet&lt;/a&gt;, para aprender Symfony en 48 horas...&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;span style="font-size: xx-small;"&gt;Nota: este tutorial, salió prácticamente intacto de lo que establece la guía &lt;a href="http://www.symfony-project.org/getting-started/1_4/en/"&gt;Getting started&lt;/a&gt; del sitio de Symfony.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-7972114476263282178?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/7972114476263282178/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2010/01/instalando-e-iniciandose-con-symfony-14.html#comment-form' title='15 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7972114476263282178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7972114476263282178'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2010/01/instalando-e-iniciandose-con-symfony-14.html' title='Instalando e iniciandose con Symfony 1.4'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-5439679949332301611</id><published>2009-12-30T13:55:00.000-08:00</published><updated>2010-01-29T10:35:28.622-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Instalar Trac para administrar proyectos</title><content type='html'>&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Administrar proyectos es parte que llega a volverse esencial cuando se&amp;nbsp; trata con proyectos que crecen poco a poco, como es el caso de los proyectos open source. Existe software hecho justamente para facilitar la administración de proyectos de software. En esta ocasión, vamos a hablar sobre &lt;a href="http://trac.edgewall.org/"&gt;Trac&lt;/a&gt;, un software hecho en Python con interfaz web para permitir la administración de proyectos.&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Trac incluye:&lt;/div&gt;&lt;ul style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;li&gt;un wiki para que el proyecto tenga su propio sitio en linea, y wiki es aun mejor si es un proyecto open source, para que los usuarios y desarrolladores puedan contar con la información más actualizada, de primera mano de parte de los mismos usuarios y desarrolladores&lt;/li&gt;&lt;li&gt;un administrador de issues o tickets para permitir estar al tanto de los bugs y sus correcciones, así como las mejoras hechas al software&lt;/li&gt;&lt;li&gt;conexión con el repositorio del código fuente del proyecto. Por defecto, Trac se conecta con repositorios SVN, pero permite también otros&lt;/li&gt;&lt;li&gt;utiliza una base de datos, ya sea SQLite, PostgreSQL o MySQL &lt;br /&gt;&lt;/li&gt;&lt;li&gt;otras características más, propias de un administrador de proyectos y que resultan útiles en ciertos momentos &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;Instalación rápida&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Este modo de instalación requiere de Python (versiones 2.3 a 2.6) así como easy_install:&lt;/div&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;easy_install Trac&lt;/span&gt;&lt;/blockquote&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;El cual instala Trac con SQLite y Genshi como framework de vista.&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;Requerimientos previos&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Si se hace una instalación rápida, se instalaría Trac utilizando SQLite. En cuanto a este tipo de instalación, sólo es necesario tener instalado &lt;a href="http://python.org/download"&gt;Python&lt;/a&gt; (versiones 2.3 a 2.6, la versión 3 aún no es soportada) y &lt;a href="http://peak.telecommunity.com/DevCenter/EasyInstall#installing-easy-install"&gt;easy_install&lt;/a&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Si se prefiere utilizar otro manejador de base de datos, entonces también es necesario tener los paquetes adecuados y los módulos para conectarse a los mismos con Python.&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Igualmente, si se desea instalar el soporte con un repositorio SVN, es necesario tener instalado Subversion, así como los bindings &lt;a href="http://svnbook.red-bean.com/svnbook-1.1/ch08s02.html#svn-ch-8-sect-2.3"&gt;SWIG&lt;/a&gt; para Python (ojo! &lt;a href="http://pysvn.tigris.org/"&gt;PySVN&lt;/a&gt; no funciona para Trac).&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Para publicar Trac en web, se necesita un servidor web. Puede ser cualquier servidor que soporte ya sea CGI, FastCGI o AJP, o en&amp;nbsp; todo caso, Apache con el módulo mod_swgi o con mod_python (esta última es la opción con la que yo lo he llegado a instalar).&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;Instalación&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Utilizando las setuptools, la instalación es sencilla:&lt;/div&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;easy_install http://svn.edgewall.org/repos/trac/tags/trac-0.11&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre class="wiki" style="font-family: Arial,Helvetica,sans-serif;"&gt;Aunque también se puede hacer desde el directorio superior del código fuente:&lt;/pre&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;python ./setup.py install&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre class="wiki" style="font-family: Arial,Helvetica,sans-serif;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="wiki" style="font-family: Arial,Helvetica,sans-serif;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="wiki" style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;Configuración&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Una vez instalado, hay que configurar dos cosas: el directorio en donde se almacenará la información del proyecto que se desea administrar, y el servidor web.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Para comenzar, se debe dar de alta el proyecto en donde quedará almacenado el sitio con la información del proyecto:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;div&gt;&lt;span style="font-size: x-small;"&gt;trac-admin /path/al/proyecto initenv&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;trac-admin&lt;/span&gt;&lt;/span&gt; pedirá información para inicializar el proyecto, como el path hacia el repositorio SVN (el cual es el tipo de repositorio por defecto), la conexión a la base de datos para usar (por defecto utiliza una base de datos con SQLite).&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Para probar el repositorio, se puede levantar provisionalmente un servidor web integrado para ver que todo funcione correctamente:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;tracd --port 8000 /path/to/myproject&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Con lo que, accediendo en el navegador a http://localhost:8000/ se puede ir hacia todos los proyectos administrados por trac.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Configurando el servidor web&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Trac se puede configurar para funcionar en modo CGI, mod_python de Apache, o FastCGI, e incluso en forma experimental en mod_wsgi de Apache&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;. A continuación explico la forma de configurar con mod_python, que es la forma en que yo lo levanté en mi servidor...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;1. Para empezar se debe asegurar que mod_python esté instalado en Apache. Una vez instalado, debe asegurarse de que Apache cargue el módulo mod_python al arrancar (cambiar el path a mod_python.so dependiendo la configuración de cada máquina):&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;blockquote&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;LoadModule python_module modules/mod_python.so&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif; font-size: small;"&gt;Una forma de probar que mod_python esté correctamente configurado es agregar lo siguiente a la configuración de Apache (y que debe borrarse una vez hecha la prueba... es como el phpinfo() de PHP):&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size: x-small;"&gt;&lt;span class="nt"&gt;&amp;lt; Location&lt;/span&gt; &lt;span class="err"&gt;/mpinfo&lt;/span&gt;&lt;span class="nt"&gt; &amp;gt;&lt;/span&gt;&lt;br /&gt;   SetHandler mod_python&lt;br /&gt;   PythonInterpreter main_interpreter&lt;br /&gt;   PythonHandler mod_python.testhandler&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt; / Location &amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;Y acceder a http://localhost/mpinfo&lt;/blockquote&gt;&lt;blockquote&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;2. La configuración básica de Apache para utilizar trac con mod_python es (cambiando la ubicación del proyecto trac y la url deseada según la máquina):&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size: x-small;"&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt; Location&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &lt;/span&gt;&lt;span class="err" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/projects/myproject&lt;/span&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;   SetHandler mod_python&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;   PythonInterpreter main_interpreter&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;   PythonHandler trac.web.modpython_frontend &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;   PythonOption TracEnv /var/trac/myproject&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;   PythonOption TracUriRoot /projects/myproject&lt;/span&gt;&lt;br /&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt; / Location &amp;gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;La opción TracUriRoot puede o no ser necesaria, deberá probarse con o sin ella...&lt;/blockquote&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;Otras opciones:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    # Un solo proyecto&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    PythonOption TracEnv /var/trac/myproject&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    # Varios proyectos&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    PythonOption TracEnvParentDir /var/trac/myprojects&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    # Para un indice de multiples proyectos&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    PythonOption TracEnvIndexTemplate /srv/www/htdocs/trac/project_list_template.html&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    # Para obtener la fecha en el orden deseado&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    PythonOption TracLocale en_GB.UTF8&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;Los eggs de Python (como los de Genshi) normalmente se descomprimen en un directorio en el cual Apache no puede escribir, esta opción se puede usar para apuntar a un directorio en el que Apache sí pueda escribir:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PythonOption PYTHON_EGG_CACHE /var/trac/myprojects/egg-cache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;3. La autenticación es necesaria para configurar el acceso al area de administración de trac. En Apache:&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size: x-small;"&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt; Location&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &lt;/span&gt;&lt;span class="err" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/projects/myproject/login&lt;/span&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  AuthType Basic&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  AuthName "myproject"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  AuthUserFile /var/trac/myproject/.htpasswd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  Require valid-user&lt;/span&gt;&lt;br /&gt;&lt;span class="nt" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt; / Location &amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;4. Más opciones, se pueden ver en &lt;a href="http://trac.edgewall.org/wiki/TracModPython"&gt;http://trac.edgewall.org/wiki/TracModPython&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Más configuraciones&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Otras opciones y configuraciones se pueden configurar en trac.ini, el archivo de configuración que se encuentra en el directorio conf del proyecto. Por ejemplo, se puede definir un logotipo para el proyecto, entre otras cosas.&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;El resto consiste en utilizar trac para poder administrar los proyectos: editando el wiki, utilizando el administrador de issues, etc.&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Toda esta información se encuentra de hecho en el sitio oficial del proyecto trac: &lt;a href="http://trac.edgewall.org/wiki/TracInstall"&gt;http://trac.edgewall.org/wiki/TracInstall&lt;/a&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;pre class="wiki" style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-5439679949332301611?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/5439679949332301611/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/12/instalar-trac-para-administrar.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5439679949332301611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5439679949332301611'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/12/instalar-trac-para-administrar.html' title='Instalar Trac para administrar proyectos'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4622619089575270827</id><published>2009-11-26T20:00:00.000-08:00</published><updated>2009-11-26T20:00:04.455-08:00</updated><title type='text'>40 años de UNIX</title><content type='html'>Esta entrada no es un how-to, pero creo pertinente escribir sobre la importancia de este hecho. 2009 es el año en que el sistema operativo UNIX cumple 40 años de haber sido creado en los laboratorios Bell...&lt;br /&gt;&lt;br /&gt;De los primeros sistemas en tener éxito como sistema multitarea, el primero en poder ser portado a muchas plataformas gracias al lenguaje C, que prácticamente nació a la par de UNIX, ancestro de sistemas de tanta importancia hoy en día como Linux, openBSD, openSolaris. UNIX es, sin duda, uno de los grandes inventos del siglo XX.&lt;br /&gt;&lt;br /&gt;Como pequeño homenaje, una serie de links para narrar la historia de este sistema:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jstitch.blogspot.com/2008/12/historia-de-unix-parte-1.html"&gt;Historia de UNIX, parte 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jstitch.blogspot.com/2009/01/historia-de-unix-parte-2.html"&gt;Historia de UNIX, parte 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jstitch.blogspot.com/2009/01/historia-de-unix-parte-3.html"&gt;Historia de UNIX, parte 3&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jstitch.blogspot.com/2009/02/historia-de-unix-parte-4.html"&gt;Historia de UNIX, parte 4&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;saludos!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4622619089575270827?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4622619089575270827/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/11/40-anos-de-unix.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4622619089575270827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4622619089575270827'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/11/40-anos-de-unix.html' title='40 años de UNIX'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-4501773031697143582</id><published>2009-11-04T16:06:00.000-08:00</published><updated>2010-02-04T20:31:28.607-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='js'/><category scheme='http://www.blogger.com/atom/ns#' term='designing'/><title type='text'>Configurar SyntaxHighlighter en tu blog</title><content type='html'>Esta configuración está probada para &lt;a href="http://blogger.com/" target="_blank"&gt;blogger.com&lt;/a&gt;, pero quizá tengas wordpress, drupal,&lt;br /&gt;joomla, o algún otro y no funcione del todo bien, en ese caso es&lt;br /&gt;mejor que consultes el sitio original para una mejor ayuda y soporte&lt;br /&gt;en: &lt;a href="http://alexgorbatchev.com/" target="_blank"&gt;http://alexgorbatchev.com/&lt;/a&gt;&lt;br /&gt;&lt;b&gt;1. &lt;/b&gt;Primero &lt;b&gt;apuntar al core &lt;/b&gt;de Syntax Highlighter.&lt;br /&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/&amp;gt;&lt;br /&gt;&amp;lt;link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/&amp;gt;&lt;br /&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;2. &lt;/b&gt;Configuración &lt;b&gt;para cada lenguaje &lt;/b&gt;(&lt;i&gt;Brushes&lt;/i&gt;):&lt;br /&gt;Debes de incluir tantos "&lt;i&gt;brushes&lt;/i&gt;" como vayas a necesitar. En este caso Java:&lt;br /&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;mas brushes ... y la &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes"&gt;lista sigue creciendo&lt;/a&gt;&lt;br /&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/&amp;gt;&lt;br /&gt;&amp;lt;script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js'&lt;br /&gt;type='text/javascript'/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;3. &lt;/b&gt;Finalmente, &lt;b&gt;activarlo&lt;/b&gt;.&lt;br /&gt;&lt;pre class="brush:js;"&gt;&amp;lt;script type='text/javascript'&amp;gt;&lt;br /&gt;SyntaxHighlighter.config.bloggerMode = true;&lt;br /&gt;SyntaxHighlighter.all();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;4. &lt;/b&gt;En tus &lt;b&gt;publicaciones &lt;/b&gt;debes colocar tu código dentro del tag &lt;br /&gt;&lt;pre&gt;Ejemplo: (tambien puedes usar como class: js, bash, shell, java, css, sql, ...)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml;"&gt;&amp;lt;pre class="brush:xml; highlight:[3,7,8]"&amp;gt;&lt;br /&gt;&amp;lt;xml:mi codigo="aqui"/&amp;gt;&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;/pre&gt;El atributo &lt;i&gt;class&lt;/i&gt; define el lenguaje y &lt;i&gt;highlight&lt;/i&gt; las lineas que quierassobresaltar en tu código.&lt;b&gt;Notas:&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Toma en cuenta que al estar apuntando a &lt;a href="http://alexgorbatchev.com/" target="_blank"&gt;http://alexgorbatchev.com&lt;/a&gt;,  si este sitio se cae o no responde, puedes no ver tu código tan bonito como lo quieres.&lt;/li&gt;&lt;li&gt;Pero si tienes un sitio personal, puedes descargar los scripts y  usarlos sin el conveniente anterior.&lt;/li&gt;&lt;li&gt;Usa dentro de tu codigo, preferentemente &amp;amp;gt; y &amp;amp;lt;, en vez de &amp;gt; y &amp;lt;, respectivamente. &lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Referencias&lt;/b&gt;:&lt;ul&gt;&lt;li&gt;&lt;a href="http://alexgorbatchev.com/" target="_blank"&gt;http://alexgorbatchev.com/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-4501773031697143582?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/4501773031697143582/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/11/configurar-syntaxhighlighter-en-tu-blog.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4501773031697143582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/4501773031697143582'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/11/configurar-syntaxhighlighter-en-tu-blog.html' title='Configurar SyntaxHighlighter en tu blog'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-373218158800654224</id><published>2009-10-19T17:13:00.000-07:00</published><updated>2009-10-19T17:15:42.346-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>El Zen de Python</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp; Bello es mejor que feo.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Explícito es mejor que implícito.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Simple es mejor que complejo.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Complejo es mejor que complicado.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Plano es mejor que anidado.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Escaso es mejor que denso.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; La legibilidad cuenta.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Los casos especiales no son tan especiales como para romper las reglas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Aunque lo práctico vence a lo puro.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Los errores nunca deben ocurrir silenciosamente.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A menos que hayan sido silenciados explícitamente.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ante la ambigüedad, rehuye la tentación de adivinar.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debería haber una-- y preferiblemente solamente una --manera obvia de hacerlo.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Aunque esa manera puede no ser obvia de inmediato a menos que seas Holandés.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ahora es mejor que nunca.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Aunque nunca es muchas veces mejor que *ahorita*.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Si la implementación es difícil de explicar, es una mala idea.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Si la implementación es fácil de explicar, puede que sea una buena idea.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Los espacios de nombres son una tremenda gran idea -- ¡hay que hacer más de esos!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(traducido libremente al español por un servidor, del &lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;original en inglés&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-373218158800654224?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/373218158800654224/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/10/el-zen-de-python.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/373218158800654224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/373218158800654224'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/10/el-zen-de-python.html' title='El Zen de Python'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-6144465521966949562</id><published>2009-09-27T20:26:00.000-07:00</published><updated>2010-01-29T10:40:11.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Configuración de TurboGears 2.0</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introducción&lt;/span&gt;&lt;br /&gt;TurboGears es un framework para desarrollar aplicaciones web basadas en el lenguaje de programación &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La &lt;a href="http://turbogears.org/2.0"&gt;versión 2&lt;/a&gt; está basada en el modelo MVC, con los siguientes frameworks como base:&lt;br /&gt;&lt;br /&gt;-&lt;a href="http://sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;, el ORM que sirve como Modelo.&lt;br /&gt;-&lt;a href="http://genshi.edgewall.org/"&gt;Genshi&lt;/a&gt;, el framework que permite manipular la Vista a través de tags específicos.&lt;br /&gt;-&lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;, proporciona el Controlador.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Requerimientos previos&lt;/span&gt;&lt;br /&gt;Para poder usar TurboGears se necesita tener lo siguiente:&lt;br /&gt;&lt;br /&gt;-Python a partir de la versión 2.4 (por ahora la versión 3 no es compatible)&lt;br /&gt;&lt;br /&gt;-Las setuptools (&lt;a href="http://peak.telecommunity.com/dist/ez_setup.py"&gt;peak.telecommunity.com/dist/ez_setup.py&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;-Drivers adecuados para las bases de datos que se utilizarán. SQLAlchemy soporta gran número de controladores de BD, como &lt;span style="font-style: italic;"&gt;SQLite&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;MySQL&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;PostgreSQL&lt;/span&gt;, etc. El lector deberá encargarse de instalar los drivers adecuados para Python según sus necesidades.&lt;br /&gt;&lt;br /&gt;-Otras dependencias, por ejemplo los headers de Python que se pueden encontrar en las utilidades de instalación de la distribución Linux que se esté usando, o la win32API para Windows.&lt;br /&gt;&lt;br /&gt;-Virtualenv, una utilidad que permite establecer un ambiente de desarrollo y producción local a cierto directorio, con el que TurboGears evita problemas de dependencias y demás. Se pueden usar las Setuptools para esto:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;easy_install virtualenv&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Instalación del ambiente&lt;/span&gt;&lt;br /&gt;La manera más sencilla es utilizar el script que se encuentra en:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.turbogears.org/2.0/downloads/current/tg2-bootstrap.py"&gt;http://www.turbogears.org/2.0/downloads/current/tg2-bootstrap.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Y después ejecutarlo con:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;python tg2-bootstrap.py --no-site-packages tg2env&lt;/blockquote&gt;&lt;br /&gt;Donde tg2env es la ruta a un directorio previamente creado y en donde se almacenará el ambiente virtual de desarrollo y/o producción.&lt;br /&gt;&lt;br /&gt;Para continuar, antes debe activarse el ambiente virtual. En tg2env (o cualquier nombre que se le haya dado) se encuentra el script bin/activate (o activate.bat para Windows). Solo hay que ejecutarlo, directamente en Windows, o en Linux con:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;source bin/activate&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;El prompt de la consola cambiará a algo como&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;(tg2env) $prompt_por_default_de_la_consola&lt;/blockquote&gt;&lt;br /&gt;Al terminar de trabajar con TurboGears se debe desactivar el ambiente con&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;deactivate&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;En Windows debe ejecutarse bin/deactivate.bat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Instalación de TurboGears&lt;/span&gt;&lt;br /&gt;Con virtualenv activado, sólo queda instalar TurboGears:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;easy_install -i http://www.turbogears.org/2.0/downloads/current/index tg.devtools&lt;/blockquote&gt;&lt;br /&gt;La manera de probar que todo esté bien es ejecutando el script paster; &lt;a href="http://pythonpaste.org/"&gt;Paste&lt;/a&gt; es un programa Python que permite publicar un servidor HTTP ligero y que TurboGears adapta y utiliza para varias tareas (aunque, claro está, habrá que investigar todavía la manera de publicar en otro servidor web, como Apache con mod_python):&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;paster --help&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;debe mostrar la ayuda del script, y con la misma al final un par de comandos nuevos para TurboGears.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Creación de un nuevo proyecto&lt;/span&gt;&lt;br /&gt;Utilizando paster, se puede crear y configurar un proyecto de TurboGears de manera sencilla y rápida:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;paster quickstart&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;A dicho script habrá que proporcionarle el nombre común del proyecto, el nombre Python del mismo y si se desea activar autenticación. Con eso basta para crear el proyecto en el directorio tg2env/nombre_comun_del_proyecto&lt;br /&gt;&lt;br /&gt;Se debe ejecutar entonces:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;cd tg2env/nombre_comun&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;python setup.py develop&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Se puede editar el archivo nombre_comun/nombre_python/websetup.py para editar datos iniciales de la BD, como de la autenticación.&lt;br /&gt;&lt;br /&gt;Si se hace ésto o si se activó la autenticación aún sin haberla editado, hay que ejecutar:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;paster setup-app development.ini&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;El archivo development.ini contiene las configuraciones del proyecto, por ejemplo:&lt;br /&gt;&lt;br /&gt;-el &lt;span style="font-style: italic;"&gt;puerto &lt;/span&gt;en que se publicará la aplicación (por defecto el 8080)&lt;br /&gt;-la &lt;span style="font-style: italic;"&gt;dirección IP&lt;/span&gt; a la que se publicará (por defecto localhost, si se coloca 0.0.0.0 se publicará a toda la red)&lt;br /&gt;-la &lt;span style="font-style: italic;"&gt;conexión a la base de datos&lt;/span&gt; (por defecto un archivo de SQLite)&lt;br /&gt;&lt;br /&gt;Para deployar el proyecto hay que ejecutar:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;paster serve development.ini&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Con paster serve se pueden usar también otros parámetros, por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;--reload&lt;/span&gt; para que el servidor detecte automáticamente cambios en los archivos del proyecto&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;--daemon&lt;/span&gt; para ejecutar el servidor como demonio en segundo plano (por defecto en el archivo paster.log se almacenará el registro que vaya pintando el servidor conforme se utilice)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;--stop-daemon&lt;/span&gt; para detener el servidor si está activo en segundo plano&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;--status&lt;/span&gt; da el estado del servidor en caso de estar en segundo plano&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;--help&lt;/span&gt; da la ayuda completa del script&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Más información&lt;/span&gt;&lt;br /&gt;El sitio de TurboGears contiene documentación, tutoriales y mucha más información.&lt;br /&gt;&lt;br /&gt;Los sitios particulares de cada plataforma en que se basa TurboGears también serán esenciales para una completa documentación (Python, SQLAlchemy, Genshi, Pylons).&lt;br /&gt;&lt;br /&gt;El sitio de PythonPaste también será útil.&lt;br /&gt;&lt;br /&gt;Como siempre, Google es un buen compañero, o el buscador de preferencia en todo caso.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;Javier Novoa C.&lt;br /&gt;&lt;a href="http://invernalia.homelinux.net/"&gt;http://invernalia.homelinux.net&lt;/a&gt;&lt;br /&gt;(Posted using BlogPress from my iPodTouch)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-6144465521966949562?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/6144465521966949562/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/09/configuracion-de-turbogears-20.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6144465521966949562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6144465521966949562'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/09/configuracion-de-turbogears-20.html' title='Configuración de TurboGears 2.0'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-6917920079377607980</id><published>2009-09-22T15:36:00.001-07:00</published><updated>2010-02-04T20:32:26.916-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='red'/><title type='text'>Levantando una sencilla VPN con OpenVPN parte 3</title><content type='html'>&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-family: georgia; font-size: 100%; font-weight: bold;"&gt;Configuración de la VPN&lt;/span&gt;&lt;span style="font-family: georgia; font-size: 100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: georgia; font-size: 100%; font-style: italic;"&gt;Generación de llaves (continuación...)&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;Teniendo claro cómo funciona la seguridad en una VPN, lo que sigue es generar las llaves y&lt;br /&gt;certificados apropiados para poder configurar, ahora sí, la VPN entre las máquinas que deseamos&lt;br /&gt;tener 'cerca'.&lt;br /&gt;&lt;br /&gt;OpenVPN viene de por sí con algunos scripts que pueden aprovecharse para la generación del&lt;br /&gt;esquema de seguridad de la red. El único requisito previo es tener instalado el software&lt;br /&gt;OpenSSL, el cual utilizan dichos scripts. (Sin embargo, si instalas desde alguna utilidad de tu&lt;br /&gt;distribución Linux, o desde Windows, el software SSL adecuado se preinstala también, pues es&lt;br /&gt;un requisito previo).&lt;br /&gt;&lt;br /&gt;Los pasos en este caso son sencillos:&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ol style="font-family: georgia;"&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt; Se genera el certificado (conocido también como 'llave pública'), así como las llaves privadas tanto para el servidor como para cada cliente.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Se genera un certificado y una llave para el 'master Certificate Authority' (CA), que se utilizan para firmar cada uno de los certificados generados anteriormente.&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;Si estás utilizando algun servidor estilo Unix, entonces ve al subdirectorio easy-rsa, que se&lt;br /&gt;encuentra en donde esté instalado OpenVPN. Por ejemplo:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;/usr/share/doc/packages/openvpn&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;Si estás utilizando Windows, el subdirectorio easy-rsa podría estar en:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;\Program Files\OpenVPN\&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul style="font-family: georgia;"&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;El primer paso consistirá en inicializar los scripts (eliminando cualquier configuración previa que se tuviera antes):&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: 100%;"&gt;init-config&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul style="font-family: georgia;"&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Después, debe editarse el archivo vars (o vars.bat en Windows) para establecer los parámetros KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG y KEY_EMAIL (estos son parámetros propios de OpenSSL, se puede averiguar más sobre ellos googleando un poco sobre este software).&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;En seguida, se debe inicializar la infraestructura de llaves públicas, ejecutando los siguientes scripts:&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-family: courier new;"&gt;vars&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;clean-all&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;build-ca&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;El último de dichos scripts (&lt;span style="font-family: courier new;"&gt;build-ca&lt;/span&gt;), construye el certificate authority (CA) y la llave,&lt;br /&gt;al invocar el comando openssl. Conforme lo solicite, debe introducirse a dicho script la&lt;br /&gt;información necesaria para terminar de construir los archivos que se están generando.&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Posteriormente, se generan el certificado y la llave privada del servidor:&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;build-key-server server&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;El Common Name a utilizar debería ser 'server'.&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;En seguida, se generan los certificados y llaves de cada cliente:&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-family: courier new;"&gt;build-key cliente1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;build-key cliente2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;build-key clienteN&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;El Common Name sería 'clienteX', donde X es el número del cliente a configurar.&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Por último se generan los parámetros Diff Hellman para el servidor OpenVPN:&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;build-dh&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Y ya como paso final, de los archivos generados, hay que llevarlos a las computadoras adecuadas:&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-style: italic;"&gt;ca.crt&lt;/span&gt; - en el servidor y en todos los clientes&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ca.key&lt;/span&gt; - para firmar más certificados (en donde quiera que se vaya a realizar esta operacion)&lt;br /&gt;(keep secret!)&lt;br /&gt;&lt;span style="font-style: italic;"&gt;dh{n}.pem&lt;/span&gt; - en el servidor&lt;br /&gt;&lt;span style="font-style: italic;"&gt;server.crt&lt;/span&gt; - en el servidor&lt;br /&gt;&lt;span style="font-style: italic;"&gt;server.key&lt;/span&gt; - en el servidor (keep secret!)&lt;br /&gt;&lt;span style="font-style: italic;"&gt;clientX.crt&lt;/span&gt; - en el cliente X&lt;br /&gt;&lt;span style="font-style: italic;"&gt;clientX.key&lt;/span&gt; - en el cliente X (keep secret!)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Archivos de configuracion&lt;/span&gt;&lt;br /&gt;De manera similar a los scripts que OpenVPN tiene para facilitar la configuración de la&lt;br /&gt;infraestructura de llave pública, también se incluyen archivos de configuración de ejemplo,&lt;br /&gt;para facilitar esta segunda, y última parte, de la configuración de la VPN.&lt;br /&gt;&lt;br /&gt;En sistemas tipo Unix, estos pueden encontrarse, tal vez, en&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-family: courier new;"&gt;/usr/share/doc/packages/openvpn&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;En Windows, puede buscarse en&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;\Program Files\OpenVPN\sample-config&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;server&lt;/span&gt;&lt;br /&gt;En cuanto al servidor, lo esencial es configurar el número de puerto y protocolo a utilizar&lt;br /&gt;(por defecto, se tiene el puerto UDP 1194)&lt;br /&gt;&lt;br /&gt;Así mismo, debe especificarse la localización de los archivos&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;ca.crt, server.crt, server.key y dh.pem&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;Igualmente, debe configurarse el rango de direcciones IP que podran tomar los clientes de la&lt;br /&gt;VPN, según el diseño previamente establecido&lt;br /&gt;&lt;br /&gt;Puede establecerse que los clientes de la VPN puedan verse entre sí o solamente vean al&lt;br /&gt;servidor, con la directiva client-client&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;clientes&lt;/span&gt;&lt;br /&gt;Lo mismo que en el servidor, debe especificarse la ubicacion de los archivos&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;ca.crt, clientX.crt y clientX.key&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;En la directiva remote se establece la dirección IP del servidor, que será contactado para&lt;br /&gt;unirse a la VPN&lt;br /&gt;&lt;br /&gt;Debe verificarse que la configuración de cada cliente sea consistente con lo que se estableció&lt;br /&gt;en el servidor. Por ejemplo, el protocolo y puerto deben ser el mismo&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Arranque&lt;/span&gt;&lt;br /&gt;Para arrancar la VPN, comenzando por el servidor, se ejecuta lo siguiente:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;openvpn [localizacion del archivo de configuracion]&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;Si todo es correcto, ejecutando ifconfig (o el programa para averiguar las direcciones IP&lt;br /&gt;disponibles que se tenga) se debe observar que existe una nueva dirección IP, correspondiente&lt;br /&gt;a la VPN, para un dispositivo tun o tap (dependiendo cómo se hubiera configurado la VPN, el&lt;br /&gt;más común es tun)&lt;br /&gt;&lt;br /&gt;Una manera sencilla de probar la VPN es, una vez levantados el servidor y algun cliente, hacer&lt;br /&gt;un ping entre ellos, con lo que ambas máquinas deben de verse:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size: 100%;"&gt;ping IP_VPN&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 100%;"&gt;si algo saliera mal, primero hay que verificar que no haya problemas de firewall, con el puerto&lt;br /&gt;y protocolo establecidos en la configuración, por ejemplo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Arranque automático&lt;/span&gt;&lt;br /&gt;En el caso de Linux, la distribución debería de haber dejado instalado el script&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;/etc/init.d/openvpn&lt;/span&gt;, el cual se encarga de buscar todos los archivos &lt;span style="font-family: courier new;"&gt;.conf&lt;/span&gt; que se&lt;br /&gt;encuentrenen &lt;span style="font-family: courier new;"&gt;/etc/openvpn&lt;/span&gt;, por lo que hay que colocar ahí los archivos de configuración&lt;br /&gt;recientemente editados, para que OpenVPN se inicie en automático correctamente.&lt;br /&gt;&lt;br /&gt;En Windows, al instalar OpenVPN se debe configurar el software como un servicio.&lt;br /&gt;OpenVPN buscará los archivos de configuración que se encuentren en&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;\Program Files\OpenVPN\config&lt;/span&gt;, para el inicio automático.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Resumen&lt;/span&gt;&lt;br /&gt;En resumen, la instalación /configuración /arranque de OpenVPN consiste de:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Generar los archivos de certificados y llaves necesarios para servidor y clientes (se pueden utilizar los scripts que OpenVPN ya incluye), llevando cada archivo a su ubicación final según lo que se dijo anteriormente&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Generar el archivo de configuración, ya sea para el servidor o el cliente, tomando en cuenta el tipo de VPN (tun o tap), la ip del servidor (en caso de configurar un cliente), el rango de ips que tendrán las máquinas pertenecientes a la VPN (en caso de configurar el servidor), el puerto y protocolo de comunicación (por defecto UDP 1194), la ubicación de los archivos de seguridad generados en el paso anterior, si se desea que haya comunicación entre clientes (en caso de configurar el servidor), y verificar la consistencia de las configuraciones entre los clientes y el servidor, además de cualquier otra cosa que se desee configurar en dichos archivos&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Para un arranque automático, colocar los archivos de configuración en los directorios adecuados, dependiendo el sistema y la distribución del mismo (consultar los manuales y google para más información, en caso de que lo dicho aquí no sea genérico para todos los casos)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Al arrancar OpenVPN, validar esto mismo observando que existe una nueva dirección IP para la máquina en cuestión, y ésta dirección debe caer forzosamente en el rango establecido al configurar el servidor&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;Una vez con dos o más máquinas configuradas correctamente, validar esto mismo, observando que todas las máquinas pueden 'verse' entre sí (o sólo cada cliente con el servidor, dependiendo las configuraciones de este último) vía la dirección IP asignada para la VPN de cada una&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre style="font-family: georgia;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Referencias&lt;/span&gt;&lt;br /&gt;OpenVPN, como buen software open source, está muy bien documentado, tanto en la&lt;br /&gt;instalación del propio software como en línea, en su sitio oficial (&lt;a href="http://www.blogger.com/www.openvpn.net"&gt;www.openvpn.net&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Precisamente en éste último sitio, se encuentra un HOWTO bastante completo, en el cual me&lt;br /&gt;basé totalmente para generar esta pequeña serie de posts (y por si quedan dudas, también me&lt;br /&gt;basé en el mismo tutorial para generar una VPN que utilizo yo mismo entre mi máquina que&lt;br /&gt;funciona como servidor y las máquinas de mi trabajo, la de mi esposa, mi hermano y mi mamá,&lt;br /&gt;para el caso de que les pueda proporcionar yo mismo ayuda vía remota desde donde quiera que&lt;br /&gt;me encuentre).&lt;br /&gt;Dicho HOWTO se puede leer en línea en:&lt;br /&gt;&lt;a href="http://www.openvpn.net/index.php/open-source/documentation/howto.html"&gt;http://www.openvpn.net/index.php/open-source/documentation/howto.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn.html"&gt;Ver la parte 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn_14.html"&gt;Ver la parte 2&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-6917920079377607980?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/6917920079377607980/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/09/levantando-una-sencilla-vpn-con-openvpn.html#comment-form' title='11 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6917920079377607980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6917920079377607980'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/09/levantando-una-sencilla-vpn-con-openvpn.html' title='Levantando una sencilla VPN con OpenVPN parte 3'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3578046874090827460</id><published>2009-09-18T15:56:00.000-07:00</published><updated>2010-02-04T20:33:43.761-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='annotation'/><title type='text'>Configurar la capa de servicios como transaccionales con spring aop</title><content type='html'>Existen diversos conceptos que ya voy a dar por conocidos en esta publicación como lo son un advice, un target, un pointcut, un advisor y un aspecto, entre otros. Pero pueden conocer mas en la &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop.html" target="_blank"&gt;documentación de referencia sobre aop&lt;/a&gt; de Spring (inglés).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/images/tx.png" target="_blank"&gt;http://static.springsource.&lt;wbr&gt;&lt;/wbr&gt;org/spring/docs/2.5.x/&lt;wbr&gt;&lt;/wbr&gt;reference/images/tx.png&lt;/a&gt;&lt;br /&gt;Conceptualmente una transacción luce como la imagen aqui arriba pero vamos a describir un poco mas el detalle.&lt;br /&gt;&lt;br /&gt;Primeramente necesitamos la dependencia de spring-aspects, considerando que nuestro proyecto sea maven, debemos agregar a nuestro pom.xml la siguiente dependencia (por ahora usaremos la ón 2.5.6):&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;&amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;&lt;br /&gt;&amp;lt;artifactid&amp;gt;spring-aspects&amp;lt;/artifactid&amp;gt;&lt;br /&gt;&amp;lt;version&amp;gt;2.5.6&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Basicamente necesitamos configurar tres elementos, (1) el manejador de las transacciones y su fuente de datos o DataSource, (2) un advice que es el código a ejecutar antes y/o despues de una petición a la base de datos punto central para iniciar-propagar-terminar una transaccion, y finalmente (3) un advisor, que es la relación de dicho advice con un pointcut.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.- Manejador de transacciones (TransactionManager)&lt;/b&gt;&lt;br /&gt;Como nuestro manejador de transacciones requiere de una fuente de datos vamos a configurarla con un driver de mysql de la siguiente forma de momento pues no abundaremos en la configuracion del datasource:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource"&amp;gt;&lt;br /&gt;&amp;lt;property name="driverClassName" value="com.mysql.jdbc.Driver"/&amp;gt;&lt;br /&gt;&amp;lt;property name="url" value="jdbc:mysql://localhost/miBaseDatos"/&amp;gt;&lt;br /&gt;&amp;lt;property name="username" value="user_sa"/&amp;gt;&lt;br /&gt;&amp;lt;property name="password" value="mipass_sa"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Luego necesitamos escoger una estrategia de transaccionalidad que implemente la interface de spring &lt;i&gt;org.springframework.&lt;wbr&gt;&lt;/wbr&gt;transaction.&lt;wbr&gt;&lt;/wbr&gt;PlatformTransactionManager&lt;/i&gt;, y dado que usaremos MySQL en este caso, escogemos: &lt;i&gt;DataSourceTransactionManager&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml; highlight:[2]"&gt;&amp;lt;bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&amp;gt;&lt;br /&gt;&amp;lt;property name="dataSource" ref="basicDataSource"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.- Advice&lt;/b&gt;&lt;br /&gt;Lo que sigue es configurar el advice o la forma en que se va a manejar la transaccionalidad, para ello necesitamos agregar el esquema y el esquema location de transaccion a nuestro tag &lt;beans&gt; del archivo de configuración de contexto de Spring:&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;xmlns:tx="&lt;a href="http://www.springframework.org/schema/tx" target="_blank"&gt;http://www.&lt;wbr&gt;&lt;/wbr&gt;springframework.org/schema/tx&lt;/a&gt;"&lt;/li&gt;&lt;li&gt;xsi:schemaLocation="&lt;a href="http://www.springframework.org/schema/tx" target="_blank"&gt;http://&lt;wbr&gt;&lt;/wbr&gt;www.springframework.org/&lt;wbr&gt;&lt;/wbr&gt;schema/tx&lt;/a&gt; &lt;a href="http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" target="_blank"&gt;http://www.springframework.&lt;wbr&gt;&lt;/wbr&gt;org/schema/tx/spring-tx-2.5.&lt;wbr&gt;&lt;/wbr&gt;xsd&lt;/a&gt;"&lt;/li&gt;&lt;/ul&gt;Luego necesitamos usar el esquema &lt;b&gt;tx:advice &lt;/b&gt;para crear nuestro advice y hacer referencia a nuestro bean con el manejador de transacciones (&lt;b&gt;txManager&lt;/b&gt;), indicamos con &lt;b&gt;tx:attributes&lt;/b&gt; la semántica que define en qué métodos (&lt;b&gt;tx:method&lt;/b&gt;) van a ser considerados para iniciar/propagar una transacción y configurar el tipo de transacción.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;tx:advice id="txAdvice" transaction-manager="txManager"&amp;gt;&lt;br /&gt;&amp;lt;tx:attributes&amp;gt;&lt;br /&gt;&amp;lt;!-- todos los metodos que inicien con get van a ser de solo lectura --&amp;gt;&lt;br /&gt;&amp;lt;tx:method name="get*" read-only="true"/&amp;gt;&lt;br /&gt;&amp;lt;!-- todos los metodos que inicien con guardar van a ejecutar rollback si se lanza alguna error de estos tipos--&amp;gt;&lt;br /&gt;&amp;lt;tx:method name="guardar*" rollback-for="java.sql.SQLException, x.y.MiInfraestructuraException"/&amp;gt;&lt;br /&gt;&amp;lt;!-- cualquier otro metodo usara la configuracion por defecto de una transaccion--&amp;gt;&lt;br /&gt;&amp;lt;tx:method name="*"/&amp;gt;&lt;br /&gt;&amp;lt;/tx:attributes&amp;gt;&lt;br /&gt;&amp;lt;/tx:advice&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Ojo&lt;/b&gt;: si tu bean manejador de transacciones ya se llama "transactionManager", puedes omitir la propiedad transaction-manager de tx:advice.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Es importante mencionar que por definición, Spring realiza rollback si encuentra que fue lanzada una Exception que herede de RuntimeException (osea no checadas) y las que listemos mediante la propiedad &lt;b&gt;rollback-for&lt;/b&gt;. Esta propiedad nos ayuda a identificar las excepciones de negocio propias que deben provocar un rollback en la base de datos.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.- Advisor y Pointcut&lt;br /&gt;&lt;/b&gt;Finalmente vamos a asegurarnos que el comportamiento que acabamos de definir para nuestras transacciones sea ejecutado para cualquier operación definida mediante un &lt;b&gt;aop:pointcut&lt;/b&gt;, para eso usamos un advisor. Agregamos el esquema y el esquema location de aop nuestro tag &lt;beans&gt; del archivo de configuración de contexto de Spring:&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;xmlns:aop="&lt;a href="http://www.springframework.org/schema/aop" target="_blank"&gt;http://www.&lt;wbr&gt;&lt;/wbr&gt;springframework.org/schema/aop&lt;/a&gt;&lt;wbr&gt;&lt;/wbr&gt;"&lt;/li&gt;&lt;li&gt;xsi:schemaLocation="&lt;a href="http://www.springframework.org/schema/aop" target="_blank"&gt;http://&lt;wbr&gt;&lt;/wbr&gt;www.springframework.org/&lt;wbr&gt;&lt;/wbr&gt;schema/aop&lt;/a&gt; &lt;a href="http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" target="_blank"&gt;http://www.springframework.&lt;wbr&gt;&lt;/wbr&gt;org/schema/aop/spring-aop-2.5.&lt;wbr&gt;&lt;/wbr&gt;xsd&lt;/a&gt;"&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;El &lt;b&gt;aop:pointcut &lt;/b&gt;define con una expresión de aspectJ (&lt;b&gt;execution&lt;/b&gt;) que el comportamiento transaccional sea ejecutado, para este caso, en todas las operaciones con un valor de retorno &lt;i&gt;void &lt;/i&gt;y que reciban cualquier numero/tipo de argumentos, de nuestras clases que terminen en &lt;i&gt;Service &lt;/i&gt;y se encuentren en el paquete &lt;i&gt;x.y.service&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Con un &lt;b&gt;aop:advisor &lt;/b&gt;simplemente relacionamos el pointcut con el advice previamente definido.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;aop:config&amp;gt;&lt;br /&gt;&amp;lt;aop:pointcut id="operacionesDeServicios" expression="execution(* x.y.service.*Service.*(..))"/&amp;gt;&lt;br /&gt;&amp;lt;aop:advisor advice-ref="txAdvice" pointcut-ref="operacionesDeServicios"/&amp;gt;&lt;br /&gt;&amp;lt;/aop:config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nota1&lt;/b&gt;:&lt;br /&gt;La sintaxis para el comando AspectJ execution es como sigue. Puedes usar ' &lt;b&gt;*&lt;/b&gt; ' para indicar "todos", o bien '&lt;b&gt;..&lt;/b&gt;' (dos puntos seguidos) para indicar "este paquete o uno más interno", o bien, "más argumentos" si el caso del método:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;execution([&lt;span style="font-size: 78%;"&gt;&lt;i&gt;valorRetornoDelMeto&lt;wbr&gt;&lt;/wbr&gt;do&lt;/i&gt;&lt;/span&gt;] [&lt;span style="font-size: 78%;"&gt;&lt;i&gt;paquete&lt;/i&gt;&lt;/span&gt;].[&lt;i&gt;&lt;span style="font-size: 78%;"&gt;clase&lt;/span&gt;&lt;/i&gt;].[&lt;i&gt;&lt;span style="font-size: 78%;"&gt;nombreMetod&lt;wbr&gt;&lt;/wbr&gt;o&lt;/span&gt;&lt;/i&gt;]([&lt;span style="font-size: 78%;"&gt;&lt;i&gt;listaArgumentos&lt;/i&gt;&lt;/span&gt;]))&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;i&gt;Ejemplo: &lt;/i&gt;Todos los métodos que empiecen con guardar que devuelvan void y reciban por lo menos un long que pertenezcan a las clases que terminen con Dao y sean del paquete x.y.daos o subpaquetes&lt;/div&gt;execution (&lt;i&gt;&lt;span style="font-size: 78%;"&gt;void x.y.daos..*Dao.guardar*(long..&lt;wbr&gt;&lt;/wbr&gt;)&lt;/span&gt;&lt;/i&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Para entender un poco mas sobre las expresiones de aspectJ ve la &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-ataspectj" target="_blank"&gt;referencia de aop-aspectj&lt;/a&gt;.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Nota 2:&lt;/b&gt; Para no confundirnos con los esquemas, la definición del tag &lt;beans&gt; puede quedar como sigue:&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;pre class="brush:xml; highlight:[4,5,7,8]"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:aop="http://www.springframework.org/schema/aop"&lt;br /&gt;xmlns:tx="http://www.springframework.org/schema/tx"&lt;br /&gt;xsi:schemaLocation="&lt;br /&gt;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&lt;br /&gt;http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd&lt;br /&gt;http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"&amp;gt;&lt;br /&gt;&amp;lt;!-- todos los demas beans que vimos--&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Referencias:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop.html" target="_blank"&gt;Programacion orientada a aspectos con Spring&lt;/a&gt; (inglés)&lt;/li&gt;&lt;li&gt;&lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html" target="_blank"&gt;Manejo de Transacciones&lt;/a&gt; (inglés)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.eclipse.org/aspectj/doc/released/progguide/starting.html" target="_blank"&gt;Getting Started with AspectJ&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-3578046874090827460?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/3578046874090827460/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/09/configurar-la-capa-de-servicios-como.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3578046874090827460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3578046874090827460'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/09/configurar-la-capa-de-servicios-como.html' title='Configurar la capa de servicios como transaccionales con spring aop'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-5524897634333081371</id><published>2009-09-09T07:15:00.001-07:00</published><updated>2010-02-04T20:29:10.754-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><category scheme='http://www.blogger.com/atom/ns#' term='annotation'/><title type='text'>Maven-Spring-Aspectos con @Configurable y Weaving</title><content type='html'>Porqué la mayoría de la gente usa Load Time Weaving (LTW)? Esto requiere reemplazar el javaagent/classloader para tu JVM el cual batalla con el ordenamiento de todas las cosas. &lt;br /&gt;Echemos un vistazo usando mejor el Compile Time Weaving (CTW).&lt;br /&gt;Este ejemplo usa Spring 2.5.2, AspectJ 1.5.4, Java 1.5 (Spring 2.5.4 usa una version posterior de weaver (3.0 contra 5.0) - Asumo que AspectJ 1.6.0 pero el aspectj-mave-plugin está también basado alrededor de la versión 1.5.4, así que por ahora trabajemos con esta combinación.&lt;br /&gt;En Spring, podemos simplemente inyectar recursos a beans normales de Spring, incluso vía la configuración del contexto de Spring, o usando el soporte para anotaciones basadas en inyecciones ((@Resource, @Autowired junto con  @Repository, @Service etc). &lt;br /&gt;Sin embargo, beans que son de alcance prototipo (scope="prototype") son más difíciles de manejar. Estas son renovadas (&lt;code&gt;Bean foo = new FooBean();&lt;/code&gt;) incluso por el desarrollador o por frameworks externos o (Hibernate para beans del modelo, contenedores de servlet, etc.).&lt;br /&gt;El sitio &lt;a href="http://www.springframework.org/" target="_blank"&gt;spring framework&lt;/a&gt; provee la anotación @Configurable para esto.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;Cualquier bean que es anotado con @Configurable será inyectado con sus propiedades utilizando aspectos. Entonces necesitamos que las cosas estén preparadas para que este aspecto se ejecute.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lo primero - el contexto de Spring.&lt;/b&gt;&lt;br /&gt;Necesitas los siguiente en el contexto de tu aplicación:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml; highlight:[3,7,8]"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:context="http://www.springframework.org/schema/context"&lt;br /&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans&lt;br /&gt;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&lt;br /&gt;http://www.springframework.org/schema/context&lt;br /&gt;http://www.springframework.org/schema/context/spring-context-2.5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;context:component-scan base-package="tu.paquete.raiz"/&amp;gt;&lt;br /&gt;&amp;lt;context:spring-configured/&amp;gt;&lt;br /&gt;&amp;lt;!-- mas beans  ... --&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;Recuerda agregar el &lt;/i&gt;&lt;i&gt;context namespace a la declaracion de esquemas en tu archivo de contexto.&lt;/i&gt;&lt;br /&gt;&lt;b&gt;Ahora la configuracion de Maven&lt;/b&gt;&lt;br /&gt;Necesitarás usar  aspectj-maven-plugin desde el proyecto codehaus MOJO.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;&amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;lt;artifactId&amp;gt;aspectj-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;lt;complianceLevel&amp;gt;1.5&amp;lt;/complianceLevel&amp;gt;&lt;br /&gt;&amp;lt;aspectLibraries&amp;gt;&lt;br /&gt;&amp;lt;aspectLibrary&amp;gt;&lt;br /&gt;&amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;lt;artifactId&amp;gt;spring-aspects&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;lt;/aspectLibrary&amp;gt;&lt;br /&gt;&amp;lt;/aspectLibraries&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&amp;lt;executions&amp;gt;&lt;br /&gt;&amp;lt;execution&amp;gt;&lt;br /&gt;&amp;lt;goals&amp;gt;&lt;br /&gt;&amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;&lt;br /&gt;&amp;lt;/goals&amp;gt;&lt;br /&gt;&amp;lt;/execution&amp;gt;&lt;br /&gt;&amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Estos jars de la lista de librerias de aspectos deberían contener aspectos pre-compilados (en este caso las de Spring) y estos aspectos serán enlazados en tiempo de compilación contra el tiempo de compilación del código.&lt;br /&gt;Lo que sigue esta traducido del documento original pero ya no existen los enlaces:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;Hay un ejemplo disponible en mercurial&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size: 85%;"&gt;&lt;code&gt;hg clone &lt;a href="https://svn.chrissearle.net/mercurial/examples" target="_blank"&gt;https://svn.chrissearle.net/mercurial/examples&lt;/a&gt;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size: 85%;"&gt;Luego mira en el  aspectj/directorio ctw.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;Si no tienes mercurial entonces puedes navegar en : &lt;code&gt;&lt;a href="https://svn.chrissearle.net/mercurial/examples/file/tip/aspectj/ctw/" target="_blank"&gt;https://svn.chrissearle.net/mercurial/examples/file/tip/aspectj/ctw/&lt;/a&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;Traducido de: &lt;a href="http://www.chrissearle.org/blog/technical/spring_aspects_configurable_and_compile_time_weaving_using_maven" target="_blank"&gt;chrissearle.org&lt;/a&gt; jueves 22 de Mayo 2008 por chris          &lt;br /&gt;Más referencias:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.aspectprogrammer.org/blogs/adrian/2006/02/a_practical_gui_2.html" target="_blank"&gt;aspectprogrammer.org/blogs/adrian&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ibm.com/developerworks/java/library/j-aopwork13.html" target="_blank"&gt;http://www.ibm.com/developerworks/java/library/j-aopwork13.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config" target="_blank"&gt;Configuracion de Spring basada en anotaciones&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/Configurable.html"&gt;http://static.springsource.org/spring/docs/2.5.x/api/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-5524897634333081371?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/5524897634333081371/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/09/maven-spring-aspectos-con-configurable.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5524897634333081371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/5524897634333081371'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/09/maven-spring-aspectos-con-configurable.html' title='Maven-Spring-Aspectos con @Configurable y Weaving'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-7150245958978724848</id><published>2009-08-14T15:20:00.000-07:00</published><updated>2010-02-04T20:35:37.837-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='red'/><title type='text'>Levantando una sencilla VPN con OpenVPN parte 2</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Configuración de la VPN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Una vez que ya se tiene instalado OpenVPN en las máquinas servidor y clientes que serán miembros de la red virtual, hay que configurar correctamente el software, tanto en servicios como en generación de llaves de seguridad para poder tener la VPN funcionando.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Diseño de la red&lt;/span&gt;&lt;br /&gt;La primer consideración importante a tener en cuenta es el diseño de la red virtual: qué máquinas formarán parte de la misma, si se formarán subredes dentro de la red virtual, cuestiones de ruteo y redireccionamiento, etc. Además se debe determinar el conjunto de direcciones IP que pertenecerán a las máquinas de la red.&lt;br /&gt;&lt;br /&gt;En el &lt;a href="http://www.ietf.org/rfc/rfc1918.txt?number=1918"&gt;RFC 1918&lt;/a&gt;, se establece que los rangos siguientes son exclusivos para redes privadas, es decir que ningún sitio en internet, que cualquiera podría ver, debe de tener asignada ninguna dirección de estos rangos, por lo que las múltiples redes privadas que puedan existir, virtuales o no, pueden hacer uso de estas direcciones IP para sus propósitos particulares.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt; De hecho, cualquiera que tenga una computadora dentro de una red privada (incluso en el hogar), podrá observar que la dirección IP que por lo común se le asigna cae en estos rangos:&lt;br /&gt;&lt;br /&gt;Dir. inicial--------Dir. final----------CIDR&lt;br /&gt;..10.0.0.0......10.255.255.255.....10.0.0.0/8&lt;br /&gt;.172.16.0.0....172.31.255.255.....172.16.0.0/12&lt;br /&gt;.192.168.0.0..192.168.255.255...192.168.0.0/16&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;La otra consideración importante a tomar en cuenta al momento de elegir las direcciones IP que se les asignará a las máquinas que pertenezcan a la red virtual viene del hecho de asegurar que para ninguna de las máquinas se producirán choques o conflictos, debido a que la dirección IP que se le asigne a cierta máquina, coincida con la dirección IP de alguna otra máquina dentro de alguna otra red a la que pertenezca o que la subred a la que pertenezca genere este mismo conflicto. Es decir, y por ejemplo:&lt;br /&gt;&lt;br /&gt;supongamos que una máquina (que llamaremos A) que pertenecerá a la VPN quedará con dirección IP asignada de 192.168.1.10 (y otras máquinas de la VPN podrían quedar con IPs similares: B tendría IP 192.168.1.70, C tendría IP 192.168.1.43, etc.). Sin embargo, el problema vendría si A pertenece a su vez a una LAN en donde el rango de direcciones válidas queda dentro de la subred 192.168.1/24 (es decir, de 192.168.1.0 a 192.168.1.255). ¿Qué provocará esto? Por un lado, podría provocar que la dirección 192.168.1.10 ya estuviera asignada a alguna otra máquina de la LAN a la que pertenece nuestra desdichada máquina A. Pero peor aún, provocará que el sistema de ruteo y redireccionamiento de la LAN piense que todo el tráfico generado por y para 192.168.1.10 deberá quedarse dentro de la LAN misma, y no que pertenezca a una red diferente.&lt;br /&gt;&lt;br /&gt;¿Qué hacer en estos casos? Bueno, la mejor solución es planear por adelantado. ¿Qué rangos posibles de subred van a  tener las máquinas que pertenecerán a la VPN? Sabiendo esto, entonces habrá que tomar la decisión de diseño, de que la dirección de subred de toda la VPN quede en un rango que no ocasione ningún conflicto para nadie.&lt;br /&gt;&lt;br /&gt;De acuerdo al ejemplo anterior, si se eligiera que la VPN quedara con direcciones dentro de la subred 192.168.20/24, con esto el problema para nuestra máquina conflictiva se vería resuelto: ahora A tendría dos direcciones IP: una dentro de la subred 192.168.20/24 (la de la VPN) y otra dentro de la subred 192.168.1/24 (la de la LAN a la que pertenece).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Servicios y puertos&lt;/span&gt;&lt;br /&gt;El siguiente punto a considerar es que OpenVPN debe estar ejecutándose en la máquina que pertenecerá a la red (obviamente, por supuesto). La mejor opción es que se ejecute como un servicio que se levante por sí solo cada vez que se reinicie la máquina, de esta forma nos evitamos el tener que levantarlo nosotros mismos cada vez que recordemos que debemos pertenecer a la red virtual (o que alguien nos lo recuerde).&lt;br /&gt;&lt;br /&gt;Además, al tratarse del servidor hay que definir el puerto sobre el que se conectarán las demás máquinas para establecer la VPN. Por lo general, ya que es la opción por defecto, se utiliza el puerto UDP 1194. Sin embargo, esto no es una regla, sino una recomendación. Se puede elegir otro número de puerto (desocupado por supuesto), y si se desea incluso, también otro protocolo de conexión, es decir en lugar de UDP se puede elegir TCP. (¡y no hay que olvidar abrir dicho puerto en el firewall del servidor una vez que se tenga todo listo para comenzar!)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Generación de llaves&lt;/span&gt;&lt;br /&gt;Puesto que OpenVPN genera una VPN segura, se necesita alguna manera de garantizar dicha seguridad. Hay que tomar en cuenta que la información que se  transmita entre las máquinas de la red virtual va a viajar através de internet y de máquinas desconocidas en lugares que podrían resultar muy variados. Esto conlleva un riesgo de seguridad: cualquiera con tiempo, ganas y habilidad podría interceptar la comunicación entre dos máquinas de la red que, de otra manera, se supone deberían ser datos privados, como en una LAN cualquiera.&lt;br /&gt;&lt;br /&gt;Para garantizar la seguridad de la comunicación entre las máquinas de la red virtual se utiliza &lt;a href="http://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"&gt;encriptación de llave pública&lt;/a&gt;, un método de encriptación de la información que, además de resultar muy popular hoy en día, resulta de los más seguros también (no hay que olvidar que, según la sabia filosofía del código abierto y el software libre, un protocolo entre más abierto y conocido sea por todos, más seguro es). En palabras breves, la encriptación de llave pública consiste en lo siguiente:&lt;br /&gt;&lt;br /&gt;Supongamos que dos máquinas se quieren comunicar seguramente. En un lado de la comunicación se encripta la información a enviar utilizando algo llamado su llave privada, y de esa manera la información viaja por internet. Algo encriptado con llave privada es dificilísimo, sino es que imposible, de desencriptar en un tiempo que puede llegar a las décadas o más (incluso para las máquinas más potentes). Esto genera un pequeño problema: ¿cómo desencriptar la información rápidamente en el lado receptor? Una solución es utilizar la misma llave privada, pero esto ocasiona el problema de que ambas partes deben conocer dicha llave privada, y para que ambas conozcan la llave privada, entonces de alguna manera un lado debe hacer del conocimiento del otro lado dicha llave privada. Y como sea que lo veamos, esta transmisión de la llave privada puede ser igualmente insegura.&lt;br /&gt;&lt;br /&gt;De esta forma, los algoritmos de llave pública implican que, en lugar de encriptar la información del transmisor con su llave privada, se encripte con la llave pública, una llave que puede ser conocida por quien sea, podría incluso transmitirse por TV o publicarse en un blog como estos, pero la forma de desencriptar la información, sólo se logra si el receptor cuenta con una llave privada generada de &lt;span style="font-style: italic;"&gt;manera adecuada&lt;/span&gt;. Esta &lt;span style="font-style: italic;"&gt;manera adecuada&lt;/span&gt; de obtener la llave privada correcta es a través de un certificado de seguridad. Y bueno, aún contando con la llave pública, las máquinas más potentes todavía tardarían décadas o más que eso en desencriptar la información, pues no cuentan con las llaves privadas adecuadas.&lt;br /&gt;&lt;br /&gt;La manera de implementar todo esto en OpenVPN es utilizando &lt;a href="http://es.wikipedia.org/wiki/Transport_Layer_Security"&gt;SSL&lt;/a&gt;. Obviamente, se pueden conseguir (a un precio no tan accesible) los certificados de seguridad generados por compañías especializadas, pero si no se tienen los medios, en una instalación estándar de OpenVPN, se incluyen también algunos scripts hechos precisamente para permitir la generación de llaves privadas y certificados de seguridad para el servidor y las máquinas cliente que formarán parte de la red virtual, a través de SSL.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn.html"&gt;Ver la parte 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/09/levantando-una-sencilla-vpn-con-openvpn.html"&gt;Ver la parte 3&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-7150245958978724848?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/7150245958978724848/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn_14.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7150245958978724848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7150245958978724848'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn_14.html' title='Levantando una sencilla VPN con OpenVPN parte 2'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-6940447472554447384</id><published>2009-08-06T16:04:00.000-07:00</published><updated>2010-02-04T20:36:00.301-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><category scheme='http://www.blogger.com/atom/ns#' term='red'/><title type='text'>Levantando una sencilla VPN con OpenVPN</title><content type='html'>&lt;span style="font-weight: bold;"&gt;¿Qué es una VPN?&lt;/span&gt;&lt;br /&gt;VPN significa Virtual Private Network. Una VPN es una red virtual, que se configura para que todas las máquinas pertenecientes a la misma puedan verse como si se encontraran dentro de una misma LAN (Local Area Network), a pesar de poder encontrarse separadas por grandes distancias (y para el contexto del lenguaje de redes, fuera de una misma LAN).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;¿Para qué sirve una VPN?&lt;/span&gt;&lt;br /&gt;Bueno, pues las aplicaciones son muchas, pero en términos sencillos, se puede aprovechar para:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Compartir archivos&lt;/li&gt;&lt;li&gt;Establecer conexiones seguras&lt;/li&gt;&lt;li&gt;Disponer de servicios entre las máquinas que pertenecen a la VPN, como si estuvieran en una LAN&lt;/li&gt;&lt;li&gt;Juegos&lt;/li&gt;&lt;li&gt;etc. etc.&lt;a name='more'&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;¿Qué necesito?&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Una máquina que funcione como 'servidor' de la VPN (puedes consultar mi tutorial sobre &lt;a href="http://micro-howto.blogspot.com/2009/03/servidor-linux-desde-tu-hogar-en-tres.html"&gt;cómo levantar un servidor desde Linux en 3 pasos&lt;/a&gt;) [NOTA: no es necesario que el servidor sea Linux]&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Máquinas que pertenecerán a la VPN, los llamados 'clientes'&lt;/li&gt;&lt;li&gt;Software para levantar la VPN. En este caso utilizaremos &lt;a href="http://www.openvpn.net/"&gt;openVPN&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Obviamente, conexiones a internet. Solamente el servidor necesita ser 'visto' por las demás máquinas, mientras que para los clientes, basta con que puedan acceder a internet, aunque no sean 'vistos' por los demás (pues pueden estar detrás de un router que les asigne una IP vía NAT por ejemplo)&lt;/li&gt;&lt;li&gt;Configurar openVPN tanto en el servidor como en los clientes&lt;/li&gt;&lt;/ol&gt;Para los puntos 1, 2 y 4, voy a asumir que ya tienes lista esa parte, y me enfocaré únicamente en los puntos 3 y 5.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;OpenVPN&lt;/span&gt;&lt;br /&gt;OpenVPN es una plataforma que permite configurar redes a nivel amplio, sin necesidad de invertir en las instalaciones que una WAN (Wide Area Network) utilizaría. Al contrario, aprovechando la infraestructura que ya existe de Internet (la red de redes), se configura de manera segura y estable una red de 'area amplia'.&lt;br /&gt;&lt;br /&gt;OpenVPN puede obtenerse en su sitio oficial, &lt;a href="http://www.openvpn.net/"&gt;openvpn.net&lt;/a&gt;. Existen versiones para distintos sistemas operativos, entre ellos Linux y Windows. Hablando de Linux, cabe mencionar que numerosas distribuciones lo incluyen  también dentro de sus repositorios, por lo que puede instalarse también a través de las utilidades de la propia distribución.&lt;br /&gt;&lt;br /&gt;En cuanto a Linux, si se decide instalar OpenVPN sin usar las utilidades de instalacion de la distribución, se puede instalar utilizando RPM (para distribuciones que lo soporten, como RedHat, Fedora, Suse, etc.), o por otro lado se puede instalar compilando el código fuente. Igualmente, para sistemas estilo Debian, existen repositorios que permiten instalar OpenVPN vía apt. En Windows, un instalador se encarga del proceso.&lt;br /&gt;&lt;br /&gt;Cabe mencionar que, para que una máquina pueda funcionar como servidor de una red con OpenVPN, debe abrirse el firewall. Por defecto se utiliza el puerto UDP 1194, pero también se puede configurar algún otro (otro número o incluso TCP en lugar de UDP).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn_14.html"&gt;Ver la parte 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/09/levantando-una-sencilla-vpn-con-openvpn.html"&gt;Ver la parte 3&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-6940447472554447384?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/6940447472554447384/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6940447472554447384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/6940447472554447384'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/08/levantando-una-sencilla-vpn-con-openvpn.html' title='Levantando una sencilla VPN con OpenVPN'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-8431822961595782496</id><published>2009-08-03T10:09:00.000-07:00</published><updated>2009-08-03T10:26:59.044-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mapeo'/><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>ORM : Mapeo Objeto - Relacional</title><content type='html'>Es una técnica de programación muy utilizada en paradigmas orientados a objetos, que te permite 'mapear' (es decir, emparejar un par de entidades de tu programa): por un lado una base de datos relacional y por otro lado objetos.&lt;br /&gt;&lt;br /&gt;Por poner un ejemplo sencillo, una agenda con personas / direcciones y teléfonos.&lt;br /&gt;En la base de datos relacional, pueden haber tablas para:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Las personas, con datos como su nombre completo, edad, género&lt;/li&gt;&lt;li&gt;Los teléfonos, con el dato del número telefónico y relacionados con las personas a través de una llave foránea (si la relación es 1-N) o una tabla de rompimiento (si la relación es N-M)&lt;/li&gt;&lt;li&gt;Las direcciones, con datos para calle, número exterior e interior, colonia, etc. y relacionados con las personas, también a través de una llave foránea.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Por otro lado, en tu programa podrías tener los siguientes objetos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Un objeto persona, con una propiedad cadena para el nombre, una propiedad entera para la edad, una propiedad de una enumeración para el género.&lt;/li&gt;&lt;li&gt;Un objeto telefono, con una propiedad cadena para el número telefónico.&lt;/li&gt;&lt;li&gt;Un objeto direccion, con una propiedad cadena para cada campo de la misma tabla&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Pero además, en tu objeto persona podrías tener lo siguiente:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Una propiedad lista de objetos telefono&lt;/li&gt;&lt;li&gt;Una propiedad de objeto direccion&lt;/li&gt;&lt;/ol&gt;Y de esta manera, una persona tiene uno o mas números telefónicos, y una dirección asociada.&lt;br /&gt;&lt;br /&gt;Ahora bien, el ORM, además de permitirte modelar tu información de manera que utilices objetos para representar las relaciones de la base de datos, también puede permitirte la llamada &lt;span style="font-weight: bold;"&gt;persistencia&lt;/span&gt;. Esta propiedad se refiere al hecho de que, a través del motor del ORM y gracias al mapeo establecido (por ejemplo en un archivo de configuración XML) entre los objetos y las tablas de la base de datos, se consigue que los datos manipulados en los objetos se reflejen en la base de datos, y que cualquier cambio en los objetos mismos dentro del programa permita que el mapeo, además de ser declarativo (que establece el mapeo en sí entre objeto y relación), sea también del contenido.&lt;br /&gt;&lt;br /&gt;En los lenguajes orientados a objetos existen muchos motores o frameworks que permiten implementar ORM en un sistema. Sin embargo, a veces es necesario o más sencillo implementar uno propio, con o sin persistencia.&lt;br /&gt;&lt;br /&gt;En cuanto a los frameworks existentes, y que pueden usarse para desarrollar sistemas con un ORM, se encuentran por ejemplo:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Hibernate, para el lenguaje Java&lt;/li&gt;&lt;li&gt;Propel, para el lenguaje PHP&lt;/li&gt;&lt;li&gt;SQLAlchemy, para el lenguaje Python&lt;/li&gt;&lt;li&gt;Doctrine, también para PHP&lt;/li&gt;&lt;li&gt;etc...&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-8431822961595782496?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/8431822961595782496/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/08/orm-mapeo-objeto-relacional.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8431822961595782496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8431822961595782496'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/08/orm-mapeo-objeto-relacional.html' title='ORM : Mapeo Objeto - Relacional'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-7497289746561089845</id><published>2009-08-03T08:13:00.001-07:00</published><updated>2009-08-03T08:17:22.619-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones'/><category scheme='http://www.blogger.com/atom/ns#' term='designing'/><title type='text'>Patrones de Diseño</title><content type='html'>Una lista de patrones de diseño&lt;br /&gt;&lt;br /&gt; &lt;table border="1" cellpadding="2" cellspacing="2" width="90%"&gt;    &lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Patrón&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Tipo&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Otros nombres&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Abstract Factory [fabrica abstracta]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;de creación&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Adapter [adaptador]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Bridge [puente]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Builder [constructor]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;de creación&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Chain of Responsability [cadena de responsabilidad]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;&lt;a href="http://micro-howto.blogspot.com/2009/03/patron-de-diseno-command.html" target="_blank"&gt;Command&lt;/a&gt; [comando]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Action, Transaction&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Composite [composición]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Decorator [decorador]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Facade [fachada]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Factory Method [método de fábrica]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;de creación&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Flyweight [ligero]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Interpreter [intérprete]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Iterator [iterador]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Mediator [mediador]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Memento [recuerdo]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Prototype [prototipo]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;de creación&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Proxy&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Estructural&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Observer [observador]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Singleton [uno solo para siempre]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;de creación&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;State [estado]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Strategy [estrategia]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Template Method [método plantilla]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Visitor [visitante]&lt;br /&gt;      &lt;/td&gt;       &lt;td valign="top"&gt;Comportamiento&lt;/td&gt;       &lt;td valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt; &lt;/table&gt; &lt;br /&gt; Fuentes:&lt;br /&gt; Una referencia rápida &lt;a href="http://www.mcdonaldland.info/2007/11/28/40/" target="_blank"&gt;aquí&lt;/a&gt;, donde pueden descargar un PDF y sino, escribanme a &lt;a href="mailto:wdonet@gmail.com" target="_blank"&gt;wdonet@gmail.com&lt;/a&gt;, yo lo he de tener.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-7497289746561089845?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/7497289746561089845/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/08/patrones-de-diseno.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7497289746561089845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7497289746561089845'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/08/patrones-de-diseno.html' title='Patrones de Diseño'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3592731622597581461</id><published>2009-07-23T11:16:00.001-07:00</published><updated>2010-02-04T20:41:39.694-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IDE'/><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='jackbe'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Intro a EAF (Enterprise AJAX Framework) de jackbe</title><content type='html'>Se trata de la parte AJAX de Jackbe y para trabajar con él podemos usar un proyecto en Eclipse con el &lt;a href="http://www.jackbe.com/enterprise-mashup/videos/jackbes-eaf-plugin-eclipse" target="_blank"&gt;plugin del EAF&lt;/a&gt;. Pero es necesario que Eclipse cuente con la funcionalidad WTP para poder trabajar.  El proyecto en Eclipse se conforma por carpetas como:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;WEB-INF &lt;/span&gt;- aquí van los archivos web&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;WEB-INF/jbml&lt;/span&gt; - son los archivos fuente de las pantallas web o con lo que se llama'&lt;b&gt;j&lt;/b&gt;ack&lt;b&gt;b&lt;/b&gt;e &lt;b&gt;m&lt;/b&gt;arkup     &lt;b&gt;l&lt;/b&gt;anguage'.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;WEB-INF/jsp&lt;/span&gt; - son creados de forma automática al crear pantallas jbml y básicamente, invocan al constructor de nuestra pantalla jbml&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;gc.jsp&lt;/span&gt; - es un archivo que almacena la configuración global para traerse al núcleo los archivos del EAF. Es de notar que en cada archivo jsp creado de forma automática, se incluye un código como sigue: &lt;span style="font-family: Cordia New;"&gt;&amp;lt;jsp:include page="./jackbe/jsp/gc.jsp"/&amp;gt;&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;jackbe&lt;/span&gt; - almacena archivos del núcleo&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;fb&lt;/span&gt; - significa '&lt;i&gt;form behavior&lt;/i&gt;', que almacenan el comportamiento de las pantallas a través de programación javascript, así que se trata de archivos '.js'.&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;jf&lt;/span&gt; - aquí se guardan los '&lt;i&gt;jackbe forms&lt;/i&gt;' o los archivos compilados de jbml, también son archivos '.js'.&lt;/li&gt;&lt;li&gt;&lt;span style="color: #cc6600;"&gt;rb&lt;/span&gt; - resources boundle&lt;a name='more'&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Para mayor apoyo sobre el uso del EAF, se puede utilizar la ayuda de Eclipse (y sino, la &lt;a href="http://www.jackbe.com/enterprise-mashup/knowledge-base/documentation" target="_blank"&gt;ayuda en línea&lt;/a&gt;), ahí vienen descritos muchos comandos que se pueden usar en un &lt;i&gt;form behavior&lt;/i&gt; (fb), pero describo algunos:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;LJF("pantalla")&lt;/b&gt; - permite cargar una pantalla, como parámetro se envía el nombre del archivo .js sin la extensión y después se llama a su constructor de la misma forma, en este ejemplo sería: pantalla();&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Otra lista de comandos&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SE &lt;/span&gt;- Source Element&lt;/li&gt;&lt;li&gt; &lt;span style="font-weight: bold;"&gt;AE &lt;/span&gt;- Attach Element&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;PX &lt;/span&gt;- Prefix&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;CN &lt;/span&gt;- Class Name&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SAO &lt;/span&gt;- Select Add Option&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;GOT &lt;/span&gt;- Got Option Text&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SI &lt;/span&gt;- Select Index - selecciona un índice del arreglo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;PM - &lt;/span&gt;Te ayuda a redireccionarte a una url.&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;WSM &lt;/span&gt;- Para abrir otra pantalla&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;GI &lt;/span&gt;- Get element by Id - Devuelve la referencia por el id&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;WO &lt;/span&gt;- Para acceer a objetos (widget) de la ventana padre&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Puedes ayudarte del plugin Firebug si usas Firefox o de la funcionalidad 'inspect element' de chrome para navegar por los objetos y elementos html.  En firebug, puedes usar la consola para ejecutar comandos como:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;console.log(x) - para sacar una traza del valor de x&lt;/li&gt;&lt;li&gt;eval(x) - sacar el resultado de interpretar x&lt;/li&gt;&lt;li&gt;JKB.widget.manager.getWidget("id") - devuelve un objeto&lt;/li&gt;&lt;li&gt;for (var x in objeto) { console.log(x) } - para mostrar los elementos de un objeto&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Algunas notas aclaratorias:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Diferencias entre &amp;lt;div&amp;gt; y &amp;lt;span&amp;gt; , si no se indican posiciones, div es relativo vertical, span es relativo horizontal.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;En estilos CSS, se usa '.estilo1'  para cuando se asigna de la forma: class="", ej. &amp;lt;div class="estilo1"/&amp;gt;; y '#estilo2' se usa cuando se asigna como id="", ej. &amp;lt;div id="estilo2"/&amp;gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://es.wikipedia.org/wiki/WSDL" target="_blank"&gt;WSDL &lt;/a&gt; - Describe los servicios web.&lt;/li&gt;&lt;li&gt;&lt;a href="http://es.wikipedia.org/wiki/SOAP" target="_blank"&gt;SOAP&lt;/a&gt; - Protocolo que usan los servicios web, nada que ver con &lt;a href="http://es.wikipedia.org/wiki/SOA" target="_blank"&gt;SOA&lt;/a&gt; .&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.webopedia.com/TERM/W/Web_clipping.html" target="_blank"&gt;Web clipping&lt;/a&gt; - Permite extraer la información no estructurada y transformarla en datos estructurados&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Otras referencias:&lt;br /&gt;&lt;a href="http://www.jackbe.com/resources/jackopedia.php" target="_blank"&gt;Conceptos varios&lt;/a&gt; | &lt;a href="http://www.jackbe.com/products/server.php" target="_blank"&gt;Servidor Presto&lt;/a&gt; | &lt;a href="http://www.jackbe.com/products/connectors.php" target="_blank"&gt;Conectores Mashup&lt;/a&gt; | &lt;a href="http://www.jackbe.com/resources/demos.php" target="_blank"&gt;Demostraciones&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jackbe.com/downloads/JackBe_White_Paper___Ajax_Best_Practices.pdf" target="_blank"&gt;Mejores Practicas con AJAX&lt;/a&gt; (PDF en inglés)&lt;br /&gt;&lt;a href="http://www.jackbe.com/downloads/JackBe%20White%20Paper%20-%20Business%20Value%20of%20Ajax.pdf" target="_blank"&gt;The Business Value of AJAX&lt;/a&gt; (PDF)&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-3592731622597581461?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/3592731622597581461/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/07/intro-eaf-enterprise-ajax-framework-de.html#comment-form' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3592731622597581461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/3592731622597581461'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/07/intro-eaf-enterprise-ajax-framework-de.html' title='Intro a EAF (Enterprise AJAX Framework) de jackbe'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-7834537253601326737</id><published>2009-07-21T08:22:00.001-07:00</published><updated>2009-07-21T08:38:16.337-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xtreme programming'/><category scheme='http://www.blogger.com/atom/ns#' term='metodología'/><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>Metodología de desarrollo XP</title><content type='html'>&lt;u&gt;Ciclo de la metodología&lt;/u&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Planificación&lt;/b&gt;. Escuchar las necesidades del Cliente, hacerlo parte del equipo, pero explicar lo que es fácil de obtener y lo que no&lt;/li&gt;&lt;li&gt;&lt;b&gt;Diseño&lt;/b&gt;. Es importante usar patrones de diseño.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Desarrollo&lt;/b&gt;. Hacer que el propio código comunique lo que está haciendo.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Pruebas&lt;/b&gt;. Realizar pruebas unitarias, puedes usar frameworks muy conocidos como JUnit y DBUnit.&lt;/li&gt;&lt;/ol&gt;&lt;u&gt;Valores que promueve&lt;/u&gt; : | &lt;i&gt;Comunicación &lt;/i&gt;| &lt;i&gt;Coraje &lt;/i&gt;| &lt;i&gt;Simplicidad &lt;/i&gt;| &lt;i&gt;Retroalimentación &lt;/i&gt;|&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ventajas&lt;/u&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Es un diseño simple&lt;/li&gt;&lt;li&gt;Obliga a que funcionen todas las pruebas unitarias, todo el tiempo.&lt;/li&gt;&lt;li&gt;Muchos comentan que no tiene, pero yo creo que solo se reduce la lógica duplicada.&lt;/li&gt; &lt;li&gt;Suele tener menor número de clases y métodos.  Aunque esto depende de la modularidad de la aplicación y que el desarrollador realice un diseño claro, simple y use patrones.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;u&gt;Desventajas&lt;/u&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; La documentación suele ser pobre.&lt;/li&gt;&lt;/ul&gt;&lt;u&gt;Buenas prácticas&lt;/u&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Realizar un &lt;b&gt;diseño simple&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Pequeñas versiones&lt;/b&gt;. Hacer entregas constantes para que el Cliente perciba el avance y retroalimente las necesidades de negocio que afinen la funcionalidad efectiva de la aplicación.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Pruebas&lt;/b&gt;. Cada funcionalidad en la aplicacion (front, back, web-services, DAOs, VOs, Utilerías, etc.) debe ser probada.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Recodificar&lt;/b&gt;. Siempre que veamos código al que se puede aplicar un &lt;i&gt;refactoring&lt;/i&gt;, aunque no sea nuestro, es conveniente avisar al equipo y planear su reestructuración a medida que la propia aplicación lo pida.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Programar en parejas&lt;/b&gt;. Un solo teclado, un solo ratón, una persona codifica, ambos piensan, se logran ideas más estratégicas (es importante que ambos estén abiertos a escuchar las ideas del otro con el fin de mejorar las propuestas planteadas y por consiguiente la aplicación).&lt;/li&gt; &lt;li&gt;&lt;b&gt;Integrar una vez al día&lt;/b&gt;. Obviamente antes de integrar implica ejecutar las pruebas para validar que todo siga funcionando como lo esperan las pruebas unitarias.&lt;/li&gt;&lt;li&gt;&lt;b&gt;40 hrs por semana máximo&lt;/b&gt; permiten estar fresco, descansar 2 días para pensar en nuevas ideas y aplicarlas al inico de semana. Estaría bien &lt;b&gt;disponer de un tiempo a medio día &lt;/b&gt;para descansar (siesta, break, tomar un pequeño postre) o despejar la mente realizando otras actividades (juegos de mesa, videojuegos, salas de lectura, reuniones de convivencia). &lt;i&gt;Es parte del modelo laboral japonés y les funciona&lt;/i&gt;.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Establecer estándares de codificación&lt;/b&gt;. Usar un checkstyle y practicar revisiones en parejas del código de otros resulta bastante bueno para la aplicación pues ayuda a detectar posibles errores de estilo e incluso de lógica, de forma que cualquier nuevo integrante que llegue al equipo se familiarice más rápido con el código.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-7834537253601326737?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/7834537253601326737/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/07/metodologia-de-desarrollo-xp.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7834537253601326737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/7834537253601326737'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/07/metodologia-de-desarrollo-xp.html' title='Metodología de desarrollo XP'/><author><name>«º))))»&amp;lt;.·´¯`·.·.·´¯`·.·• wdo»</name><uri>http://www.blogger.com/profile/05477259225859568605</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_813bkGL_8xA/S6EfmsLi4II/AAAAAAAAA8k/ICd8fjwEL5U/S220/me-os.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-935584277036034532</id><published>2009-07-14T13:03:00.000-07:00</published><updated>2010-02-04T20:40:21.142-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><title type='text'>Servidor Linux desde tu hogar Intro 2</title><content type='html'>Antes de entrar en tema, demos un breve recorrido por los tres pasos para levantar un servidor en tu hogar, para averiguar por qué necesitamos llevarlos a cabo:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Publicar mi dirección IP&lt;/span&gt;. Tal vez has notado alguna vez al momento de estar conectado en el hogar, que la dirección IP que tiene asignada tu máquina por parte del ISP es una dirección local, de la LAN creada en tu hogar con el ruteador al que te conectas a Internet. Mientras tanto la dirección IP 'real' que el mundo conoce de la LAN es otra. Puedes visitar algún sitio como &lt;a href="http://whatismyipaddress.com/" target="'_blank'"&gt;este&lt;/a&gt;, y podrás notar que aunque tu sistema informa que su dirección IP es una (a través de &lt;span style="font-family: times new roman; font-style: italic;"&gt;ifconfig &lt;/span&gt;por ejemplo), 'desde afuera', la dirección IP es otra, pues se trata de la dirección con la que en realidad el ruteador de tu LAN se comunica al mundo exterior. El truco en este paso consistirá entonces en &lt;span style="font-weight: bold;"&gt;hacer que la dirección IP del ruteador con el que te conectas, quede de alguna manera asignada (o más bien ligada) también a la máquina que funcionará como tu servidor&lt;/span&gt;.&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Configurar y levantar el servidor&lt;/span&gt;. Después hay que configurar la máquina que será el servidor. Por un lado se deben de &lt;span style="font-weight: bold;"&gt;instalar y configurar los servicios&lt;/span&gt; que se desean ofrecer: HTTP (web), FTP (servidor de archivos), SSH (conexión remota), SVN (versionador), etc. Por otro lado, también hay que configurar el servidor para que los puertos con los que se comunicará el servidor con el mundo exterior queden abiertos. Esto implica que esos puertos del servidor, y no otros, sean visibles en el exterior, lo que significa &lt;span style="font-weight: bold;"&gt;configurar la seguridad del servidor&lt;/span&gt; a través de un firewall.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Recordar mi dirección IP&lt;/span&gt;. Aunque con los dos primeros pasos ya se puede tener un servidor conectado a Internet, hay que tomar en cuenta dos factores: que un número de dirección IP es difícil de recordar (ya sea por ti, o por las personas a las que les informes de tu servidor, o a cualquier persona que, navegando por internet, se tope con el mismo y utilice los servicios que ofrezca), y que posiblemente tengas contratado un servicio de internet con asignación dinámica de IP (lo cual significa que en algún momento (como cuando se va la energía eléctrica) tu servidor cambiará de dirección IP, y esto vuelve complicado el proceso de conocer a qué dirección conectarse en realidad: si al dejar tu casa olvidas consultar cual es la dirección IP actual de tu servidor, acceder a él será en la práctica algo imposible, a pesar de que se encuentre visible al exterior en todo momento). Hay varias maneras de resolver esto. Una, si cuentas con los medios económicos adecuados, contrata un servicio de internet que te permita además tener una dirección IP fija. Pero el caso es que no siempre se puede tener esto, además aún queda el problema de que el número de dirección IP es difícil de recordar. Presentaré aquí una opción que puede resultar conveniente y barata a través de un &lt;span style="font-weight: bold;"&gt;servicio de DNS dinámico.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;Por último, antes de describir cómo llevar a cabo estos 3 pasos, vale la pena mencionar unos cuantos programas de utilidad que conviene tengas instalados y conozcas su uso. Casi todos se pueden ejecutar desde una consola cualquiera en Linux, aunque algunos requieren permisos de superusuario (que dicho está de más, es el modo con el que se necesitan instalar y configurar los servicios que el servidor ofrecerá). Para los que ya los conocen, pueden saltarse libremente esta sección. Nota: estos programas también tienen sus equivalentes para otras plataformas, si vas a utilizarlos para monitorear tu servidor desde el exterior, investiga dichas equivalencias para el sistema desde el cual te vayas a conectar a tu servidor.&lt;br /&gt;&lt;br /&gt;-&lt;span style="font-family: times new roman; font-style: italic;"&gt;ifconfig&lt;/span&gt;, informa de la dirección IP y otra información útil de la máquina actual, dando información para cada interfaz de conexión de red que tenga el sistema. Por ejemplo, se da información para la interfaz Ethernet, la Wireless, etc. Su uso más sencillo es:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;ifconfig&lt;/blockquote&gt;-&lt;span style="font-family: times new roman; font-style: italic;"&gt;ping&lt;/span&gt;, permite 'llamar' a cierta dirección IP o servidor para saber si está respondiendo. Su uso más sencillo es:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;ping dirIP&lt;/blockquote&gt;o&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;ping nombreSevidor&lt;/blockquote&gt;Cuando se tenga suficiente, se puede presionar &lt;span style="font-family: courier new;"&gt;Ctrl-C&lt;/span&gt; y &lt;span style="font-family: times new roman; font-style: italic;"&gt;ping &lt;/span&gt;informa de la estadística que se haya obtenido al comunicarse con cierto servidor.&lt;br /&gt;&lt;br /&gt;-&lt;span style="font-family: times new roman; font-style: italic;"&gt;traceroute&lt;/span&gt;, permite conocer la ruta que siguen los paquetes de información para llegar desde la localidad en que es invocado hasta el servidor solicitado. Su uso más común es:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;traceroute dirIP&lt;/blockquote&gt;o&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;traceroute nombreServidor&lt;/blockquote&gt;El resultado es una serie de ruteadores por los que la información viaja desde la localidad en que fue invocado hasta la máquina especificada.&lt;br /&gt;&lt;br /&gt;-&lt;span style="font-family: times new roman; font-style: italic;"&gt;nmap&lt;/span&gt;, que puede conseguirse en &lt;a href="http://insecure.org/" target="'_blank'"&gt;este sitio&lt;/a&gt;, permite conocer los detalles de algún servidor. Su uso más sencillo es:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;nmap dirIP&lt;/blockquote&gt;o&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;nmap nombreServidor&lt;/blockquote&gt;El resultado es una lista de los nombres y números de puertos abiertos en el sistema indicado. También son de uso común los parámetros &lt;span style="font-family: courier new;"&gt;-O&lt;/span&gt; y &lt;span style="font-family: courier new;"&gt;-A&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;-&lt;span style="font-family: times new roman; font-style: italic;"&gt;tcpdump&lt;/span&gt;, te muestra en tiempo real el contenido de los paquetes de información en una interfaz de red. Su uso más sencillo es:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;tcpdump&lt;/span&gt;&lt;/blockquote&gt;El resultado es el volcado en tiempo real de todos los paquetes de comunicación que lleguen a la interfaz de red por defecto en el sistema. Cuando tengas suficiente presiona &lt;span style="font-family: courier new;"&gt;Ctrl-C&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;a href="http://micro-howto.blogspot.com/2009/03/servidor-linux-desde-tu-hogar-en-tres.html"&gt;Introduccion...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-1.html"&gt;Al paso 1...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-2.html"&gt;Al paso 2...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-3.html"&gt;Al paso 3...&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-935584277036034532?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/935584277036034532/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-intro-2.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/935584277036034532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/935584277036034532'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-intro-2.html' title='Servidor Linux desde tu hogar Intro 2'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-769079428539100835</id><published>2009-07-13T20:55:00.000-07:00</published><updated>2010-02-04T20:39:56.993-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><title type='text'>Servidor Linux desde tu hogar Paso 3</title><content type='html'>&lt;div style="text-align: right;"&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-2.html" name="'servidor-en-linux-dns'"&gt;&lt;/a&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=8587897704769639737&amp;amp;postID=769079428539100835" name="'servidor-en-linux-dns'"&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=8587897704769639737&amp;amp;postID=769079428539100835" name="'servidor-en-linux-dns'"&gt;&lt;span style="font-style: italic;"&gt;Recordando la localización de mi servidor&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Y otra vez los tres incisos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;conseguir el servicio de DNS&lt;/li&gt;&lt;li&gt;configurar el servidor&lt;/li&gt;&lt;li&gt;probar&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-style: italic;"&gt;Servicio de DNS&lt;/span&gt;&lt;br /&gt;Lo más recomendable es utilizar un servicio DNS que por un lado ligue la dirección IP de tu servidor/ruteador con un nombre común y fácil de recordar. Por otro lado, en caso de que tengas una dirección IP dinámica, el servicio DNS también debería asociar dinámicamente la nueva dirección IP con el nombre de tu servidor.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Esto se logra de manera sencilla y barata registrándose con servicios gratuitos de DNS dinámico. Por ejemplo &lt;a href="http://dyndns.com/" target="_blank"&gt;dyndns.com&lt;/a&gt;, &lt;a href="http://no-ip.com/" target="_blank"&gt;no-ip.com&lt;/a&gt;, etc.&lt;br /&gt;&lt;br /&gt;En un sitio como estos deberás dar de alta la dirección IP actual y relacionarla con el dominio DNS que desees. Si el servicio es gratuito, por lo general tu domino quedará con un 'apellido' proporcionado por el servicio. Si esto te importa y deseas tener tu dominio completamente personal, deberás buscar un servicio de DNS al cual pagarle una cuota. Si deseas un domino .mx, .es, o de cualquier otra localidad, el servicio de DNS debería de ser proporcionado en el país elegido.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Configurar el servidor&lt;/span&gt;&lt;br /&gt;Además de esto, tu servidor debe de ejecutar algún script de inicio para que cada vez que se encienda el servidor se contacte con el servidor DNS dinámico y se asocie el nombre de tu dominio con la dirección IP que tenga tu servidor actualmente, para el caso en que haya cambiado. Por lo general, los sitios de servicios de DNS dinámico te dan instrucciones para poder levantar dicho script de inicio.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Pruebas&lt;/span&gt;&lt;br /&gt;A estas alturas las pruebas ya son muy sencillas. Las puedes hacer incluso desde dentro de tu servidor o tu LAN, o desde fuera. Elige alguna aplicación o servicio que esté dado de alta en el servidor e intenta conectarte a él con el número de puerto correcto, pero en vez de utilizar el número de dirección IP, utiliza el nombre del dominio que hayas registrado.&lt;br /&gt;&lt;br /&gt;Por ejemplo, con un navegador web, intenta la URL: &lt;a href="http://midominio.posible_apellidodns.com_o_net_o_org_o_loquesea/" style="font-family: courier new;"&gt;http://miDominio.posible_apellidoDNS.com_o_net_o_org_o_loquesea&lt;/a&gt; y deberás de poder ver la página web de inicio que tengas configurada en tu servidor...&lt;br /&gt;&lt;br /&gt;Otra prueba importante es la del cambio de dirección IP, en caso de que, como yo, tengas asignación de dirección IP dinámica por parte de tu ISP. Una manera sencilla puede consistir en desconectar de la corriente eléctrica tu ruteador y esperar un rato, luego reconectar (con la esperanza de que así se renueve la dirección IP y cambie a otra), reiniciar el servidor (me parece que en este caso no hay más que hacer, debe re-ligarse el servidor con la nueva dirección IP, aunque quien sabe, tal vez haya forma de hacerlo sin reinicio... además debe ejecutarse el script de inicio para remapear la nueva dirección IP con el dominio que tengas, cosa que no necesariamente implica un reincio, se podría ejecutar manualmente) y luego volver a hacer la prueba con el nombre de dominio...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=8587897704769639737&amp;amp;postID=769079428539100835" name="servidor-en-linux-apendice"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Apéndice&lt;/span&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hay muchas otras cosas que se pueden hacer aún para mejorar la configuración y desempeño del servidor. Afinar un servidor para su funcionamiento eficiente es también parte del trabajo que hace un buen administrador de sistemas. Además de lo que se pueda hacer dentro del servidor, se pueden hacer algunas otras cosas para mejorar el servicio de internet mismo que recibe el servidor, como ahorrar un poco y contratar un &lt;span style="font-style: italic;"&gt;servicio más rápido&lt;/span&gt;, o una &lt;span style="font-style: italic;"&gt;dirección IP fija&lt;/span&gt;. Una buena inversión puede ser la de protejer tu servidor, y tu ruteador dicho sea de paso, con un &lt;span style="font-style: italic;"&gt;no-break / regulador&lt;/span&gt;. Además de la protección contra picos de corriente, el hecho de que tu servidor se mantenga más tiempo encendido puede motivarte. Y además, si tu ruteador no se apaga por fallos de corriente, probablemente los cambios de dirección IP te afecten menos...&lt;br /&gt;&lt;br /&gt;Internet es, en mi opinión, uno de los sistemas más interesantes que existen en el mundo. La forma en que funciona, su capacidad de auto-organizarse, las características de sus protocolos, etc. Levantar un servidor en Internet es apenas un pequeño pedazo de la complejidad interesante que compone a la red de redes, y al haber levantado un servidor, al mismo tiempo se abre la puerta a muchas otras características interesantes que se pueden conocer de lo que es Internet.&lt;br /&gt;&lt;br /&gt;Para conocer más, de servidores en particular y de Internet en general, existen muchos recursos, libros y sitios en la red, que se pueden consultar.&lt;br /&gt;&lt;br /&gt;Este &lt;a href="http://www.theshulers.com/whitepapers/internet_whitepaper/index.html"&gt;link&lt;/a&gt; es una introducción breve (en inglés) al funcionamiento general de Internet.&lt;br /&gt;&lt;br /&gt;Los protocolos y toda la definición de internet se lleva a cabo a través de documentos llamados &lt;a href="http://www.ietf.org/rfc.html"&gt;RFCs&lt;/a&gt; (Request For Comments), que administra la &lt;a href="http://www.ietf.org/"&gt;IETF&lt;/a&gt; (Internet Engineering Task Force), el organismo que tradicionalmente heredó la administración y definición de Internet desde su &lt;a href="http://es.wikipedia.org/wiki/Historia_de_Internet"&gt;creación&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por ejemplo, el protocolo IP se define en el RFC 791. El TCP en el RFC 793. HTTP en el RFC 2616. SMTP (email) en el RFC 822, etc.&lt;br /&gt;&lt;br /&gt;Para conocer de protocolos también se puede hacer uso de software que permite observar la comunicación de la red en acción, ya mencioné &lt;span style="font-family: times new roman; font-style: italic;"&gt;tcpdump&lt;/span&gt;, pero existen otros programas de entorno más amigable, como &lt;a href="http://wireshark.org/"&gt;Wireshark&lt;/a&gt;, entre otros.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;a href="http://micro-howto.blogspot.com/2009/03/servidor-linux-desde-tu-hogar-en-tres.html"&gt;Introduccion...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-intro-2.html"&gt;Intro-2...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-1.html"&gt;Al paso 1...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-2.html"&gt;Al paso 2...&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-769079428539100835?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/769079428539100835/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-3.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/769079428539100835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/769079428539100835'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-3.html' title='Servidor Linux desde tu hogar Paso 3'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-8655331258989812130</id><published>2009-07-13T20:54:00.000-07:00</published><updated>2010-02-04T23:17:46.793-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><title type='text'>Servidor Linux desde tu hogar Paso 2</title><content type='html'>&lt;a href="http://www.blogger.com/" name="'servidor-en-linux-levantandoservidor'"&gt;&lt;span style="font-style: italic;"&gt;Levantado mi servidor&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;De nuevo, este paso se realiza en tres incisos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;configurar el firewall, para la seguridad&lt;/li&gt;&lt;li&gt;instalar, configurar y levantar los servicios en sí mismos&lt;/li&gt;&lt;li&gt;probar&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-style: italic;"&gt;Configurar el firewall&lt;/span&gt;&lt;br /&gt;Dependiendo la distribución Linux que tengas, éstas muchas veces ya vienen con utilidades de configuración que permiten establecer la seguridad del firewall en la máquina. Todo lo puedes configurar a través de estas utilidades, o configurando directamente los archivos pertinentes. En este tutorial no nos enfocaremos en ninguna de esas dos formas, solamente mencionaré lo que en sí tienes que conseguir.&lt;br /&gt;&lt;br /&gt;Una de las cosas que requieres, y que probablemente haya quedado configurada desde el inicio cuando instalaste (o te instalaron) Linux en la máquina, es que el firewall se active desde que arranca la máquina, de otra forma tendrías que estarlo activando manualmente cada vez que reinicias tu máquina.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Por otro lado, también debes seleccionar la interfaz de red que quedará protegida por el firewall. Por un lado es recomendable que actives para todas las interfaces, pero por otro también recuerda que sólo una de las interfaces quedará configurada con el port-forwarding desde el ruteador, por lo que ésta es la más importante a configurar. Las demás, son lo de menos pues el mismo ruteador implementa seguridad de firewall para los otros dispositivos ;)&lt;br /&gt;&lt;br /&gt;Por último, debes habilitar los servicios a ser permitidos. Esto no significa que los servicios ya quedarán configurados, solamente se abrirán los puertos especificados para que los servicios funcionen. El listado de puertos debe configurarse para que sean vistos hacia el exterior, de lo contrario no serán vistos desde fuera. Dicho listado puede incluir cuantos servicios quieras levantar en el servidor. Los más comunes son HTTP (puerto 80), FTP (puerto 21), SSH (puerto 22), Telnet (puerto 23), SMTP (puerto 25) y cualquier otro puerto de aplicaciones particulares como MySQL (puerto 3306), PostgreSQL (puerto 5432), SubVersion (puerto 3690), algún servidor de aplicaciones como Tomcat (puerto 8080), etc. Obviamente, si al momento de levantar un servicio (lo que cubriré a continuación), eliges utilizar un puerto diferente al estándar, entonces dicho puerto es el que debes abrir en el firewall, en lugar del que comúnmente se utilizaría, y debes recordar conectarte al servidor en ese puerto específico para usar dicho servicio, de lo contrario puedes estar intentando conectarte al puerto por defecto y asumir que no hay conexión o que el servidor no funciona correctamente.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Los servicios&lt;/span&gt;&lt;br /&gt;A continuación, debes levantar los servicios a utilizar. Igualmente, puedes hacerlo 'a mano', o utilizando las utilidades de configuración que vengan con la distribución Linux que estés utilizando. Sin enfocarme en una u otra opción, ni en ningún servicio en particular, básicamente tienes que instalar y configurar la aplicación que proporcione dicho servicio en el sistema.&lt;br /&gt;&lt;br /&gt;Por ejemplo, para un servidor HTTP, puedes instalar el popular Apache. Para un servidor FTP, puedes utilizar VSFTP. Para SSH, el más común es OpenSSH. Para aplicaciones particulares, como servidores de bases de datos, versionadores o aplicaciones, cada aplicación la debes instalar y configurar correctamente (sin olvidar abrir los puertos necesarios en el firewall del servidor cada vez que hagas esto).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Hecho esto, ahora sí solamente te queda probar...&lt;/span&gt;&lt;br /&gt;Supongamos que instalaste Apache en tu servidor (o cualquier otro servidor web). En un navegador web dentro del mismo servidor puedes introducir en la URL lo siguiente: &lt;a href="http://localhost/" style="font-family: courier new;" target="_blank"&gt;http://localhost/&lt;/a&gt;, con lo que no estarás utilizando el port-forwarding. Si por otro lado introduces &lt;a href="http://midireccionip/" style="font-family: courier new;" target="_blank"&gt;http://midireccionip/&lt;/a&gt; y obtienes el mismo resultado que con &lt;span style="font-family: courier new;"&gt;localhost&lt;/span&gt;, entonces las cosas van funcionando bien. Si haces la prueba de &lt;a href="http://midireccionip/" style="font-family: courier new;" target="_blank"&gt;http://midireccionip/&lt;/a&gt; desde otra máquina de la LAN, debes obtener el mismo resultado. Pero la prueba más interesante, y la más efectiva, es realizar la prueba desde el exterior. Te puedes ir a un cibercafé cercano, o probar desde otro lugar con acceso a internet, o que alguien más prueba mientras te informa del resultado. Asegúrate, claro está, de tener tu servidor encendido y conectado a internet, y de recordar ese feo numerito: &lt;span style="font-family: courier new;"&gt;midireccionIP&lt;/span&gt; ;)&lt;br /&gt;&lt;br /&gt;Las mismas pruebas las puedes hacer para servicios distintos a un servidor HTTP:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;con FTP conéctate e intenta bajar/subir archivos (dependiendo la forma en que hubieras configurado el servico)&lt;/li&gt;&lt;li&gt;con SSH, intenta conectarte y entrar a sesión en el servidor de forma remota&lt;/li&gt;&lt;li&gt;con SVN, levanta un repositorio en el servidor y luego trata de acceder a él (haciendo un checkout y luego checkins a cambios hechos) desde el exterior&lt;/li&gt;&lt;li&gt;con MySQL, con un cliente de dicha base de datos en el exterior, intenta conectarte al servidor levantado&lt;/li&gt;&lt;li&gt;en fin, las prueba dependerá de la aplicación y servicio instalados&lt;/li&gt;&lt;/ul&gt;Además, si es posible que tengas acceso fuera de la LAN a los programas de utilidad que mencioné al principio, puedes hacer un &lt;span style="font-family: times new roman; font-style: italic;"&gt;ping&lt;/span&gt; al servidor nuevo, para ver si responde, un &lt;span style="font-family: times new roman; font-style: italic;"&gt;traceroute&lt;/span&gt; para ubicar la ruta para llegar a el, y un &lt;span style="font-family: times new roman; font-style: italic;"&gt;nmap &lt;/span&gt;para conocer qué puertos tiene abiertos tu servidor. Por otro lado, de regreso al servidor, las aplicaciones levantadas suelen dejar un log que será conveniente que siempre revises y monitorees, para observar cómo ha sido el desempeño y el uso que se ha hecho de tu servidor desde el exterior.&lt;br /&gt;&lt;br /&gt;Para terminar este paso, una pequeña nota: para los que son observadores, podrán haber notado que este segundo paso (levantar el servidor), es de alguna manera independiente al paso 1 (publicar la dirección IP). ¿Qué se logra si se realiza este paso 2, sin haber realizado el paso 1?... ¿Aún no? Bueno, pues se logra tener servicios levantados, pero &lt;span style="font-weight: bold;"&gt;exclusivamente&lt;/span&gt; para la LAN en que se encuentre el servidor. Es decir, todas las demás máquinas de la LAN podrán usar los servicios del servidor, a manera de una &lt;span style="font-style: italic;"&gt;intranet&lt;/span&gt;. Es cuando se publica la dirección IP que se consigue tener el servidor a nivel externo de la LAN.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;a href="http://micro-howto.blogspot.com/2009/03/servidor-linux-desde-tu-hogar-en-tres.html"&gt;Introduccion...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-intro-2.html"&gt;Intro-2...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-1.html"&gt;Al paso 1...&lt;/a&gt;&lt;br /&gt;&lt;a href="http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-3.html"&gt;Al paso 3...&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8587897704769639737-8655331258989812130?l=micro-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://micro-howto.blogspot.com/feeds/8655331258989812130/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-2.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8655331258989812130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8587897704769639737/posts/default/8655331258989812130'/><link rel='alternate' type='text/html' href='http://micro-howto.blogspot.com/2009/07/servidor-linux-desde-tu-hogar-paso-2.html' title='Servidor Linux desde tu hogar Paso 2'/><author><name>Javier Novoa C. (Stitch)</name><uri>http://www.blogger.com/profile/13132360799518616672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/_XrECR80gtTI/Sx2CaSRSaUI/AAAAAAAAAGs/kpuqsihzfzo/s1600-R/User_JStitch_esWikipedia.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8587897704769639737.post-3375544379431421860</id><published>2009-07-13T20:53:00.000-07:00</published><updated>2010-02-04T23:17:08.599-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='servidores'/><title type='text'>Servidor Linux desde tu hogar Paso 1</title><content type='html'>&lt;a href="http://www.blogger.com/" name="servidor-en-linux-publicarip"&gt;&lt;span style="font-style: italic;"&gt;Publicando mi dirección IP&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Este paso se realiza en dos (bueno, tres) incisos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;ligar la dirección IP del ruteador con el servidor, configurando el ruteador&lt;/li&gt;&lt;li&gt;habilitar el servidor para tomar dicha dirección&lt;/li&gt;&lt;li&gt;probar&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-style: italic;"&gt;Ligar la dirección IP&lt;/span&gt;&lt;br /&gt;Para publicar la dirección IP, es decir, para que la dirección IP externa, del ruteador, quede ligada a la máquina que funcionará como servidor, debes acceder a la página de configuración del ruteador. Dependiendo el modelo del aparato, esta puede cambiar. En este caso te recomiendo que consultes la documentación del ruteador para conocerla. Un caso típico es en la dirección &lt;span style="font-family: courier new;"&gt;192.168.1.254&lt;/span&gt;, aunque como dije, esto depende de cada ruteador.&lt;br /&gt;&lt;br /&gt;Una vez dentro debes buscar la opción para redirigir todas las peticiones del ruteador hacia la máquina específica del servidor. Esto se conoce como &lt;span style="font-style: italic; font-weight: bold;"&gt;port-forwarding&lt;/span&gt;, y normalmente se encuentra dentro de las opciones del firewall del ruteador. Por ejemplo, en un ruteador 2Wire, accediendo a las opciones del firewall para la máquina en particular que funcionará como servidor, deberías colocar dicha máquina en el modo &lt;span style="font-style: italic;"&gt;DMZPlus&lt;/span&gt;. Esto provocará que todo el tráfico que entre al ruteador sea dirigido a la máquina servidora, excepto aquel que por configuraciones del mismo firewall del ruteador se haya especificado para dirigirse a otras máquinas, para aplicaciones particulares.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Cabe mencionar que &lt;span style="font-style: italic;"&gt;esta configuración quedará habilitada únicamente para una de las interfaces de red de la máquina servidora&lt;/span&gt;. Es decir, si el servidor accede a la red vía Ethernet, vía Wireless y demás, sólo una de ellas puede ser habilitada para el port-forwarding, por lo que cuando se use la máquina como servidor, asegúrate de estar usando dicha interfaz de red, de lo contrario la máquina funcionará como cualquier otra máquina de la LAN y no será vista en el exterior. De hecho, esta configuración sólo puede habilitarse para una interfaz de una sola máquina de la LAN, el resto de las máquinas no quedarían como servidores.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Habilitar servidor&lt;/span&gt;&lt;br /&gt;En cuanto a la máquina servidora, debes &lt;span style="font-style: italic;"&gt;habilitar el modo DHCP&lt;/span&gt; en la misma, de forma que la máquina mantenga la 'liga' de su dirección IP con la del ruteador. Esto lo puedes hacer con las utilidades de configuración de la distribución Linux que tenga o manualmente, como prefieras. Hay que instalar los paquetes necesarios para DHCP y levantar los servicios para que se inicien siempre.&lt;br /&gt;&lt;br /&gt;Una vez hecho esto, este es uno de los raros casos en que deberás reiniciar la máquina, para tener el servidor listo para ser visto por el mundo exterior. A partir de entonces, si lo deseas y cuentas con la posibilidad, prácticamente será innecesario reiniciar la máquina servidora, para tenerla disponible todo el tiempo en internet. Incluso al configurar el firewall, instalar o configurar los servicios y demás operaciones, el servidor puede permanecer sin reiniciar y seguir funcionando eficientemente (detalle que por cierto caracteriza a los servidores Linux, frente a los servidores en Windows, y que es motivo de orgullo para algunos administradores de servidores, al mantener un récord del tiempo corrido que sus servidores han permanecido encendidos y sin reiniciar).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;¿Cómo probar si todo esto funcionó?&lt;/span&gt;&lt;br /&gt;Una vez configurado el ruteador y la máquina servidora en modo DHCP, y reiniciada, la máquina ya debe ser visible desde el exterior. Una forma de probarlo es que continués hasta llegar a las pruebas del paso 2, hasta que ya se tengan servicios levantados. Por otro lado, desde dentro de la LAN es más difícil probarlo, y desde fuera se puede hacer un ping a la dirección IP que tenga ya la máquina, aunque esto no garantiza que te estés comunicando con la máquina en sí, sino con el ruteador. Lo que si debes notar es que, al hacer un &lt;span style="font-family: times new roman; font-style: italic;"&gt;ifconfig&lt;/span&gt;, la dirección IP de la máquina debe ser idéntica a la que reporte un sitio como &lt;a href="http://whatismyipaddress.com/" target="'_blank'"&gt;este&lt;/a&gt;. &lt;span style="font-weight: bold;"&gt;¡Toma nota de ese número!&lt;/span&gt; por ahora será la dirección IP con la que podrás acceder a tu servidor desde el exterior. Además, si haces un &lt;span style="font-family: times new roman; font-style: italic;"&gt;tcpdump&lt;/span&gt;, puedes inspeccionar los paquetes de tu servidor para darte cuenta que se está utilizando la dirección IP del ruteador.&lt;br /&gt;&lt;br /&gt;Además, si consultas el log del sistema (depende de la instalación Linux, un lugar típico es en &lt;span style="font-family: courier new;"&gt;/var/log&lt;/span&gt;, y si estás usando &lt;span style="font-family: times new roman; font-style: italic;"&gt;syslog &lt;/span&gt;para loggear eventos del sistema, en el archivo &lt;span style="font-family: courier new;"&gt;messages&lt;/span&gt;), debes notar que el cliente DHCP de 
