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

<channel>
	<title>BlueThinking</title>
	<atom:link href="http://www.elartistadelalambre.net/bluethinking/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.elartistadelalambre.net/bluethinking</link>
	<description>think in blue</description>
	<lastBuildDate>Fri, 13 Apr 2012 19:18:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ejecutar un comando con pipe desde python y leer la salida</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=82</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=82#comments</comments>
		<pubDate>Fri, 13 Apr 2012 19:18:56 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Trucos]]></category>
		<category><![CDATA[ipmitool]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[pipe]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=82</guid>
		<description><![CDATA[Desde python, como desde cualquier lenguaje de programación, podemos lanzar un comando externo al propio lenguaje de programación. Bien para cubrir algún aspecto que no provee el lenguaje o, la mayoría de las veces, para tapar nuestro desconocimiento del lenguaje. En la mayoría de las ocasiones no es suficiente sólo con lanzar el comando. Queremos, [...]]]></description>
			<content:encoded><![CDATA[<p>Desde python, como desde cualquier lenguaje de programación, podemos lanzar un comando externo al propio lenguaje de programación. Bien para cubrir algún aspecto que no provee el lenguaje o, la mayoría de las veces, para tapar nuestro desconocimiento del lenguaje.</p>
<p>En la mayoría de las ocasiones no es suficiente sólo con lanzar el comando. Queremos, además, poder procesar la salida recibida de alguna forma.</p>
<p>En python existen muchas formas de lanzar un comando externo, una de ellas es usando <strong>subprocess</strong>, que tiene algunas características particulares cuando el comando que lanzamos tiene pipes (tuberías).</p>
<p>En sistemas operativos entendemos por una tubería al procedimiento que permite enlazar la salida de un comando como entrada de otro:</p>
<blockquote><p>In Unix-like computer operating systems (and, to some extent, Microsoft Windows), a pipeline is the original software pipeline: a set of processes chained by their standard streams, so that the output of each process (stdout) feeds directly as input (stdin) to the next one. Each connection is implemented by an anonymous pipe. Filter programs are often used in this configuration. <a title="operating system pipe" href="http://en.wikipedia.org/wiki/Pipeline_%28Unix%29">Wikipedia</a></p></blockquote>
<p>Un ejemplo sería, en un entorno linux, el siguiente comando que nos cuenta el número de ficheros y directorios que tenemos en un determinado directorio:</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ls -l | wc -l</div></div>
<p>Curioso, ¿verdad? </p>
<p>Lo que hemos hecho ha sido ejecutar un ls -l (que muestra cada fichero y cada directorio en una línea) y el resultado, en vez de mostrarlo en pantalla como haría por defecto, se lo hemos pasado al comando wc -l que cuenta el número de lineas que ha recibido como entrada.</p>
<p>El ejemplo que queremos ver es el siguiente:</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ipmitool sensor | grep deg</div></div>
<p>ipmitool es una herramienta que permite leer la información de los sensores de nuestro ordenador. Nuestro ordenador tiene una serie de sensores que nos informan del estado del sistema, la mayoría de ellos se refieren a la temperatura que hay en la CPU, en la tarjeta gráfica etc.</p>
<blockquote><p>IPMItool is a utility for managing and configuring devices that support the Intelligent Platform Management Interface (IPMI) version 1.5 and version 2.0 specifications. IPMI is an open standard for monitoring, logging, recovery, inventory, and control of hardware that is implemented independent of the main CPU, BIOS, and OS.</p></blockquote>
<p>Lo que hacemos con el comando anterior es mostrar la información de todos los sensores, y la salida, en vez de mostrarla en pantalla, la pasamos al comando grep que filtra sólo aquellas que tienen la palabra deg en algún lado: es decir el comando entero sólo muestra la información de aquellos sensores que tengan algo que ver con la temperatura (deg = grados )</p>
<p>La salida esperada sería algo como:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CPU <span style="color: #000000;">0</span> Temp &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">48.000</span> &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> degrees C &nbsp;<span style="color: #000000; font-weight: bold;">|</span> ok &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">93.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">95.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<br />
CPU <span style="color: #000000;">1</span> Temp &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">50.000</span> &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> degrees C &nbsp;<span style="color: #000000; font-weight: bold;">|</span> ok &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">93.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">95.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<br />
Ambient Temp0 &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">39.000</span> &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> degrees C &nbsp;<span style="color: #000000; font-weight: bold;">|</span> ok &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">70.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">75.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<br />
Ambient Temp1 &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">47.000</span> &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">|</span> degrees C &nbsp;<span style="color: #000000; font-weight: bold;">|</span> ok &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">70.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">75.000</span> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">|</span> na</div></div>
<p>La primera columna es el nombre del sensor, la segunda la temperatura actual. Las tres últimas informan de las temperaturas máximas que el sistema soportará antes de enviar mensajes de warning, de peligro o críticos, respectivamente.</p>
<p>Si queremos procesar esa salida de forma &#8220;elegante&#8221; para poder realizar algunas operaciones con ellos (guardar histórico, enviar correos&#8230;) debemos guardar esos datos en, por ejemplo, un array.</p>
<p>Por extraño que pueda parecernos, python no deja lanzar un comando con un pipe porque entiende, con toda la razón, que son dos procesos que deben enlazarse de la forma correcta:</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">subprocess</span> <span style="color: #ff7700;font-weight:bold;">import</span> Popen<span style="color: #66cc66;">,</span> PIPE<br />
<br />
<br />
p1 <span style="color: #66cc66;">=</span> Popen<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;ipmitool&quot;</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">&quot;sensor&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> stdout<span style="color: #66cc66;">=</span>PIPE<span style="color: black;">&#41;</span><br />
p2 <span style="color: #66cc66;">=</span> Popen<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;grep&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;deg&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> stdin<span style="color: #66cc66;">=</span>p1.<span style="color: black;">stdout</span><span style="color: #66cc66;">,</span> stdout <span style="color: #66cc66;">=</span> PIPE<span style="color: black;">&#41;</span><br />
p1.<span style="color: black;">stdout</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
result <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span> p2.<span style="color: black;">communicate</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: black;">&#41;</span><br />
p1.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>Es de una lógica aplastante, pero no es nada intuitivo. Una vez que hemos adivinado eso, el resto es relativamente sencillo.</p>
<p>Conviene fijarse en con que gran habilidad hemos convertido la salida del proceso en líneas que luego son procesadas, a través del uso del readline y del split:</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">subprocess</span> <span style="color: #ff7700;font-weight:bold;">import</span> Popen<span style="color: #66cc66;">,</span> PIPE<br />
<br />
p1 <span style="color: #66cc66;">=</span> Popen<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;ipmitool&quot;</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">&quot;sensor&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> stdout<span style="color: #66cc66;">=</span>PIPE<span style="color: black;">&#41;</span><br />
p2 <span style="color: #66cc66;">=</span> Popen<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;grep&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;deg&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> stdin<span style="color: #66cc66;">=</span>p1.<span style="color: black;">stdout</span><span style="color: #66cc66;">,</span> stdout <span style="color: #66cc66;">=</span> PIPE<span style="color: black;">&#41;</span><br />
p1.<span style="color: black;">stdout</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
result <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span> p2.<span style="color: black;">communicate</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: black;">&#41;</span><br />
p1.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
result <span style="color: #66cc66;">=</span> result.<span style="color: black;">splitlines</span> <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">for</span> data <span style="color: #ff7700;font-weight:bold;">in</span> result:<br />
&nbsp; &nbsp;l <span style="color: #66cc66;">=</span> data.<span style="color: black;">split</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;|&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;nombre <span style="color: #66cc66;">=</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;temperatura <span style="color: #66cc66;">=</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;twarn <span style="color: #66cc66;">=</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;tsoft <span style="color: #66cc66;">=</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;tcrit <span style="color: #66cc66;">=</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>La ausencia de vida social, lejos del dolor y la agonía que me auguraba mi psicólogo,  permite encontrar breves momentos de paz en estas cosas.</p>
<p>Sad but true.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=82</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Error en Drupal 7:drupal 7 PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded;</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=72</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=72#comments</comments>
		<pubDate>Thu, 22 Mar 2012 16:05:59 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Trucos]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[MySql]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=72</guid>
		<description><![CDATA[Cuando trabajamos con Drupal 7 normalmente cargamos bastante el sistema durante el despliegue inicial: instalación de módulos, cargar el contenido inicial&#8230; A veces, cuando estamos realizando esas operaciones, el servidor contra el que lo hacemos puede dar algún fallo por lo que debemos refrescar la página para volver a entrar. Cada vez que entramos en [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando trabajamos con Drupal 7 normalmente cargamos bastante el sistema durante el despliegue inicial: instalación de módulos, cargar el contenido inicial&#8230;</p>
<p>A veces, cuando estamos realizando esas operaciones, el servidor contra el que lo hacemos puede dar algún fallo por lo que debemos refrescar la página para volver a entrar.</p>
<p>Cada vez que entramos en el sistema Drupal guarda cierta información en las tablas de la base de datos para hacer más rápida la carga (una especie de caché del sistema). Si el servidor nos da algún fallo y refrescamos los datos de esas tablas pueden corromperse y el sistema nos devuelve de forma insistente ese mensaje de error:</p>
<blockquote><p><strong>drupal 7 PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded;</strong></p></blockquote>
<p>No sé si existirá una opción mejor, pero una forma de arreglar ese problema es conectarse a la base de datos de Drupal (generalmente a través del administrador que nos provee el servicio de hosting, a través de la línea de comandos o bien con phpMyAdmin), y vaciar todas las tablas relacionadas con la cache del sistema:</p>
<div class="codecolorer-container sql default" style="border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_block`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_bootstrap`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_field`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_filter`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_form`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_image`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_menu`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_metatag`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_page`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_path`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_token`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_update`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_variable`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_views`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_views_data`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`cache_widgets`</span> ;<br />
<span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #ff0000;">`sessions`</span> ;</div></div>
<p>Si al vaciar alguna de esas tablas obtenemos un error debemos reparar la tabla afectada.</p>
<div class="codecolorer-container sql default" style="border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">REPAIR <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`tbl_name`</span>;</div></div>
<p>No es peligroso eliminar los datos de esas tablas, ya que el contenido es creado de forma automática durante la navegación por el sitio, aún así siempre es conveniente realizar una copia de seguridad, eso no hace falta decirlo, ¿verdad?</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=72</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Personalizar los breadcrumbs en Drupal 7x</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=69</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=69#comments</comments>
		<pubDate>Sat, 03 Mar 2012 18:51:12 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Trucos]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=69</guid>
		<description><![CDATA[Un hilo de Ariadna (Breadcrumb o migas de pan en inglés) es una técnica de navegación usada para desarrollar la interfaz gráfica de usuario. Tiene como objetivo que el usuario guarde una ruta de su ubicación dentro de programas o documentos. El término en inglés es breadcrumb, que proviene del cuento clásico Hansel y Gretel. [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Un <strong>hilo de Ariadna</strong> (<strong>Breadcrumb</strong> o <strong>migas de pan</strong> en <a title="Idioma inglés" href="http://es.wikipedia.org/wiki/Idioma_ingl%C3%A9s">inglés</a>) es una técnica de navegación usada para desarrollar la <a title="Interfaz gráfica de usuario" href="http://es.wikipedia.org/wiki/Interfaz_gr%C3%A1fica_de_usuario">interfaz gráfica de usuario</a>. Tiene como objetivo que el usuario guarde una ruta de su ubicación dentro de programas o documentos. El término en inglés es <strong>breadcrumb</strong>, que proviene del cuento clásico <a title="Hansel y Gretel" href="http://es.wikipedia.org/wiki/Hansel_y_Gretel">Hansel y Gretel</a>. En español, en vez del rastro de migas, se ha acuñado el término evocando el hilo que <a title="Ariadna" href="http://es.wikipedia.org/wiki/Ariadna">Ariadna</a> dejó a <a title="Teseo" href="http://es.wikipedia.org/wiki/Teseo">Teseo</a> para que encontrase el camino de salida en el <a title="Laberinto" href="http://es.wikipedia.org/wiki/Laberinto">laberinto</a> del <a title="Minotauro" href="http://es.wikipedia.org/wiki/Minotauro">Minotauro</a>. (fuente <a title="BreadCrumb" href="http://es.wikipedia.org/wiki/Hilo_de_Ariadna">Wikipedia</a>)</p></blockquote>
<p>&nbsp;</p>
<p>En resumen, un breadcrumb o hilo de Ariadna es ese texto que suele aparecer en la parte superior de algunas páginas web para mostrarnos el camino recorrido. De tal forma que si hemos entrado en un sitio buscando los drivers de nuestra tarjeta gráfica tendremos en la parte superior algo como: inicio / drivers / tarjeta gráfica / modelo. Siendo cada uno de los textos entre las barras un enlace que permite volver a la página de inicio, volver a la sección de drivers y sucesivamente.</p>
<p>En Drupal podemos generar de forma automática los breadcrumbs, pero el sistema lo hace a través de los elementos del menú que hayamos pulsado, para extender su funcionalidad podemos usar el módulo &#8220;<a title="menu breadcrumb module" href="http://drupal.org/project/menu_breadcrumb" target="_blank">Menu Breadcrumb</a>&#8220;, que admite la posibilidad de añadir de forma automática al breadcrumb el menú al que pertenece la página actual junto con la página actual convertida en enlace.</p>
<p>Sin embargo, existen ocasiones en que esto no es suficiente y necesitamos tener más control sobre lo que se muestra. En el ejemplo anterior, nos gustaría que, hubiésemos llegado como hubiésemos llegado a ella, siempre que se muestre la página de descarga de una determinada tarjeta gráfica se mostrase, además, la ruta: inicio / drivers / tarjeta gráfica, y no sólo inicio / tarjeta gráfica. Es decir, que al usuario siempre le quede claro que se encuentra en esa sección y que puede volver a buscar otros modelos y, por supuesto, volver al inicio.</p>
<p>Para lograr ese comportamiento deberíamos conseguir que al mostrar una página determinada se adjuntase al breadcrumb la ruta anterior con sus enlaces correspondientes, algo que no hace por defecto.</p>
<p>La mejor opción para lograrlo es instalar un módulo y saber un poco, muy poco, de PHP.</p>
<p>En el ejemplo siguiente partiremos del siguiente supuesto:</p>
<ul>
<li>Tenemos una página llamada productos cuya url es productos y con identificador node/30</li>
<li>En la página productos tenemos enlaces al productoA, productoB y productoC, que serán respectivamente node/25, node/30, node/45</li>
<li>Queremos que al mostrar productoA se muestre en el breadcrumb la ruta inicio / productos / productoA</li>
</ul>
<p>&nbsp;<br />
Seguir leyendo<span id="more-69"></span></p>
<p>&nbsp;</p>
<p>Los módulos necesarios son (customs breadcrumbs y menú breadcrumb):</p>
<p><a href="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread4.png"><img class="alignnone size-medium wp-image-65" title="CustomBread4" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread4-300x96.png" alt="Módulos necesarios" width="300" height="96" /></a></p>
<p>&nbsp;</p>
<p>Una vez instalados y activados debemos crear un disparador que cada vez que el sistema quiera mostrar alguna página de productos (25,30,45) se dispare y, mediante algún comando, adjunte la ruta de productos a nuestro breadcrumb.</p>
<p>En Drupal 7 lo hacemos pulsando sobre la opción de administración &#8220;structure&#8221;, y eligiendo la opción &#8220;custom breadcrumbs&#8221;:</p>
<p><a href="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread1.png"><img class="alignnone size-medium wp-image-68" title="CustomBread1" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread1-300x73.png" alt="Crear un breadcrumb" width="300" height="73" /></a></p>
<p>&nbsp;</p>
<p>Lo que nuestra la siguiente ventana:</p>
<p>&nbsp;</p>
<p><a href="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread3.png"><img class="alignnone size-medium wp-image-66" title="CustomBreadCrumbs" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread3-300x54.png" alt="" width="300" height="54" /></a></p>
<p>&nbsp;</p>
<p>En la que debemos elegir &#8220;Add a new custom breadcrumb&#8221;, bastante obvio por el momento, ¿verdad?</p>
<p>&nbsp;</p>
<p>En esta parte es donde debemos elegir como &#8220;node type&#8221; basic page, esto provoca que cada vez que se carga una página se llama a la función PHP escrita en la parte de Breadcrumb visibility, si la función devuelve true, entonces se modifica la función con los parámetros definidos:</p>
<p><a href="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread2.png"><img class="alignnone size-medium wp-image-67" title="CustomBread2" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2012/03/CustomBread2-300x137.png" alt="" width="300" height="137" /></a></p>
<p>&nbsp;</p>
<p>Vayamos por partes:</p>
<h1><span style="text-decoration: underline;"><strong>Breadcrumb visibility</strong></span>:</h1>
<p>&nbsp;</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//Array con las páginas que cumplirán la condición:</span><br />
<span style="color: #666666; font-style: italic;">//Aunque sea código PHP no debemos poner las etiquetas de inicio o cierre</span><br />
<span style="color: #666666; font-style: italic;">//ya que este código irá incrustado dentro de otro:</span><br />
<br />
<span style="color: #000088;">$listands</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">30</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">45</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//Si la página actual se encuentra en el array devuelve un TRUE:</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span> <a href="http://www.php.net/in_array"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$node</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>nid<span style="color: #339933;">,</span> <span style="color: #000088;">$listands</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Este código simplemente crea un array con los valores númericos de las páginas de producto, recordemos que eran 25, 30, 45. Después comprueba si la página actual se encuentra en esa lista y, de ser así, devuelve un verdadero.</p>
<p>&nbsp;</p>
<h1><strong>Titles</strong>:</h1>
<p>En caso de que la función anterior haya devuelto verdadero debemos construir nuestro hilo. El hilo se compone de una parte visual, la que se muestra al usuario: inicio / productos / productoA. Y una parte de sistema, las rutas a las que lleva cada paso home / node/20 / node/25.</p>
<p>En la parte de Title es el lugar donde definimos la parte visual:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Productos<br />
<span style="color: #009900;">&#91;</span>node<span style="color: #339933;">:</span>title<span style="color: #009900;">&#93;</span></div></div>
<p>Es decir, se mostrará al usuario una etiqueta llamada Productos / el título de la página actual, por ejemplo ProductoA.</p>
<h1><strong>Paths</strong>:</h1>
<p>Aquí definimos, por cada etiqueta anterior, la ruta que tiene:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">node<span style="color: #339933;">/</span><span style="color: #cc66cc;">20</span><br />
<span style="color: #009900;">&#91;</span>current<span style="color: #339933;">-</span>page<span style="color: #339933;">:</span>url<span style="color: #339933;">:</span>path<span style="color: #009900;">&#93;</span></div></div>
<p>&nbsp;</p>
<p>Si lo leemos en orden podemos ver que sería algo como: Por cada página que quiera mostrar evalúa la función PHP, si esta devuelve verdadero pinta en pantalla el contenido de Titles y asigna a cada uno de ellos la ruta establecida en paths.</p>
<p>La función PHP que hemos puesto es bastante versátil, pero podría ponerse cualquier condición, eso sí, hay que tener cuidado de no ser demasiado creativos, porque esa evaluación se disparará en cada página mostrada. Podríamos poner un simple IF con las diferentes páginas, examinar alguna condición externa.. Además, dentro de ese código, tenemos acceso a la variable $node que contiene toda la información relativa a la página actual (nodo).</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=69</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asignar permisos a un directorio desde la línea de comandos (en Windows)</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=62</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=62#comments</comments>
		<pubDate>Thu, 17 Nov 2011 19:41:37 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Comandos]]></category>
		<category><![CDATA[Trucos]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=62</guid>
		<description><![CDATA[En los últimos años Microsoft, en sus sistemas para servidores, parece haberse dado cuenta que encadenar todo la administración a una interfaz gráfica plagada de opciones no es la mejor solución para automatizar las operaciones más comunes. Uno de los últimos intentos ha sido la inclusión de una interfaz de comandos llamada powershell. Para aquellos [...]]]></description>
			<content:encoded><![CDATA[<p>En los últimos años Microsoft, en sus sistemas para servidores, parece haberse dado cuenta que encadenar todo la administración a una interfaz gráfica plagada de opciones no es la mejor solución para automatizar las operaciones más comunes.</p>
<p>Uno de los últimos intentos ha sido la inclusión de una interfaz de comandos llamada <strong>powershell</strong>. Para aquellos que vengan del mundo Unix no será nada revolucionado, e incluso puede ser frustrante cuando intentan usarla porque ha sido hecha al mejor estilo Microsoft: Un tipo de letra horrible, un autocompletar demente y una integración entre las diversas partes un tanto dudosas.</p>
<p>Para terminar de potenciar la interfaz han incluido un lenguaje de programación, de nuevo al estilo de los sistemas Unix, que permita automatizar las operaciones más comunes. Hemos visto en esta página algunos ejemplos sobre como usarlo.</p>
<p>El problema es que Microsoft tiene una capacidad innata para convertir en basura casi todas las buenas ideas que pasan por sus manos, y esto no es más que el siguiente hito en el camino. El sistema no es compatible entre diferentes versiones, hay demasiadas formas de hacer las cosas, y dependiendo desde donde lo ejecutes puedes obtener resultados distintos.</p>
<p><strong>Creación automatizada de directorios y asignación de permisos desde línea de comandos para una lista de usuarios:<br />
</strong></p>
<blockquote><p>Un ejemplo típico de la utilidad de las herramientas de administración mediante consola es la siguiente: Imaginemos que nos han pasado una lista con cien usuarios, y ha sido redactada de la siguiente forma:</p></blockquote>
<ul>
Usuario1<br />
Usuario2<br />
Usuario3
</ul>
<p>Y que queremos, en uno de nuestros servidores, crear un directorio a modo de repositorio con el nombre de casa usuario en el que sólo tenga permiso de acceso dicho usuario.</p>
<p>Desde la interfaz gráfica deberíamos situarnos en el directorio, crear un directorio, ir a las propiedades del mismo y asignar los permisos. Son cien usuarios, pues eso mismo cien veces.</p>
<p>Los permisos se pueden asignar desde la interfaz gráfica, como hemos dicho en el punto anterior, o bien recurrir a la herramienta icacls desde la línea de comandos:</p>
<div class="codecolorer-container powershell default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="powershell codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">#Para quitar el acceso al directorio para todos los usuarios del dominio:</span><br />
<span style="color: #008080; font-weight: bold;">PS</span> C:\<span style="color: pink;">&gt;</span> icacls directorio <span style="color: pink;">/</span>remove \<span style="color: #800000;">&quot;Usuarios del dominio&quot;</span> <br />
<span style="color: #008000;">#Damos permiso total (full control) al usuario:</span><br />
<span style="color: #008080; font-weight: bold;">PS</span> C:\<span style="color: pink;">&gt;</span> icacls directorio <span style="color: pink;">/</span>grant usuario:F</div></div>
<p>Sin embargo, aun teniendo la herramienta icacls, el crear los directorios uno por uno y asignar los permisos uno a uno es una tarea farragosa e ingrata. Lo ideal sería poder recorrer la lista anterior y, para cada usuario, crear un directorio, borrar los permisos para todo el mundo y agregar los del usuario.</p>
<p>Para hacerlo con el lenguaje de programación de <strong>powershell</strong> necesitaríamos una manera de ejecutar un comando externo, algo que seguramente exista, pero de todas las opciones probadas no he logrado que funcione ninguna (seguramente por culpa mía, claro)</p>
<p>Al final la opción más sencilla resulto hacer un programa en python y ejecutar los comandos desde allí.</p>
<div class="codecolorer-container powershell default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="powershell codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import sys<br />
import os<br />
from subprocess import call<br />
<br />
def ensure_dir<span style="color: #000000;">&#40;</span> d <span style="color: #000000;">&#41;</span>:<br />
<br />
&nbsp; &nbsp; <span style="color: #0000FF;">if</span> not os.path.exists<span style="color: #000000;">&#40;</span>d<span style="color: #000000;">&#41;</span>:<br />
&nbsp; &nbsp; print <span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;creando directorio %s&quot;</span><span style="color: #000000;">&#41;</span> <span style="color: pink;">%</span> <span style="color: #000000;">&#40;</span> d <span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; os.makedirs<span style="color: #000000;">&#40;</span>d<span style="color: #000000;">&#41;</span><br />
<br />
<span style="color: #008000;">#------------------------------------</span><br />
<br />
<span style="color: #0000FF;">if</span><span style="color: #000000;">&#40;</span>len<span style="color: #000000;">&#40;</span>sys.argv<span style="color: #000000;">&#41;</span> <span style="color: pink;">&gt;</span> <span style="color: #804000;">1</span><span style="color: #000000;">&#41;</span>:<br />
&nbsp; &nbsp; fichero <span style="color: pink;">=</span> sys.argv<span style="color: #000000;">&#91;</span><span style="color: #804000;">1</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; print <span style="color: #800000;">&quot;Abriendo &quot;</span> <span style="color: pink;">+</span> fichero<br />
&nbsp; &nbsp; f <span style="color: pink;">=</span> open<span style="color: #000000;">&#40;</span> fichero<span style="color: pink;">,</span> <span style="color: #800000;">&quot;r&quot;</span> <span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0000FF;">for</span> line <span style="color: #0000FF;">in</span> f:<br />
&nbsp; &nbsp; &nbsp; &nbsp; datos <span style="color: pink;">=</span> line.strip <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span> len <span style="color: #000000;">&#40;</span> datos <span style="color: #000000;">&#41;</span><span style="color: pink;">&gt;</span> <span style="color: #804000;">3</span> <span style="color: #000000;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print <span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;---%s--&quot;</span><span style="color: #000000;">&#41;</span> <span style="color: pink;">%</span> <span style="color: #000000;">&#40;</span>datos<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-weight: bold;">dir</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;.\\&quot;</span> <span style="color: pink;">+</span> datos<br />
&nbsp; &nbsp; &nbsp; &nbsp; print <span style="color: #008080; font-weight: bold;">dir</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ensure_dir <span style="color: #000000;">&#40;</span> <span style="color: #008080; font-weight: bold;">dir</span> <span style="color: #000000;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; cmd <span style="color: pink;">=</span> <span style="color: #800000;">&quot;icacls &quot;</span> <span style="color: pink;">+</span> &nbsp;datos <span style="color: pink;">+</span> <span style="color: #800000;">&quot; /remove \&quot;</span>Usuarios <span style="color: #008080; font-weight: bold;">del</span> dominio\<span style="color: #800000;">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; os.system<span style="color: #000000;">&#40;</span> cmd <span style="color: #000000;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; cmd <span style="color: pink;">=</span> <span style="color: #800000;">&quot;icacls &quot;</span> <span style="color: pink;">+</span> &nbsp;datos <span style="color: pink;">+</span> <span style="color: #800000;">&quot; /remove Everyone&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; os.system <span style="color: #000000;">&#40;</span> cmd <span style="color: #000000;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; cmd <span style="color: pink;">=</span> <span style="color: #800000;">&quot;icacls &quot;</span> <span style="color: pink;">+</span> &nbsp;datos <span style="color: pink;">+</span> <span style="color: #800000;">&quot; /grant &quot;</span> <span style="color: pink;">+</span> datos <span style="color: pink;">+</span> <span style="color: #800000;">&quot;:F&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; os.system <span style="color: #000000;">&#40;</span> cmd <span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; f.close<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> &nbsp; &nbsp;<br />
<span style="color: #0000FF;">else</span>:<br />
&nbsp; &nbsp; print <span style="color: #800000;">&quot;Debes indicar el nombre del archivo&quot;</span></div></div>
<p>El programa se encarga de abrir el fichero, recorrer cada línea, crear un directorio con ese nombre y asignar los permisos correspondientes. EL truco es que el nombre de usuario se llama exactamente igual que el directorio.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=62</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cambiar el tamaño a un grupo de imágenes</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=59</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=59#comments</comments>
		<pubDate>Tue, 18 Oct 2011 20:37:56 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Comandos]]></category>
		<category><![CDATA[Trucos]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mogrify]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=59</guid>
		<description><![CDATA[Muchas veces nos toca mandar alguna fotografía por correo y descubrimos que ocupan demasiado para poder ser enviadas. Algunos programas permiten automatizar de alguna forma ese problema, aunque no siempre los tenemos instalados o requieren demasiados pasos. El comando convert, del que ya hemos hablado en otras ocasiones, permite reducir el tamaño de una fotografía [...]]]></description>
			<content:encoded><![CDATA[<p>Muchas veces nos toca mandar alguna fotografía por correo y descubrimos que ocupan demasiado para poder ser enviadas. Algunos programas permiten automatizar de alguna forma ese problema, aunque no siempre los tenemos instalados o requieren demasiados pasos.</p>
<p>El comando <b>convert</b>, del que ya hemos hablado en otras ocasiones, permite reducir el tamaño de una fotografía a un porcentaje de la original o bien a un tamaño predefinido. Si tenemos un directorio con las fotos y otro llamado thumbs donde queremos guardar las imágenes en un tamaño más reducido (15% del tamaño inicial), podemos escribir lo siguiente en un terminal:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#Recorremos todos los ficheros con la extensión jpg y</span><br />
<span style="color: #666666; font-style: italic;">#los convertimos en la carpeta thumb:</span><br />
<span style="color: #000000; font-weight: bold;">for</span> f <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">*</span>.jpg ; <span style="color: #000000; font-weight: bold;">do</span> convert <span style="color: #660033;">-resize</span> <span style="color: #000000;">15</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #007800;">$f</span> thumb<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$f</span>; <span style="color: #000000; font-weight: bold;">done</span></div></div>
<p>Si, además, somos de los que no nos gusta dar pistas sobre como hemos hecho las fotos siempre podemos hacer un procesado para eliminar toda la información Exif (además ahorramos algo de tamaño). En esta ocasión lo haremos directamente sobre las fotos, sin salvar el original, y con el comando find (por variar):</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#Vamos al directorio donde hemos dejado las fotos</span><br />
<span style="color: #7a0874; font-weight: bold;">cd</span> thumb<br />
<span style="color: #666666; font-style: italic;">#Y eliminamos la información Exif del fichero:</span><br />
<span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #000000; font-weight: bold;">*</span>.jpg &nbsp;<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">xargs</span> mogrify <span style="color: #660033;">-strip</span></div></div>
<p><b>mogrify</b> es una navaja suiza similar a <b>convert</b>, y también cuenta con numerosas posibilidades que se pueden consultar con el man.</p>
<p>Si miramos la ayuda de convert veremos que permite, además, hacer un sinfín de operaciones con las imágenes, que pueden ser procesadas usando el comando anterior.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=59</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Segunda parte: creación de módulos en drupal 7.x</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=56</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=56#comments</comments>
		<pubDate>Sat, 17 Sep 2011 20:53:24 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=56</guid>
		<description><![CDATA[en el ejemplo anterior vimos como crear un módulo avanzado con drupal, que tuviese navegación entre varios formularios y crease un esquema en la base de datos. Sin embargo ese ejemplo era un módulo que se encontraba disponible para todo el mundo, tanto usuarios registrados como usuarios públicos. Si queremos añadir algún tipo de control [...]]]></description>
			<content:encoded><![CDATA[<p>en el ejemplo <a href="http://www.elartistadelalambre.net/bluethinking/?p=51" title="primera parte" target="_blank">anterior</a> vimos como crear un módulo avanzado con drupal, que tuviese navegación entre varios formularios y crease un esquema en la base de datos.</p>
<p>Sin embargo ese ejemplo era un módulo que se encontraba disponible para todo el mundo, tanto usuarios registrados como usuarios públicos.</p>
<p>Si queremos añadir algún tipo de control de acceso debemos retocar algo el código anterior, en concreto en el hook de menú:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> MiPrimerModulo_menu<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//global $user;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//$user-&gt;uid == 0 son los usuarios no registrados en el sistema</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//if ($user-&gt;uid != 0) {</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$items</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'MiPrimerModulo/principal'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'title'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Crear proyecto'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'page callback'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'drupal_get_form'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'page arguments'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MiPrimerModulo_principal_form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'access callback'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'custom_module_access'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">//llamamos a la funcion custom_modulo_access con el parametro gestorproyectos.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'access arguments'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'gestorproyectos'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> MENU_NORMAL_ITEM<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$items</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//}</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Es decir, cada vez que se presenta en pantalla el módulo se llama a una función llamada custom_module_access con el parámetro del rol gestor_de proyectos. El rol gestor_de_proyectos, es un rol que hemos creado en la administración de Drupal y en el que hemos incluido al usuario con el que estamos haciendo las pruebas-</p>
<p>La función custom_module_access sería algo así:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> custom_module_access <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$rol</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> &nbsp;<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/in_array"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$rol</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array_values"><span style="color: #990000;">array_values</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">roles</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> &nbsp;<span style="color: #009900;">&#40;</span><a href="http://www.php.net/in_array"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'administrator'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array_values"><span style="color: #990000;">array_values</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">roles</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Vale, la comparación es bastante mala y se podría programar mucho mejor, pero es una forma sencilla de definir que tanto los administradores como los que pertenezcan al grupo gestor_de_proyectos podrán usar el módulo.</p>
<p>El código completo <a href='http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2011/08/MiPrimerModuloControlAcceso.zip'>MiPrimerModuloControlAcceso</a>.</p>
<p>No debemos olvidar que Drupal puede integrarse con un servidor LDAP, por lo que podemos integrar los grupos de acceso a este módulo como grupos de LDAP o, como en este ejemplo, con grupos locales.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=56</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creación de módulos en drupal 7.x con navegación de pantallas</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=51</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=51#comments</comments>
		<pubDate>Fri, 26 Aug 2011 08:45:54 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=51</guid>
		<description><![CDATA[La ventaja de los gestores de contenido es que nos ofrecen ya resueltas operaciones complejas como la gestión de usuarios y de contenidos, además de darnos una serie de herramientas para poder ampliar esas funcionalidades. Muchas veces sólo es necesaria la instalación de un módulo que, una vez configurado, nos solucione el problema. A veces, [...]]]></description>
			<content:encoded><![CDATA[<p>La ventaja de los gestores de contenido es que nos ofrecen ya resueltas operaciones complejas como la gestión de usuarios y de contenidos, además de darnos una serie de herramientas para poder ampliar esas funcionalidades.</p>
<p>Muchas veces sólo es necesaria la instalación de un módulo que, una vez configurado, nos solucione el problema. A veces, sin embargo, es necesario llegar un poco más lejos y debemos ser nosotros quien desarrollemos esos módulos.</p>
<p>Para Drupal tenemos una <a title="Creatging Drupal 7.x modules" href="http://drupal.org/node/361112" target="_blank">mini guía sobre el desarrollo de módulos</a> que cubre bastantes aspectos básicos, pero no sobre algunos más complejos.</p>
<p><em><strong>En el caso que nos ocupa queremos desarrollar un módulo desde cero que permita navegar a través de varios formularios (la mayoría de módulos han sido pensados para hacer operaciones sencillas que no necesitan formularios, ya que muestran la información en la barra de opciones).</strong></em></p>
<p>Toda la complejidad del asunto gira en torno al hook del menú:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> MiPrimerModulo_menu<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//$user-&amp;gt;uid == 0 son los usuarios no registrados en el sistema</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>uid <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$items</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'MiPrimerModulo/principal'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'title'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'Crear proyecto'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'page callback'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'drupal_get_form'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'page arguments'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MiPrimerModulo_principal_form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'access callback'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> MENU_NORMAL_ITEM<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$items</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Y la función a la que se llama desde el menú, en este caso de nombre MiPrimerModulo_principal_form, que en vez de limitarse a mostrar el formulario, se encarga de hacer un uso ingenioso de las variables:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_num'</span><span style="color: #009900;">&#93;</span><br />
<span style="color: #666666; font-style: italic;">//Valores de los campos de la página 1</span><br />
<span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_values'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><br />
<span style="color: #666666; font-style: italic;">//Valores de los campos de la página 2</span><br />
<span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_values'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><br />
<span style="color: #666666; font-style: italic;">//Guardamos los valores de la página 2</span><br />
<span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_values'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'values'</span><span style="color: #009900;">&#93;</span></div></div>
<p><em>Esas variables nos indican en todo momento en que punto de la navegación nos encontramos y, lo que es mejor, los valores que se han ido guardando (para poder volver hacia atrás sin perder el contenido, y también para recopilar la información al final del proceso).</em></p>
<p>En esta función, que es el punto al que volvemos después de cada formulario, debemos definir que formulario presentamos:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> MiPrimerModulo_principal_form <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;</span><span style="color: #000088;">$form_state</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Display page 2 if $form_state['page_num'] == 1</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_num'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #000088;">$form_state</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_num'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> MiPrimerModulo_opcion1_form <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">,</span> <span style="color: #000088;">$form_state</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// En otro caso estamos en la página 1.</span></div></div>
<p><strong>Además, el módulo funcionando crearía una estructura sencilla en la base de datos (que no se usa pero he puesto como ejemplo de uso), y un entrada en el menú principal disponible para todos los usuarios</strong>:</p>

<a href='http://www.elartistadelalambre.net/bluethinking/?attachment_id=52' title='ModuloInstalado'><img width="150" height="150" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2011/08/ModuloInstalado-150x150.png" class="attachment-thumbnail" alt="ModuloInstalado" title="ModuloInstalado" /></a>
<a href='http://www.elartistadelalambre.net/bluethinking/?attachment_id=53' title='Modulo funcinando'><img width="150" height="150" src="http://www.elartistadelalambre.net/bluethinking/wp-content/uploads/2011/08/Modulo-funcinando-150x150.png" class="attachment-thumbnail" alt="Modulo funcinando" title="Modulo funcinando" /></a>

<p><strong>Se puede descargar el código completo <a href="http://www.elartistadelalambre.net/bluethinking/?attachment_id=50" title="Código fuente del módulo" target="_blank">aquí</a></strong>. Ese código, y otros ejemplos, se pueden encontrar en este enlace, pero no son ejemplos completos como este que se ha desarrollado aquí.</p>
<p>En el código adjunto también se encuentra el fichero module.install que proporciona la manera de crear el esquema de la base de datos al instalar el módulo. Si en algunas de las pruebas no se genera bien el esquema, debemos desinstalar (no deshabilitar) el módulo para que Drupal entienda que lo hemos borrado del todo y volver a instalarlo (para que Drupal vuelva a leer el module.install). Si sólo se deshabilita, Drupal no vuelve a leer el module.install.</p>
<p>Otro ejemplo sobre la creación de módulos puede verse <a href="http://franruano.tipoffsecurity.com/2011/05/02/crear-un-modulo-en-drupal-7-iv/" title="crear módulo en drupal 7" target="_blank">aquí</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=51</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Combinar el comando tar con pipe</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=47</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=47#comments</comments>
		<pubDate>Tue, 09 Aug 2011 11:45:38 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Trucos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[tar]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=47</guid>
		<description><![CDATA[A veces cuando queremos copiar grandes cantidades de información el comando CP puede ser bastante lento. Si hacemos la copia combinándola con un tar &#8220;al vuelo&#8221;, los resultados suelen ser bastante mejores: (asumimos como /Datos/Origen el directorio de origen, y /Datos/Destino como directorio destino) cd /Datos/Origen tar cf - * &#124; &#40;cd /Datos/Destino ; tar [...]]]></description>
			<content:encoded><![CDATA[<p>A veces cuando queremos copiar grandes cantidades de información el comando CP puede ser bastante lento.</p>
<p>Si hacemos la copia combinándola con un tar &#8220;al vuelo&#8221;, los resultados suelen ser bastante mejores:</p>
<p>(asumimos como /Datos/Origen el directorio de origen, y /Datos/Destino como directorio destino)</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>Datos<span style="color: #000000; font-weight: bold;">/</span>Origen<br />
<span style="color: #c20cb9; font-weight: bold;">tar</span> cf - <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>Datos<span style="color: #000000; font-weight: bold;">/</span>Destino ; <span style="color: #c20cb9; font-weight: bold;">tar</span> xf - <span style="color: #7a0874; font-weight: bold;">&#41;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=47</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Instalar un Windows 7 o Windows Server 2008 desde una memoria USB</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=45</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=45#comments</comments>
		<pubDate>Tue, 09 Aug 2011 11:37:21 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Trucos]]></category>
		<category><![CDATA[Windows Server]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=45</guid>
		<description><![CDATA[En ocasiones no nos es posible tener acceso a una unidad de DVD para instalar el sistema operativo, pero sí tenemos disponible una memoria USB. La solución entonces es hacer la instalación desde el propio USB: (Si asumimos como unidad de DVD la unidad d: y la f: como unidad de USB) Abrimos una venta [...]]]></description>
			<content:encoded><![CDATA[<p>En ocasiones no nos es posible tener acceso a una unidad de DVD para instalar el sistema operativo, pero sí tenemos disponible una memoria USB.</p>
<p>La solución entonces es hacer la instalación desde el propio USB:</p>
<p>(Si asumimos como unidad de DVD la unidad d: y la f: como unidad de USB)</p>
<p>Abrimos una venta de MSDOS (ejecutar CMD) o buscarla en el menú de Windows.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">d:\boot\bootsect.exe <span style="color: #000000; font-weight: bold;">/</span>NT60 f: <span style="color: #000000; font-weight: bold;">/</span>force <span style="color: #000000; font-weight: bold;">/</span>mbr<br />
xcopy d:\<span style="color: #000000; font-weight: bold;">*</span>.<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">/</span>s <span style="color: #000000; font-weight: bold;">/</span>e <span style="color: #000000; font-weight: bold;">/</span>f h:\</div></div>
<p>Nota: En algunos sitios el comando bootsec lo ejecutan sin las dos últimas opciones. Esto da problemas (al menos en nuestro caso)</p>
<p>El último paso es arrancar el equipo y desde la BIOS indicar que debe arrancar desde el USB.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=45</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sistema linux cifrado: partición de datos y swap</title>
		<link>http://www.elartistadelalambre.net/bluethinking/?p=42</link>
		<comments>http://www.elartistadelalambre.net/bluethinking/?p=42#comments</comments>
		<pubDate>Thu, 10 Feb 2011 10:55:36 +0000</pubDate>
		<dc:creator>bluethinking</dc:creator>
				<category><![CDATA[Comandos]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[luks]]></category>

		<guid isPermaLink="false">http://www.elartistadelalambre.net/bluethinking/?p=42</guid>
		<description><![CDATA[Hay cosas peores que el robo de un ordenador portátil, por ejemplo el robo de un portátil con toda la documentación dentro. No sólo por el robo de la información, que si hacemos copias de seguridad (ejem, ejem) debería ser mínimo, sino por la desagradable sensación de dejar parte de nuestra vida en manos de [...]]]></description>
			<content:encoded><![CDATA[<p>Hay cosas peores que el robo de un ordenador portátil, por ejemplo el robo de un portátil con toda la documentación dentro. No sólo por el robo de la información, que si hacemos copias de seguridad (ejem, ejem) debería ser mínimo, sino por la desagradable sensación de dejar parte de nuestra vida en manos de un desconocido, eso sin contar las claves, documentos y demás que si sean vitales para nuestro trabajo.</p>
<p>En Linux existe una solución muy sencilla para evitar ese problema, y es cifrar todas las particiones que sean elegidas para guardar los datos (generalmente el home del usuario, aunque es conveniente hacerlo con el swap). </p>
<p>El cifrado de particiones no afecta al rendimiento general del equipo, y ha sido pulido hasta convertirse en una opción estándar que suele ser ofrecida incluso durante la instalación, aunque siempre es mejor hacer las cosas a mano hasta saber cual es el funcionamiento real.</p>
<p>Eso es lo que intentaré explicar en los siguientes puntos. Como configurar un sistema linux ya instalado para que tenga cifradas las particiones de datos.</p>
<p></p>
<h1>Creando la partición</h1>
<p>
Como trabajamos con una distribución basada en Red Hat (CentOS), las particiones de datos suelen estar guardadas en un contenedor LVM. En mi caso sigo sus reglas y en la instalación hago un contenedor LVM con todo el espacio que me queda para datos y sólo creo un partición swap. Luego, según lo voy necesitando lo voy asignando.</p>
<p>Creamos una partición de 10G para el home de los usuarios:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">&#123;</span>bst<span style="color: #000000; font-weight: bold;">@</span>procserver00<span style="color: #7a0874; font-weight: bold;">&#125;</span>~: lvm<br />
lvm<span style="color: #000000; font-weight: bold;">&amp;</span>gt; lvcreate VolGroup00 <span style="color: #660033;">-L</span> 9.75G<br />
<span style="color: #666666; font-style: italic;">#Lo crea como lvol0. Se puede cambiar de nombre:</span><br />
lvrename VolGroup00 lvol0 LogVolHome</div></div>
<p></p>
<h1>Borrar la información y cifrar los datos</h1>
<p></p>
<p>Si el disco es nuevo o no nos importan mucho los datos que había dentro podemos saltar este paso. En caso contrario es buena idea no dejar ni rastro de los datos antiguos, aunque puede llevar bastante tiempo:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome <span style="color: #007800;">bs</span>=1G <span style="color: #007800;">count</span>=<span style="color: #000000;">0</span> <span style="color: #007800;">seek</span>=<span style="color: #000000;">8</span></div></div>
<p>En este punto tenemos la partición lista para ser cifrada. Lo haremos con un cifrado AES de 256 bits, suele ser la opción recomendada aunque si miramos el manual podemos ver los tipos de cifrados soportados.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cryptsetup <span style="color: #660033;">--verify-passphrase</span> <span style="color: #660033;">--verbose</span> <span style="color: #660033;">--hash</span>=sha256 <span style="color: #660033;">--cipher</span>=aes-cbc-essiv:sha256 <span style="color: #660033;">--key-size</span>=<span style="color: #000000;">256</span> luksFormat <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome<br />
<br />
WARNING<span style="color: #000000; font-weight: bold;">!</span><br />
========<br />
This will overwrite data on <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome irrevocably.<br />
<br />
Are you sure? <span style="color: #7a0874; font-weight: bold;">&#40;</span>Type uppercase <span style="color: #c20cb9; font-weight: bold;">yes</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>: YES<br />
Enter LUKS passphrase:<br />
Verify passphrase:</div></div>
<p>Acabamos de crear una partición cifrada dentro de nuestro contenedor LVM. Ahora intentaremos trabajar sobre ella:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cryptsetup luksOpen <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome homecr<br />
Enter LUKS passphrase <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome:<br />
key slot <span style="color: #000000;">0</span> unlocked.<br />
Command successful.</div></div>
<p>Con estos comandos hemos abierto la partición cifrada y la hemos llamado homecr. Ya podemos trabajar sobre ella, aunque antes es necesario formatearla:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mkfs.ext3 <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>homecr</div></div>
<p>Este dispositivo funciona exactamente como cualquier unidad de disco. Es decir, podemos habilitarla y empezar a trabajar sobre ella:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>homecr <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span></div></div>
<p><span id="more-42"></span></p>
<p></p>
<h1>Montaje automático de la partición en el arranque</h1>
<p>
Obviamente la forma de trabajar presentada en el punto anterior no es nada práctica: cada vez que arrancase el sistema deberíamos entrar en modo texto y escribir en la consola:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome<br />
cryptsetup luksOpen <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome homecr<br />
<span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>homecr <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span></div></div>
<p>Antes de poder entrar en modo gráfico y comenzar a trabajar con un usuario.</p>
<p>Lo ideal sería que el sistema, de forma automática y transparente, localizase la partición cifrada, nos pidiese la clave y, además, nos la montase en el directorio indicado.</p>
<p>Los dos primeros pasos se solucionan editando el fichero /etc/crypttab</p>
<p>Que, según el man, tiene el siguiente formato:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mappingname &nbsp; &nbsp; &nbsp; &nbsp;devicename &nbsp; &nbsp; &nbsp; &nbsp;password_file_path &nbsp; &nbsp; &nbsp; &nbsp;options</div></div>
<p>En el ejemplo anterior, que teníamos una partición LVM llamada /dev/mapper/VolGroup00-LogVolHome sobre la que mapeábamos un dispositivo llamado homecr, quedaría:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">homecr&nbsp; <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolHome</div></div>
<p>No hemos rellenado el campo password_file_path ni el campo de opciones. El primero porque queremos que el sistema, durante el arranque, se detenga un momento para pedirnos la contraseña, y el segundo por que es lo suficientemente inteligente para detectar el tipo de cifrado (a no ser que probemos opciones exóticas)</p>
<p>El último paso es decirle al sistema que monte de forma automática el dispositivo creado en la partición home. Sí, eso se hace en el /etc/fstab, donde añadiremos la siguiente línea:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>homecr &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">/</span>home &nbsp; &nbsp; &nbsp; &nbsp;ext3 &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">0</span> <span style="color: #000000;">0</span></div></div>
<p>Si salvamos el fichero y reiniciamos la máquina esta, durante el arranque, se detendrá para pedirnos la contraseña del dispositivo cifrado. Una vez introducida de forma correcta continuará el arranque normal y nos dejará el sistema con la partición home cifrada lista para ser usada.</p>
<p></p>
<h1>Partición swap y temporal</h1>
<p></p>
<p>Todo esto funciona bien para particiones de datos. Sin embargo existen particiones especiales de las que solemos pedir otro tipo de comportamiento. Me refiero a las particiones de tipo swap y los directorios temporales. No habría ningún problema en tratar estas dos particiones como dos particiones normales y cifrarlas según el procedimiento anterior, sin embargo suele ser habitual iniciarlas al arranque totalmente vacías. Para ello lo que se hace es generar una clave de forma automática leyéndola del /dev/urandom (lo cual de forma implícita destruye el contenido).</p>
<p>En /etc/crypttab:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cryptedSwap &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolSwap &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>urandom &nbsp; &nbsp; &nbsp; &nbsp;swap</div></div>
<p>En /etc/fstab:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>cryptedSwap &nbsp; &nbsp; &nbsp; swap &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;swap &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">0</span> <span style="color: #000000;">0</span></div></div>
<p>Y, algo parecido podríamos hacer con el tmp:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cryptedTmp &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>VolGroup00-LogVolSwap &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>urandom &nbsp; &nbsp; &nbsp; &nbsp;tmp</div></div>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mapper<span style="color: #000000; font-weight: bold;">/</span>cryptedTmp &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">/</span>tmp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ext3 &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">0</span> <span style="color: #000000;">0</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.elartistadelalambre.net/bluethinking/?feed=rss2&#038;p=42</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

