G A C E T A   D E   L I N U X
...haciendo a Linux un poco más divertido!
perl-en-una-línea del mes: La Aventura de los Archivos Extraviados
Por Ben Okopnik
Traducción al español por Isaac Uribe
el día 15 de Julio 2003, para La Gaceta de Linux
 
 - "Bien, bien, ¿Qué es lo que tenemos aquí?"

Woomert Foonly había estado trabajando con su colección de aviones raros, y estaba concentrándose en los finos detalles del flujo en la compuerta del turbocargador y en las altísimas presiones del combustible en los jets. No obstante, el ligero ruido detrás de él, que anunciaba a un visitante (Woomert habría distinguido el caminar de Frink) ocasionó que se diera la vuelta brúscamente, y aplicara una de las llaves de su repertorio Pentjak Silat al intruso, causando al último parecer como un extraño pretzel (si es que los pretzels pueden producir tantos quejidos). La pregunta le fué hecha calmadamente, con tonos mesurados, pero había un obvio tono de "Esto puede hacerse más doloroso, así que no desperdicies mi tiempo" que hizo cambiar el quejumbroso gemir del intruso por palabras ligeramente más útiles.

 - "¡Oh! estoy muy apenado, Sr. Foonly, lo siento, ¡pero tenía que venir a verlo! Me encuentro con este serio problema, y ¡Ay! Realmente no quería que alguien se enterara, y por eso utilicé la puerta trasera, no quise entrar por el frente porque alguién pudiera haberse dado cuenta, en realidad no quise que nadie saliera lastimado, ¡en verdad!

Woomert suspiró y soltó a su asustada presa, y ayudó al extraño a componerse, ya que era claro que él no hubiera podido por sí mismo. Sonrió para sí brevemente; las antiguas habilidades aún no se habían perdido, y seguirían ahí cuando en verdad las necesitara.

 - "Para la próxima vez, sugiero que llame o mande un correo electrónico con anticipación -comentó Foonly-. La banda Zigamorph, a quienes atraparon gracias a mi ayuda al resolver el misterio del "Bank Round-Downs", está fuera de prisión y han hecho una serie de amenzas criminales; puedo manejarlos, a ellos y a sus planes, pero no es precisamente una buena idea sorprenderme de esa manera en estos momentos -o en cualquier otro momento, como sea, ¿Quién eres?"

El visitante se sacudió e hizo un esfuerzo por alizar su chaqueta arrugada, ya que ahora parecía una prenda recién tomada de la lavandería, se rendió después de unos momentos y agitó la cabeza fúnebremente.

 - "Bien... mi nombre es Willard Furrfu. Verá Sr. Foonly, estoy trabajando como capturista, pero he estado intentando aprender algo de programación después del trabajo, usted sabe, para mejorar. Logré instalar un compilador de C en mi directorio personal, y he estado experimentando con ciclos... hasta que conseguí en verdad estropear las cosas. Espero que pueda ayudarme, ya que si alguien se entera de lo que sucedió, ¡estoy frito!"

Mientras Willard hablaba, Woomert rapidamente limpió su mesa de trabajo y cerró la cubierta del motor del aeroplano. Al terminar, guió a su invitado fuera del hangar y hacia dentro de la casa. Una vez dentro, empezó a preparar té, se sentó y examinó a su invitado.

 - "Dime exactamente lo que pasó."

 - "Bueno... No estoy muy seguro. Quería practicar algo de lo que había aprendido: haciendo una copia de un archivo existente con un nombre aleatorio, una linea a la vez; desafortunadamente, parece que la función que escribí se cicló en la rutina de creación de archivo así como en la línea de copiado. Me tomó unos cuantos segundos darme cuenta de esto y matar el proceso, pero ahora hay cientos y cientos de archivos en mi directorio personal, ¡donde antes no había más cincuenta o sesenta! Peor aún, dado el formato de nombres del esquema original, es imposible saber cuáles son - los nombres se ven aleatorios desde un principio - y no puedo imaginarme cuánto me tomaría hacer esto a mano, es imposible. No me importa decirle a usted, Sr. Foonly, that que estoy en pánico. Intenté escribir alguna clase de función que hiciera un ciclo en los archivos y los comparara para deshacerse de los duplicados, pero me dí cuenta a la mitad del camino, que en primer lugar no tengo un nivel como para realizar algo por el estilo y que además es una cantidad horrible de comparaciones - Nunca lo terminaría a tiempo. Mañana en la mañana, cuando se supone que capture mayor información en los archivos, estaré en serios problemas - He oido de usted, y de cómo ha ayudado a la gente con problemas de programación. Por favor Sr. Foonly - ¡No sé lo que haré si usted se niega!"

 - "Hmm. Interesante." Woomert olfateó el té preparándose y cerró la tapa, después se sentó de nuevo. "¿Qué tipo de archivos son estos?"

 - "Archivos de texto, todos ellos."

 - "¿Son muy grandes?"

 - "Bueno, todos están por debajo de los 100KB, la mayoría de ellos por debajo de los 50KB. Pensé en tomar archivos del mismo tamaño, pero resulta que varios de ellos son diferentes a pesar de tener el mismo tamaño."

 - "¿Te importa el nombre del archivo, mientras que los mismos sean únicos?"

 - "Pero por supuesto que no, de ninguna manera - cuando sean los archivos originales, puedo revisarlos e identificarlos en unos cuantos minutos. Sr Foonly, ¿quiere decir que ve una solución para este problema? ¿es esto posible?"

Woomert encogió los hombros.

 - "Primero echemos un vistazo al problema, ¿le parece? No tiene sentido adivinar, hasta que tengamos los hechos a la mano. De cualquier modo, no se vé tan difícil. Tienes razón al decir que comparar el archivo actual con cada uno de los demás archivos sería un proceso muy largo; mañana en la mañana sería probablemente insuficiente, a menos de que fuera una máquina poderosa..." Ante la mirada ansiosa, Woomert prosiguió. "No supuse que lo fuera, por la manera en que suena. Bien hagamos un intento, ¿De qué manera podemos consultarlo desde aquí?"

A Willard se iluminó el rostro.

 - "He seguido sus casos en los documentos, Sr. Foonly, y sé que prefiere SSH. De hecho, acabo de convencer a nuestro administrador de sistemas para hacer el cambio - habíamos estado usando telnet, y después de mostrarle algo de lo que había dicho usted sobre telnet (tuve que censurarlo un poco, por supuesto), se convenció, e incluso cambió el sistema de administración."

 - "Nada mal, Willard. Estás empezando con el pie derecho - de alguna manera, sin embargo, sin importar el lenguaje que escojas para aprender, debes ser cuidadoso. Debemos mantenerte alejado de sistemas de producción. Nunca sabes los efectos negativos que pudiera haber, así que mientras seas al menos semi-competente... Te sugiero que hables con tu administrador de sistemas sobre la posibilidad de configurar "chroot jail", donde puedes experimentar de manera segura, sin poner en peligro el ambiente de producción."

  - "Lo haré, Sr. Foonly, tan pronto como regrese a la empresa. ¿Cree usted que arreglar el problema nos tome mucho tiempo?"

 - "Veamos. Utiliza la máquina que está por allí para iniciar una sesión, y veremos lo que sucede. Como sabes, - ``ls -l|head -1'' nos arrojá como resultado ``total 27212'', que nos muestra cuántos archivos tienes. Hasta ahora todo bien. Ahora - antes que nada, ¿Qué nombre le diste al archivo que hizo esto?"

 - "Mm, ``randfile''. Todavía tengo el código por aquí..."

 - "Eso está bien, porque vamos a eliminarlo. ¡Odiaría que se repitiera la catástrofe justo después de que lo arreglemos! Ahora, veamos... sip, al parecer todo es texto, no hay problema. Otro punto en tu favor, Willard: Un pronto reporte de los problemas es una buena práctica, y al parecer estás usándola bien. Correcto ahora..."

perl -MDigest::MD5=md5 -0we'@a=@ARGV;@h{map{md5($_)}<>}=@a;@b=values%h;print"@b\n"' *
Los dedos de Woomert volaban sobre el teclado mientras surgía "perl-en-una-línea". Después de cerca de un minuto, sonrió pero se mantuvo con la mirada fija en la pantalla - la cual, después de a  otro segundo o dos, imprimió una lista de archivos.

 - "Aquí tienes, Willard - una lista con nombres únicos. Me complace que tu sistema tuviera el módulo que necesitaba - es uno bastante común, pero no estaba seguro. Cópialos a otro directorio, borra todos los demas, pónlos de regreso, y habrás terminado. Podrías incluso automatizar el proceso escribiendo..." Una sonrisa traviesa apareció en el rostro de Woomert por un segundo. "...un programa. Bien, un script de consola de una línea, como sea."

 - "¿¿¿Eso... eso es todo???" Willard miró la pantalla, con una mezcla de esperanza y escepticismo. Rápidamente creó una carpeta en "/tmp", copió los archivos cuidadósamente utilizando "cp" y comillas inversas a ambos lados del script de Woomert, y los leyó utilizando "less". Cuando se volvió hacia Woomert unos segundos después, su cara estaba radiante de felicidad.

 - "Sr. Foonly... me ha salvado. Prometo ser más cuidadoso de ahora en adelante, y hablaré con nuestro administrador acerca de instalar un -¿Cómo dijo que se llamaba, un ``chroot jail''? - como sea, estoy muy agradecido. ¿Cómo podré pagarle?"

 - "Bueno, podrías traerme grandes sacos de oro y joyas..." Woomert se detuvo y se rió de la mirada de desaliento del joven hombre, "sólo bromeaba. Tenga una sugerencia para tí, que podrías meditar. Al parecer tienes aptitudes para la programación - le eché un vistazo a tu "randfile.c", y excepto por los errores obvios, lo estabas haciendo bastante bien. Te aconsejaría tomar unos cursos de programación en la vocacional local, para empezar - cuando uno se esta iniciando, es difícil llegar a resultados concretos, especialmente en lenguajes como C y C++ que tienen tantas, tantas trampas y tropezaderos para los desprevenidos. Son muy buenos para sus objetivos específicos, pero se necesita algo de entrenamiento formal para entender el trasfondo de lo que estás haciendo, o terminas con un desastre."

 - "La vocacional." Willard parecía golpeado por la idea. "No lo había pensado; Solo sabía que la universidad era demasiado cara para mí, y que quería aprender de alguna manera. Gran idea, Sr. Foonly; ¡Daré una vuelta por allá y veré qué es lo que se necesita, tan pronto como pueda! Es más, creo que dejaré la práctica de C por un tiempo, hasta que entienda el trasfondo de todo esto... ¿Y qué hay acerca de lo estaba usando?, he oido algo de PERL anteriormente."

 - "Bueno, no se llama ``PERL'', ya que no es una abreviación, aunque algunas personas han inventado diferentes orígenes de la palabra [1]. Es ``Perl'' si nos referimos al lenguaje, y "perl" para el nombre del ejecutable. Y sí, creo que aprender Perl sería una buena idea, especialmente si piensas complementarlo con estudio de C; te darás cuenta de que es sencillo aprender, y de que mantenerte haciéndolo permitirá que seas competente muy pronto, además te evitarás muchos de las dificultade por lidiar con los problemas de lenguajes obsoletos, como manejo de memoria y punteros erróneos. Sugeriría que escojas un buen libro - ten cuidado, hay muchos libros póbremente escritos sobre Perl, definitivamente te recomiendo "Learning Perl'' by Randal Schwartz and Tom Phoenix - y que lo estudies. Una o dos tardes de eso y estarás listo para meterte en problemas aún más eficiéntemente de como le hiciste con tu programa en C." Woomert sonrió con complicidad al sonrojado Willard, quien finalmente sonrió también.

 - "Bueno, en realidad he leido un poco sobre esto antes, pero sobre lo difícil que es leer, o de entender Perl, así que estaba un poco predispuesto para estudiarlo". Willard se veía avergonzado, "después de ver su código, ahora sé a lo que se referían. ¿Es siempre así de complicado?"

 - "Para nada. Utilizo estos perl-en-una-linea porque domino bastante bien Perl, y porque no es código que esté dejando para que alguien más utilice. De hecho, si te interesa, puedo explicarte lo que hice y mostrarte como se vería en un script."

- "Sr. Foonly, estaría encantado. Después de todo, estaré aprendiendo esto - ¿que mejor manera que empezar que oir su explicación?"

Sonriendo, Woomert extrajo su teléfono celular de su autoextraible, resistente al agua e inoxidable sujetor que reciéntemente había inventado.

"Espera un minuto mientras nos alcanza Frink. Le gustará ves esto también, estoy seguro. Hola, ¿Frink? Tengo un caso por acá... en realidad, está resuelto ya, pero quizás quieras ver el método. ¿Diez minutos? Nos vemos entonces." Regresó el teléfono al sujetor. "Tomemos algo de este excelente brebaje que inventé mientras nos alcanza Frink. Es un excelente y fino té Nepalés de altura que tiene un excelente sabor. ¿Una taza?..."

Un rato después, Frink llegó, viéndose como si se hubiera perdido un gran proyecto. También se veía molesto, pero Woomert inmediátamente se adelantó:

 - "Frink, sé que prefieres participar en mis casos; yo también lo prefiero así, ya que ahora vas a ser mi compañero. Sin embargo, hay ocasiones cuando un caso sale furtívamente en tu camino y de pronto te encuentras tan involucrado aún antes de que puedas pestañar, y tienes que atar todos los cabos suelto antes que el problema se cicle y se multiplique en un número enorme de variables." Ambos contemplaban a Willard quien estaba infructuósamente intentando frenar su risa. "Willard, por ejemplo, entiende perfectamente lo que quiero decir. De cualquier manera, ten por sentado que no te habría dejado fuera si no estuviera el elemento tiempo invoucrado; al final, pude resolver el problema rapidamente, pero siempre hubo la posibilidad de que necesitára cada segundo disponible. Permíteme explicarte y tú mismo podrás juzgar."

Unos cuantos instantes bastaron para poner al tanto a Frink, quien sonreía y miraba a Woomert.

 - "Gracias, Woomert. Me sentía fuera del juego, y aprecio que me explicaras. Una buena comunicación entre compañeros es importante, ¿no es asì?, esa es una buena lección por sí misma." Ambos sonrieron uno al otro antes de volverse a la computadora.

 - "Adelante Frink. Puedes desarmar esta para Willard? Estaré justo aquí, así que si te trabas, mantendremos el ritmo."

- "Muy bien, veamos." Frink miró fíjamente el código en pantalla, y frunció el ceño de concentración.

perl -MDigest::MD5=md5 -0we'@a=@ARGV;@h{map{md5($_)}<>}=@a;@b=values%h;print"@b\n"' *

 - "Correcto. ``-MDigest::MD5=md5'' es bastante sencillo: estás cargando el módulo ``Digest::MD5'' e importantdo el método ``md5'' de él, justo como hablamos anteriormente. ``-we'', sabemos acerca de habilitar los mensajes preventivos y de ejecutar lo que sigue como un script. ``-0'', ahora... ¡ah!, Ya recuerdo - un número como opción es el código octal de la definición de fin-de-línea para los archivos que estemos leyendo. ¡Ah, ya entiendo! estás deshabilitando el EOL, de manera que "engulles" archivos completas, uno a la vez. ¿Correcto?"

Woomert aplaudió silenciósamente; Frink sonrió y volvió a la pantalla frente a él.

 - "A continuación. Copiaste @ARGV justo al inicio - esto guarda la lista de archivos para volverlos a usar, ya que @ARGV cambiará conforme leamos archivos. Más aún, no es necesario utilizar el procedimiento BEGIN para hacer esto ya que no estamos ciclando el script en su totalidad, como tendríamos que hacer con un operador ``-n'' o ``-p''. Sigamos... uh, lo siguiente se pone complicado. Admitó que me has confundido, aunque puedo explicar lo que hiciste más adelante: copiaste los valores en el "hash" %h a un arreglo de manera que pudieras utilizar el mecanismo "pretty print" de Perl: un arreglo en comillas dobles se imprime con espacios entre sus elementos, que es lo que querías. El ``\n'' al final también merece un comentario: normalmente utilizarías el parámetro ``-l'' en la línea de comandos, lo que añadiría un EOL a cada línea que fuera impresa, pero habías redefinido EOL como nulo, por lo que no habría sido de utilidad - por lo que tuviste que utilizar ``\n''. ¿Cómo estuvo?"

 - "Bien hecho compañero, ahora viene el resto de la historia - ¿Estás siguiéndonos, Willard? Interrúmpenos si no entiendes algo. Mientras Frink se quema el coco, por así decirlo, así que habla y aprende en el proceso, eres nuestro crítico, en el proceso: si algo no está explicado claramente nos gustaría oir que es lo que tienes que decir."

Willard se aclaró la garganta.

 - "Bien - en realidad, he entendido todo hasta ahora. Me imagino que un "módulo" es como una librería en C, y que ``Digest::MD5'' probablemente tiene que ver con la generación de sumas MD5 - he oido al respecto, pero no estoy muy seguro de lo que significa, fuera de esto, creo que lo he entendido."

Frink habló.

 - "Un compendio MD5, o suma (A veces llamado también "hash"), es utilizado como una clave única para cadenas, normalmente el contenido de archivos. Si recibes un archivo y su suma MD5, puedes revisarlo con herramientas comunes para asegurarte que el archivo no ha cambiado de alguna manera generando un nuevo hash MD5 y comparándolo con la suma que recibiste. De hecho, aquí tengo una pequeña utilería que utilizo para hacer eso precísamente, en lugar de tener que compararlas visualmente:

#!/usr/bin/perl # "md5check" created by Ben Okopnik on Wed Apr 9 21:27:05 EDT 2003 use warnings; use strict; use Digest::MD5; die "Usage: ", $0 =~ /([^\/]+)$/, " <filename> <md5_hex_digest>\n" unless @ARGV == 2; open Fh, shift or die "Can't open: $!\n"; my $d = Digest::MD5 -> new -> addfile( *Fh ) -> hexdigest; print "MD5 sums ", ($d eq shift) ? "" : "*DO NOT* ", "match.\n"

Nos hace más fácil el proceso, eso creo. De cualquier manera, regresando a la explicación de Woomert... Me gustaría saber como ejecutó este truco particularmente."

Woomert sonrió a su compañero.

 - "Obviamente estas hablando acerca del trozo ``@h{map{md5($_)}<>}=@a'', ¿correcto? Sí, este es un poco complejo si no estás acostumbrado a él. Lo que hice fué utilizar una sección del hash para llenar %h - es un pequeño modismo para tener en cuenta. Si piensas en la manera como se estructura un hash:
llave1 => valor1
llave2 => valor2
llave3 => valor3
llave4 => valor4
llave5 => valor5
...
verás que es un arreglo de llaves que apuntan a un arreglo de valores. Por consiguiente, podemos tratarlo como tal; por ejemplo, podemos crear un hash del alfabeto y sus posiciones numéricas diciendo
@alpha{ 1 .. 26 } = "a" .. "z";             # El operador de rango, '..' genera las dos listas
El ``@'' antes del nombre simplemente indica el contexto de lo que está pasando; lo que nos dice acerca del tipo de variable que estamos utilizando son las llaves que siguen al nombre de la variable - que indica un hash. Si tuviéramos corchetes, sabríamos que tenemos una sección de un arreglo en su lugar.

Aún así, eso no explica complétamente todo - así que aquí viene el resto. Ya que estamos leyendo el contenido del archivo de una sentada, lo que significa que tenemos un archivo completo útil cuando leemos el manipulador de archivo especial ``<>'', simplemente utilicé la función map para hacer un ciclo implícito sobre el archivo - y correr la rutina ``md5()'' sobre cada uno de estos bloques de texto. Tendría que haber hecho algo complétamente diferente si no hubieran sido archivos de texto - un archivo que tuviera un nulo habría echado a perder la cuenta - pero eran de texto. Mi margen de seguridad era el operador ``-w'' que habría avisado si tuvieramos un hash desbalanceado - que es lo que habría ocurrido si hubiera un nulo en algún lugar. Así que, creé un hash de llaves que eran compendios MD5 de los contenidos de los archivos, y asigné el arreglo de nombres de archivo que creé anteriormente como valores. Es importante notar que los hash no almacenan los pares de valores en el orden en que fueron asignados... pero eso no era un factor importante aquí, ya que estabamos tratando con arreglos que están almacenados en orden.

Ahora, Frink, Dejaré esta para tí. ¿Porqué esto produce una lista de nombres de archivo únicos?"

Frink se rió.

 - "Gracias, Woomert. En realidad me sé este. Ya que las llaves de un hash son únicas - los valores no tienen que serlo necesariamente, pero las llaves si - cada vez que añadías un par valor/llave que ya existía en el hash, el valor antiguo para esta llave simplemente se sobreescribía. ¡Voila! - una lista única. De hecho, ahora puedo poner todo esto en un script... mmm, tendré que cambiar unas cuantas cosas, ya que la manera en que lo hiciste está implícita en el mecanismo que utilizaste:


#!/usr/bin/perl -w use Digest::MD5 qw/md5/; { local $/; # EOL indefinido temporalmente @n=@ARGV; $count = 0; while ( <> ){ $llave = md5($_); value = $n[$count++]; $uniq{ $llave } = $valor; } } print"$_ " for values %uniq
Después de unos instantes, Willard repentínamente habló.

 - "Digamos, creo que entendí todo esto, ¡Ahora no se ve nada complicado! Solo que no estoy seguro de las variables ``$_'' y ``$/'', pero creo que puedo averiguarlo - ¿Perl tiene una buena documentación, verdad?"

Frink y Woomert se rieron, Frink respondió al pregunta.

 - "La mejor. De hecho, todo viene con Perl - y está comentado en cada módulo que instales. Todo es accesible a travez del programa ``perldoc''; comienza leyendo ``perldoc perldoc'', y nunca te encontraràs con la falta de documentación acerca de Perl."

Un rato después, cuando el agradecido Willard iba rumbo a casa y (finalmente) a una noche de descanso, Frink y Woomert se relajaban con una grabación extraña de Burundi Ubuhuba canto-ruidoso acompañado de un piano-de-pulgares y una cítara. Como siempre, la comida que acompañaba la música era deliciosa y apropiada para la ocasión: la comida consistía de "ingelegde vis" finamente cocinado (una receta de pescado picante que Woomert había aprendido en el cabo Malayo) y de "futari" (calabaza y ñames) a un lado, con pan de la Samosa Africana Oriental y salsa picante "piri-piri" para los aventados. Duraznos africanos escogidos cerraban con broche de oro el menú.
De pronto, hubo un fuerte ruido en el exterior, seguido de tales maldiciones que habrían desprendido culquier pintura barata (Providencialmente, Woomert había realizado los acabados exteriores con goma epóxica de alta calidad, por lo que no fueron afectados), y por sirenas policiacas al poco rato.

 - "Ah." Woomert se reclinó sobre el respaldo de su silla despreocupádamente, mientras se deleitaba con el último bocado de un sabroso durazno. "Esos deben haber sido los Zigamorphs. De regreso a prisión por violar su libertad bajo palabra; les habían dicho explícitamente que estuvieran lejos de mi vecindario."

 - "¿Qué fue lo que pasó..., Woomert? Se oyó bastante mal."

 - "Sabía que tarde o temprano vendrían, y preparé una trampa para ellos. Tan solo un programa numérico básico de complementación que lanzaría una excepción "jaula-metálica" cuando detectara un nulo [2]. Alguno de estos días, Frink, los delincuentes se volverán inteligentes, toma nota, es una simple cuestión de evolución. Hata entonces, podemos dormir tranquilos en nuestras camas..."

[1] Larry Wall, el creador de Perl, sugirió "Pathologically Eclectic Rubbish Lister" para aquellos que simplemente no pueden asimilar que Perl no sea un acrónimo. "Practical Extraction and Report Language" también ha sido sugerido para aquellos que tienen que vender la idea de utilizarlo para los administradores, lo cual es bien sabido carece de sentido del humor.


[2] Un zigamorph, de acuerdo a la jerga común, es un caracter hexadecimal 'FF' (11111111). Un complemento numérico de este, sería por supuesto, ceros - un nulo.

 

Ben es un editor para la Gaceta de Linux y miembro del "Answer Gang".

picture Ben nació en Moscú, Rusia en 1962. Se interesó por la electricidad a la edad de seis años --demostrándolo pronto al introducir un tenedor en un enchufe provocando un incencio-- y ha estado inmiscuido en la tecnología desde entonces. Ha trabajado con computadoras desde los primeros tiempos, cuando tenían que ser armadas soldando piezas sobre circuitos impresos y los programas tenían que alcanzar en 4k de memoria. Pagaría bastante dinero de muy buena gana por el tratamiento psicológico que lo pudiera curar de las pesadillas resultantes de esas experiencias.

Las siguientes experiencias de Ben incluyen la creación de software en cerca de una docena de lenguajes, mantenimiento de bases de datos y redes durante el avecinamiento de un huracán, y escribir artículos para revistas que van desde navegación hasta publicaciones tecnológicas. Reciéntemente terminó un viaje de siete años en el Atlántico/Caribe a vela, actualmente está anclado en Baltimore, MD, donde trabaja como instructor técnico para Sun Microsystems.

Ben ha trabajado con Linux desde 1997, y lo excusa debido a su completa falta de interés en emprender la guerra nuclear en partes del Noroeste del Pacífico.


Copyright © 2003, Ben Okopnik. Licencia de copia http://www.linuxgazette.com/copying.html
Publicado en el número 91 de Linux Gazette, Junio 2003