Artículo muy interesante. Preparar una tila, que la verdad que duele:
http://www.outono.net/elentir/2011/05/29/asi-afectara-a-los-blogs-la-ley-mordaza-que-prepara-leire-pajin/
Recopilando pelusillas en mi ombligo con las que, algún día, dominaré el Mundo entero! Muahaahahaha!
martes, 31 de mayo de 2011
domingo, 27 de marzo de 2011
El Mínimo Absoluto que Todos los Desarrolladores Deberían Conocer Sobre Unicode y Codificaciones.
Este artículo pretende ser una traducción más o menos fiel [1] de el artículo de Joel Spolsky. Me ha gustado tanto que me he decidido a traducirlo para hacerlo accesible a todos aquellos que no dominan el inglés, o que prefieren leer en castellano. Es un magnífico texto que todavía hoy sigue vigente. Te recomiendo la lectura, ya seas programador, administrador de sistemas, o simplemente un curioso de la informática.

----------------------------------------------------------------------------------------------
El Mínimo Absoluto que Todos los Desarrolladores Deberían Conocer Sobre Unicode y Codificaciones.
Miércoles, 08 de Octubre de 2003 by Joel Spolsky
Alguna vez te has preguntado acerca de la etiqueta misteriosa "Content-Type"? Ya sabes, la que se supone que debes poner en el HTML y que nunca has sabido realmente que poner?
Alguna vez has recibido un correo de tus amigos de Bulgaria con un asunto igual a "???? ??? ?? ????? ??" ?
Me he molestado al descubrir que muchos desarrolladores no saben realmente como funciona el misterioso mundo de las codificaciones de caracteres, Unicode, etc... Unos años atrás un beta tester de FogBUGZ se estaba preguntando si podría recibir correos en Japonés. Japonés? Ellos escriben correos en Japonés? No tenía ni idea. Cuando miré mas de cerca el componente comercial que estábamos desarrollando en ActiveX para parsear las cabeceras MIME de los e-mails, nos dimos cuenta de que lo estábamos haciendo mal con las codificaciones de caracteres, por lo que tuvimos que reescribir el código de conversión. Cuando miré el código de otra aplicación comercial, también tenia una mala implementación en la codificación de caracteres. Mandé un par de e-mails al desarrollador del paquete, pero el dijo algo así como: "no puedo hacer nada al respecto".
Cuando descubrí que en el lenguaje de programación PHP no se habían tenido en cuenta las condificaciones y que usaba tan solo 8 bits para la codificación de caracteres, haciendo prácticamente imposible el desarrollo de buenas aplicaciones internacionales, pensé: ya es suficiente.
Tengo un anuncio que hacer: si eres un programador y no tienes unos conocimientos mínimos sobre caracteres, tabas de caracteres, codificaciones y Unicode, te voy a pillar y te castigaré haciéndote pelar cebollas durante 6 meses en un submarino. Te juro que te pillaré.
Y algo más:
En este artículo voy a explicar exactamente lo que todos los programadores deberían saber. Todo esto de que "texto en claro = ASCII = caracteres de 8 bits" no está solamente mal, sino que está fatal, y si sigues programando de este modo, no eres mucho mejor que un doctor que no cree en los gérmenes. POR FAVOR, no escribas otra línea de código antes de haber acabado de leer este artículo.
Antes de que empiece, debería advertirte de que si eres una de estas raras personas que sabe algo sobre la internacionalización, vas a encontrar todo lo de este posto un poco "simplificado". Yo estoy intentando establecer un mínimo, para que todo el mundo pueda entender de qué va el tema, y pueda escribir código que tenga alguna oportunidad de funcionar en textos escritos en cualquier lenguaje ( o en otro subset de inglés que no incluya palabras acentuadas ¬¬ ). Y debo advertirte que el tratamiento de caracteres es solo una pequeña parte de lo que conlleva crear software que funcione intencionalmente. Me temo que yo solo puedo escribir artículos sobre una cosa a la vez, o sea que hoy tocan codificaciones de caracteres.
Des de la perspectiva histórica
========================
La manera mas fácil de entender todo esto es ir viéndolo de manera cronológica.
Probablemente estarás pensando que voy a hablar sobre antiguas tablas de caracteres como EBCDIC. Bueno, no voy a hacerlo. EBCDIC no es relevante para tu vida. No tenemos que ir tan atrás en el tiempo.

Volviendo atrás en los tiempos semi-antiguos, cuando Unix fue inventado y K&R estaba escribiendo The C Programming Language, todo parecía muy simple. EBCDIC estaba ya de salida. Los únicos caracteres que importaban eran los caracteres del inglés, con letras no acentuadas. Así se creó el ASCII que eran unas tablas capaces de representar todos los caracteres usando números del 32 al 127. El carácter que se correspondía con el espacio era el 32, la letra "A" se correspondía con el 65, etc. Todo esto se podía guardar perfectamente en 7 bits. La mayoría de ordenadores en estos días usan bytes de 8 bits, entonces no solo podrías almacenar todos los caracteres ASCII, sino que tenías un bit adicional que "sobraba" ( no se usaba ) y que, si querías podías utilizar para tus propios ( y maléficos ) fines. Este bit adicional se utilizó en WordStar para indicar la última letra de una palabra, condenando, así, WordStart a que sólo funcionara en inglés. Los códigos por debajo de 32 se llamaban "unprintables" ( que no se pueden escribir ) y se utilizaban para insultar. Estaba bromeando. Realmente se usaban como caracteres de control, como el 7, que hacía que ordenador emitiese un "beep", y el 12, que se interpretaba por las impresoras como un salto de página, por lo que dejaba de imprimir en la hoja actual y cargaba otra hoja.
Todo esto estaba muy bien. Suponiendo, claro, que fueses de habla inglesa.
Como el código ASCII solo ocupaba 7 bits, mucha gente pensó "caramba, puedo utilizar los código 128 hasta el 255 para almacenar mis cosas". El problema fue que MUCHA gente pensó esto en el mismo momento, pero cada uno tuvo su propia idea de qué debería ir en el espacio de 128 a 255. El IBM-PC creó algo que se llegó a conocer como mapa de caracteres OEM, que contenía caracteres acentuados para los lenguajes Europeos, así como muchos caracteres para dibujar líneas.... barras horizontales, barras verticales, etc... así que tu podías usar estas líneas para dibujar caracteres en la pantalla y hacer cuadros y líneas a tu gusto ( era un recurso para embellecer las aplicaciones de línea de comandos ). Asimismo, cuando la gente empezó a comprar ordenadores fuera de EEUU, se diseñaron muchos tipos diferentes de tablás de caracteres OEM. Cada una de ellas usaba los últimos 128 caracteres para sus propios propósitos. Por ejemplo, en algunos ordenadores el código 130 se mostraba como "é", pero en los ordenadores vendidos en Isael se veía la letra Hebrea Gimel (
), así que si des de Estados Unidos enviaban un documento con la palabra "résumés" los israelitas las recibían como "r
sum
s". En muchos casos, como en Rusia, hubieron muchas ideas sobre qué hacer con los últimos 128 caracteres, por lo que intercambiar documentos en la misma Rusia se convertía en un problema.
Eventualmente, este "libre albedrío" de qué hacer en los últimos 128 caracteres se acabó con el estándar ANSI. En este nuevo estándar, todo el mundo accedió en "qué hacer con estos 128 caracteres". Pero este nuevo método establecía muchos maneras de tratar los últimos 128 caracteres, dependiendo del sitio donde vivieras. Estos sistemas diferentes se llamaron *code pages* (páginas de código). En Israel, por ejemplo, el sistema operativo DOS usaba la página con código 862, mientras que en Grecia usaban la página de códigos 737. O sea, sus tablas de códigos eran igual por debajo de los 128 ( ASCII ), pero eran diferentes por encima de los 128 ( donde se ponían todos aquellos "caracteres divertidos" de cada país o región ). Las versiones de MS-DOS tenían docenas de páginas de códigos, que permitían hacer que un mismo ordenador fuera "multilenguaje", de modo que podían abrir documentos escritos en inglés, islandés o esperanto (usando una tabla de códigos que suportara los tres idiomas al mismo tiempo). Pero qué pasaba si querías usar el hebreo y el griego en el mismo ordenador? Pues que no podías ya que cada uno tenía su tabla de códigos específica, y no había ninguna tabla de códigos "compartida" entre estos dos idiomas.
Mientras tanto en Asia, estaban pasando cosas bastante mas complicadas por el hecho de que los alfabetos asiáticos tienen cientos de carácteres. Ellos lo solucionaron con un sistema muy lioso llamado DBCS, "double byte charse set" en el que _algunas_ letras se guardaban en un byte, otras letras se guardaban en dos bytes. Este sistema te permitía moverte sin problemas hacia "adelante" en un string, pero era realmente complicado moverte "hacia atrás". Por esto los programadores dejaron de usar s++ o s-- y empezaron a usar las funciones de Windows AnsiNext y AnsiPrev para no tener que pelearse con este complicado sistema.
Pero aún así la gente seguía programando de modo que un carácter fuese un byte, y que un carácter tenía 8 bits, lo que significava que "nunca muevas un texto de un ordenador a otro". Pero claro, con la aparición de Internet hubo un sitio muy propicio para intercambiar textos de un ordenador a otro, y todo el tema de las codificaciones se vino abajo. Por suerte se inventó Unicode.
Unicode
=======
Unicode fue el resultado de un gran esfuerzo por crear un solo set de caracteres que incluía cualquier sistema de escritura razonable en el planeta, y algún otro como el Klingon, también. Algunas personas, malentendiendo lo que Unicode es, piensan realmente que es un sistema de 16 bits, donde cada carácter ocupa 16 bits. Esto significaría que con este sistema se podrían escribir hasta 65.536 caracteres. Pero esto no es realmente cierto. Es uno de los mitos mas tontos sobre Unicode, por lo que si creías que que era así, no te sientas mal.
De hecho, Unicode tiene un modo diferente de pensar sobre los caracteres, y tu tienes que entender este modo de pensar, o nada va a tener ningún sentido para ti.
Hasta ahora, hemos asumido que un carácter se guarda en un número determinado de bytes como por ejemplo:
A = 0100 0001
En Unicode, los caracteres se llaman "code point", que son solo un concepto teórico. El cómo un "code point" se representa en memoria o en disco, es otra historia.
En Unicode, la letra A es una idea platónica. Solo está flotando en el aire:
Cualquier letra platónica ( concepto de letra ) en todos los alfabetos, es un número mágico en el consorcio Unicode, que se escribe tal que así: U+0639. Este número mágico es llamado "code point". El U+ significa Unicode y los números son hexadecimal.
No hay un límite real en el número de letras que Unicode puede definir, aún a pesar de que parezca de que solo se utilicen 2 bytes, y por tanto, solo se pueden definir 65535 letras. Esto es otro mito sobre Unicode.
Bien, aquí tenemos una cadena de texto:
que, en Unicode, corresponde a estos cinco puntos de código:
Solo sólo un montón de puntos de código (codepoints). Números, en realidad. Todavía no hemos hablado de cómo guardar esto en memoria o en disco, o cómo representarlo en un mensaje de correo electrónico.
Econdings
=========
Aquí es donde entran los "encodings" (codificaciones).
La primera idea de las codificaciones en Unicode, que nos deja el mito sobre los dos bytes, fué: "ei! vamos a guardar estos números en dos bytes cada uno". Así que "Hello" se convierte en:
Bien? No, demasiado rápido! No podría escribirse como?
Bueno, técnicamente, si. Creo que se podría, y de hecho, los primeros programadores querían ser capaces de guardar los "code points" de Unicode en "high-endian" o "low-endian" en función de si su procesador iba mas rápido en un sistema que en el otro. Entonces la gente estuvo forzada a adoptar la convención bizarra de guardar FE FF al principio de cada texto Unicode; esto se llama Unicode Byte Order Mark ( Marca de orden de bytes Unicode ), y, si tu estabas girando el orden tus bytes de mayor y menor peso, esta marca sería FF FE, así la persona que leyera tu texto sabría si tiene que girar el orden de los bytes o no. Ufff. No todos los textos Unicode tendría la marca de orden al principio, o sea que ya os podéis imaginar los problemas que conllevaría esto.
Durante un tiempo, esto parecía que debería suficiente, pero los programadores se estaban quejando y diciendo: "Ei! Mira todos estos ceros!", ya que ellos eran americanos y estaban mirando texto en inglés. El texto en inglés cumplía la propiedad de que rara vez habían "code points"por encima de U+00FF. También estaban los hippies liberales de California que querían conservar (grrr). Si fueran tejanos, no les habría importado el consumo del doble de memoria para guardar un texto en inglés ( chiste americano ). Pero los cobardes de California no podían soportar la idea de duplicar la cantidad de espacio almacenado para guardar textos. De todos modos habían muchos documentos antiguos por ahí almacenados en ANSI y DBCS. Y que iban a hacer, convertirlos todos? Ellos? Solo por esta razón hubo mucha gente que decidió hacer caso omiso a Unicode durante varios años, y por tanto la cosa empeoró.
Así, se inventó el concepto brillante de UTF-8. UTF-8 fue otro sistema para guardar "code points" en Unicode, pero solo usando 8 bits de memoria. En UTF-8, cada "code point" de 0 a 127 solo se guarda en un solo byte". Solo los "code points" de 128 para arriba se guardan en 2, 3, 4, 5 o 6 bytes.
Esto también tuvo un "efecto secundario" muy bueno en los textos escritos inglés. El texto era exactamente igual en UTF-8, que en ASCII, así que los americanos no verían nada extraño. Solo el resto del mundo debía pasar por el aro. Específicamente "Hello", que es: U+0048 U+0065 U+006C U+006C U+006F, se guardaría como: 48 65 6C 6C 6F!! Exactamente igual como se guardaría en ASCII y ANSI, y en todos los grupos de caracteres OEM del planeta! Ahora bien, si eres tan valiente como para utilizar letras acentuadas, o letras griegas o letras Klingon, tendrás que utilizar varios bytes para almacenar un "code point" único, pero los estadounidenses nunca se darán cuenta de eso.
Hasta ahora te he dicho tres formas de codificación Unicode. Los métodos tradicionales guardalo-en-dos-bytes son llamados UCS-2 ( por que tiene 2 bytes ) o UTF-16 ( porque tiene 16 bytes ), y uno todavía tiene que averiguar si se trata de UCS-2 big-endian o UCS-2 low-endian. Y también tenemos el nuevo y popular estándar UTF-8 que tiene la agradable propiedad de funcionar perfectamente bien con el texto en ingles ( tanto ASCII como ANSI ) y con programas que no tienen ni idea de que existan otras cosas que no sean ASCII.
Hoy en día hay un montón de otras formas de codificar Unicode. Hay algo llamado UTF-7, que se parece mucho a UTF-8 pero que garantiza que el mayor bit va a ser siempre cero. Si tienes, por ejemplo, algún tipo de servidor de correo nazi, que cree que 7 bits son "suficientes, gracias", todavía puedes salir ileso y enviar tus e-mails codificándolos con UTF-7. También hay UCS-4, que guarda cada "code point" en 4 bytes, y tiene la bonita propiedad de que cada "code point" puede ser guardado en el mismo número de bytes, pero, caramba! Incluso la gente de Texas no sería tan osada como para gastar tanta memoria.
De hecho, ahora que estás pensando en la idea platónica que representan los "code points" en Unicode, te puedes dar cuenta que estos "code points" se pueden encodear en cualquier encoding de la "vieja escuela". Por ejemplo, podrías encodear "Hello" ( U+0048 U+0065 U+006C U+006C U+006F ) en ASCII, o el OEM de Grecia, o en la codificación ASCII del Hebreo, o con cualquier codificación anteriormente inventada. Solo con una pega: dejarás de ver algunas letras! Si no existe ningún equivalente para el "code point" de Unicode en el encoding en el que lo estas intentando transformar, normalmente vas a ver el símbolo de pregunta, "?", o quizás puedes llegar a ver el símbolo �. Te suena?
Hay cientos de encodings tradicionales, que solo pueden almacenar ALGUNOS de los "code points" de Unicode. Los "code points" que no tienen una representación en el encoding viejo, se cambian por símbolos de interrogación. Algunos encodings populares en inglés son: Windows-1252 ( el estándar Europeo para Windows 9x ), y el ISO 8859-1 ( también llamado Latin-1 ), también usado por los idiomas del oeste Europeo. Pero intenta almacenar Ruso, o Hebreo en estos encodings, y solo vas a ver un montón de símbolos de interrogación. UTF 7, 8, 16 y 32 tienen la propiedad de poder almacenar cualquier "code point" de manera correcta.
La cosa mas importante sobre los encodings
==========================================
Si has olvidado todo lo que te acabo de explicar, por favor aprende una cosa muy importante. No tiene ningún sentido tener una cadena de texto sin saber que encoding usa. Ya no puedes seguir pensando que "texto claro" es ASCII.
Si tu tienes un texto, en memoria, o en un fichero, o en un e-mail DEBES saber en que encoding ha sido guardado, o no serás capaz de mostrar los caracteres correctamente.
Casi todos los problemas estúpidos "mi web parece un galimatías" o "mi amiga no puede leer mi correo electrónico cuando lleva acentos", se reducen a que un programador ingenuo que no comprendía el simple hecho de que si no me dices como has codificado el texto, ya sea en UTF-8, o ASCII, o ISO-8859-1 o Windows 1252 yo SIMPLEMENTE no puedo mostrar correctamente el texto ( ni saber donde el texto termina )!
¿Dónde podemos preservar la información sobre qué codificación usa el texto que mandamos? Bueno, hay maneras estándar para hacer esto. Por ejemplo, para un correo electrónico, uno espera encontrar en la cabecera un string que ponga:
Para una página web, la idea original era que el servidor web devolviese una cabecera (HTTP) con el Content-Type, ( y no en el HTML ). De manera que uno ya sepa la codificación de la página antes de recibir el HTML.
Esto da problemas. Imagina que tienes un gran servidor web con muchos sitios, y con cientos de páginas con contribuciones de gente de todo el mundo, en diferentes idiomas. Y que todas utilizan la codificación que quiera que use el Microsfot FrontPage. El servidor web no nunca sabrá realmente qué encoding tiene cada archivo, por lo que no podrá mandar una cabecera con el Content-Type.
Sería conveniente que pudieses poner un Content-Type en el HTML donde va el fichero mismo, utilizando algún tipo de tag especial. Por supuesto esto llevó a la locura a los puristas... "¿Cómo se puede leer un fichero HTML hasta que no sepas que codificación lleva?!" Por suerte, casi cada encoding común usa los mismos caracteres entre 32 y 127, entonces siempre podemos empezar a leer HTML sin ver caracteres estaños:
Por lo que el meta tag tiene que estar estar justo después de declarar la sección head ya que, tan pronto como el navegador web vea este tag, va a parar de interpretar la página y volverá a empezar reinterpretando toda la página con el encoding que has especificado.
¿Que hacen los navegadores si no encuentran ningún Content-Type y ningún tag en el header HTML? Internet Exploiter hace algo bastante interesante: intenta adivinar, basado en la frecuencia en la que aparecen algunos bytes en los típicos encodings en diferentes idiomas. Ya que varios encodings de 8 bits intentaban poner sus letras de su idioma nativo entre el rango entre 128 y 255, y ya que todos los idiomas tienen diferentes características de frecuencia en el uso de determinadas letras en texto escrito, se podía adivinar mas o menos el encoding en el que ha sido escrito el texto. Es bastante raro, pero parece funcionar bastante bien para las páginas programadas por ingenuos programadores que necesitarían echarle un vistazo a lo que es el Content-Type de su página web. ¿ Que pasa? Que si no se ajusta bien el encoding ( la detección falla ), y si Internet Exploiter decide que el idioma es coreano, pues el usuario que ha cargado la página no puede entender nada. Esto prueba, creo, la Ley de Postel sobre: "conservador en lo que dices y liberal en lo que aceptas" no es un principio bueno para un trabajo de ingeniería. De todos modos, ¿Qué hace el pobre lector que entra en una página escrita en búlgaro y la ve en coreano? Va al menú View>Encoding y prueba diferentes codificaciones (hay varias docenas de codificaciones en el Este de Europa ), hasta que ve bien el texto. Esto si sabe que puede hacerlo, claro, y mucha gente ni lo sabe.
Para la última versión de CityDesk un sitio de administración web publicado por mi compañía, decidimos internamente utilizar Unicode UCS-2 (dos bytes), que es el tipo nativo de Visual Basic, COM y Windows NT/2000/XP para los tipos de datos string. En C++, declarábamos los strings como wchar_t, en vez de char, y usábamos la función wcs en vez de str. Para crear un literal UCS-2 en C, simplemente poníamos un L antes, así quedaba algo como: L"Hello".
Cuando CityDesk publicó su página, se convirtió todo en UTF-8, que siempre ha sido una codificación muy bien soportada por todos los navegadores. Aquí tenemos el muro de las 29 versiones en las que está ecodeada la página de "Joel on Software", y yo nunca he escuchado a ninguna persona que haya tenido algún problema al visitar mi página.
Este artículo se está haciendo demasiado largo, y me es imposible explicar todo lo relacionado con la codificación de caracteres en Unicode, pero creo que si has leído hasta aquí, has aprendido suficiente como para volver a programar, y usar antibióticos, en vez de sanguijuelas y hechizos.
--------------------------------------------------------------------------------------------------------

[1]: Teniendo en cuenta que mi nivel de inglés es bastante.... humilde. Aún así he hecho un gran esfuerzo para traducir del mejor modo que he podido el artículo. Se aceptan correcciones.
Nota: Se ha usado “cadena de texto” como sinónimo de “string”.
Nota2: Se ha cambiado intencionadamente “Internet Explorer(tm)(r)” por “Internet Exploiter”. Seguramente el autor no estaría de acuerdo con esto. Es un chiste fácil.
Nota 3: Si te ha gustado el artículo y eres un blogger, agradecería que creases un post mencionando el al artículo original ( o hacia esta traducción, o ambos ). Un mundo con mejor comprensión sobre el Unicode, es un mundo mejor. Gracias. ;)

----------------------------------------------------------------------------------------------
El Mínimo Absoluto que Todos los Desarrolladores Deberían Conocer Sobre Unicode y Codificaciones.
Miércoles, 08 de Octubre de 2003 by Joel Spolsky
Alguna vez te has preguntado acerca de la etiqueta misteriosa "Content-Type"? Ya sabes, la que se supone que debes poner en el HTML y que nunca has sabido realmente que poner?
Alguna vez has recibido un correo de tus amigos de Bulgaria con un asunto igual a "???? ??? ?? ????? ??" ?
Me he molestado al descubrir que muchos desarrolladores no saben realmente como funciona el misterioso mundo de las codificaciones de caracteres, Unicode, etc... Unos años atrás un beta tester de FogBUGZ se estaba preguntando si podría recibir correos en Japonés. Japonés? Ellos escriben correos en Japonés? No tenía ni idea. Cuando miré mas de cerca el componente comercial que estábamos desarrollando en ActiveX para parsear las cabeceras MIME de los e-mails, nos dimos cuenta de que lo estábamos haciendo mal con las codificaciones de caracteres, por lo que tuvimos que reescribir el código de conversión. Cuando miré el código de otra aplicación comercial, también tenia una mala implementación en la codificación de caracteres. Mandé un par de e-mails al desarrollador del paquete, pero el dijo algo así como: "no puedo hacer nada al respecto".
Cuando descubrí que en el lenguaje de programación PHP no se habían tenido en cuenta las condificaciones y que usaba tan solo 8 bits para la codificación de caracteres, haciendo prácticamente imposible el desarrollo de buenas aplicaciones internacionales, pensé: ya es suficiente.
Tengo un anuncio que hacer: si eres un programador y no tienes unos conocimientos mínimos sobre caracteres, tabas de caracteres, codificaciones y Unicode, te voy a pillar y te castigaré haciéndote pelar cebollas durante 6 meses en un submarino. Te juro que te pillaré.
Y algo más:
** NO ES TAN DIFÍCIL **
En este artículo voy a explicar exactamente lo que todos los programadores deberían saber. Todo esto de que "texto en claro = ASCII = caracteres de 8 bits" no está solamente mal, sino que está fatal, y si sigues programando de este modo, no eres mucho mejor que un doctor que no cree en los gérmenes. POR FAVOR, no escribas otra línea de código antes de haber acabado de leer este artículo.
Antes de que empiece, debería advertirte de que si eres una de estas raras personas que sabe algo sobre la internacionalización, vas a encontrar todo lo de este posto un poco "simplificado". Yo estoy intentando establecer un mínimo, para que todo el mundo pueda entender de qué va el tema, y pueda escribir código que tenga alguna oportunidad de funcionar en textos escritos en cualquier lenguaje ( o en otro subset de inglés que no incluya palabras acentuadas ¬¬ ). Y debo advertirte que el tratamiento de caracteres es solo una pequeña parte de lo que conlleva crear software que funcione intencionalmente. Me temo que yo solo puedo escribir artículos sobre una cosa a la vez, o sea que hoy tocan codificaciones de caracteres.
Des de la perspectiva histórica
========================
La manera mas fácil de entender todo esto es ir viéndolo de manera cronológica.
Probablemente estarás pensando que voy a hablar sobre antiguas tablas de caracteres como EBCDIC. Bueno, no voy a hacerlo. EBCDIC no es relevante para tu vida. No tenemos que ir tan atrás en el tiempo.

Volviendo atrás en los tiempos semi-antiguos, cuando Unix fue inventado y K&R estaba escribiendo The C Programming Language, todo parecía muy simple. EBCDIC estaba ya de salida. Los únicos caracteres que importaban eran los caracteres del inglés, con letras no acentuadas. Así se creó el ASCII que eran unas tablas capaces de representar todos los caracteres usando números del 32 al 127. El carácter que se correspondía con el espacio era el 32, la letra "A" se correspondía con el 65, etc. Todo esto se podía guardar perfectamente en 7 bits. La mayoría de ordenadores en estos días usan bytes de 8 bits, entonces no solo podrías almacenar todos los caracteres ASCII, sino que tenías un bit adicional que "sobraba" ( no se usaba ) y que, si querías podías utilizar para tus propios ( y maléficos ) fines. Este bit adicional se utilizó en WordStar para indicar la última letra de una palabra, condenando, así, WordStart a que sólo funcionara en inglés. Los códigos por debajo de 32 se llamaban "unprintables" ( que no se pueden escribir ) y se utilizaban para insultar. Estaba bromeando. Realmente se usaban como caracteres de control, como el 7, que hacía que ordenador emitiese un "beep", y el 12, que se interpretaba por las impresoras como un salto de página, por lo que dejaba de imprimir en la hoja actual y cargaba otra hoja.
Todo esto estaba muy bien. Suponiendo, claro, que fueses de habla inglesa.
Como el código ASCII solo ocupaba 7 bits, mucha gente pensó "caramba, puedo utilizar los código 128 hasta el 255 para almacenar mis cosas". El problema fue que MUCHA gente pensó esto en el mismo momento, pero cada uno tuvo su propia idea de qué debería ir en el espacio de 128 a 255. El IBM-PC creó algo que se llegó a conocer como mapa de caracteres OEM, que contenía caracteres acentuados para los lenguajes Europeos, así como muchos caracteres para dibujar líneas.... barras horizontales, barras verticales, etc... así que tu podías usar estas líneas para dibujar caracteres en la pantalla y hacer cuadros y líneas a tu gusto ( era un recurso para embellecer las aplicaciones de línea de comandos ). Asimismo, cuando la gente empezó a comprar ordenadores fuera de EEUU, se diseñaron muchos tipos diferentes de tablás de caracteres OEM. Cada una de ellas usaba los últimos 128 caracteres para sus propios propósitos. Por ejemplo, en algunos ordenadores el código 130 se mostraba como "é", pero en los ordenadores vendidos en Isael se veía la letra Hebrea Gimel (
Eventualmente, este "libre albedrío" de qué hacer en los últimos 128 caracteres se acabó con el estándar ANSI. En este nuevo estándar, todo el mundo accedió en "qué hacer con estos 128 caracteres". Pero este nuevo método establecía muchos maneras de tratar los últimos 128 caracteres, dependiendo del sitio donde vivieras. Estos sistemas diferentes se llamaron *code pages* (páginas de código). En Israel, por ejemplo, el sistema operativo DOS usaba la página con código 862, mientras que en Grecia usaban la página de códigos 737. O sea, sus tablas de códigos eran igual por debajo de los 128 ( ASCII ), pero eran diferentes por encima de los 128 ( donde se ponían todos aquellos "caracteres divertidos" de cada país o región ). Las versiones de MS-DOS tenían docenas de páginas de códigos, que permitían hacer que un mismo ordenador fuera "multilenguaje", de modo que podían abrir documentos escritos en inglés, islandés o esperanto (usando una tabla de códigos que suportara los tres idiomas al mismo tiempo). Pero qué pasaba si querías usar el hebreo y el griego en el mismo ordenador? Pues que no podías ya que cada uno tenía su tabla de códigos específica, y no había ninguna tabla de códigos "compartida" entre estos dos idiomas.Mientras tanto en Asia, estaban pasando cosas bastante mas complicadas por el hecho de que los alfabetos asiáticos tienen cientos de carácteres. Ellos lo solucionaron con un sistema muy lioso llamado DBCS, "double byte charse set" en el que _algunas_ letras se guardaban en un byte, otras letras se guardaban en dos bytes. Este sistema te permitía moverte sin problemas hacia "adelante" en un string, pero era realmente complicado moverte "hacia atrás". Por esto los programadores dejaron de usar s++ o s-- y empezaron a usar las funciones de Windows AnsiNext y AnsiPrev para no tener que pelearse con este complicado sistema.
Pero aún así la gente seguía programando de modo que un carácter fuese un byte, y que un carácter tenía 8 bits, lo que significava que "nunca muevas un texto de un ordenador a otro". Pero claro, con la aparición de Internet hubo un sitio muy propicio para intercambiar textos de un ordenador a otro, y todo el tema de las codificaciones se vino abajo. Por suerte se inventó Unicode.
Unicode
=======
Unicode fue el resultado de un gran esfuerzo por crear un solo set de caracteres que incluía cualquier sistema de escritura razonable en el planeta, y algún otro como el Klingon, también. Algunas personas, malentendiendo lo que Unicode es, piensan realmente que es un sistema de 16 bits, donde cada carácter ocupa 16 bits. Esto significaría que con este sistema se podrían escribir hasta 65.536 caracteres. Pero esto no es realmente cierto. Es uno de los mitos mas tontos sobre Unicode, por lo que si creías que que era así, no te sientas mal.
De hecho, Unicode tiene un modo diferente de pensar sobre los caracteres, y tu tienes que entender este modo de pensar, o nada va a tener ningún sentido para ti.
Hasta ahora, hemos asumido que un carácter se guarda en un número determinado de bytes como por ejemplo:
A = 0100 0001
En Unicode, los caracteres se llaman "code point", que son solo un concepto teórico. El cómo un "code point" se representa en memoria o en disco, es otra historia.
En Unicode, la letra A es una idea platónica. Solo está flotando en el aire:
A
Esta platónica A es diferente de B, y diferente de a, pero igual a A, y A, y A. La es idea que A en el tipo de letra Times Roman es lo mismo que A en el tipo de fuente Helvetica, pero diferente de "a" en minúscula. Esto no parece que tenga que causar mucha controversia, pero en algunos lenguajes, determinar lo que realmente una letra es puede ser complicado. Por ejemplo en Alemán la letra ß es una letra real o es otro modo de escribir ss? Si una letra cambia, por el hecho de estar escrita al final de una palabra, es la misma letra? Los hebreos dicen que si. Los arábigos dicen que no. De todos modos, la gente inteligente de el consorcio de Unicode, se han estado preguntando todo esto durante la última década, acompañado por un gran debate político. Por esto tu no debes preocuparte por todo esto. Ellos ya lo han calculado todo ya.Cualquier letra platónica ( concepto de letra ) en todos los alfabetos, es un número mágico en el consorcio Unicode, que se escribe tal que así: U+0639. Este número mágico es llamado "code point". El U+ significa Unicode y los números son hexadecimal.
No hay un límite real en el número de letras que Unicode puede definir, aún a pesar de que parezca de que solo se utilicen 2 bytes, y por tanto, solo se pueden definir 65535 letras. Esto es otro mito sobre Unicode.
Bien, aquí tenemos una cadena de texto:
Hello
que, en Unicode, corresponde a estos cinco puntos de código:
U+0048 U+0065 U+006C U+006C U+006F
Solo sólo un montón de puntos de código (codepoints). Números, en realidad. Todavía no hemos hablado de cómo guardar esto en memoria o en disco, o cómo representarlo en un mensaje de correo electrónico.
Econdings
=========
Aquí es donde entran los "encodings" (codificaciones).
La primera idea de las codificaciones en Unicode, que nos deja el mito sobre los dos bytes, fué: "ei! vamos a guardar estos números en dos bytes cada uno". Así que "Hello" se convierte en:
00 48 00 65 00 6C 00 6C 00 6F
Bien? No, demasiado rápido! No podría escribirse como?
48 00 65 00 6C 00 6C 00 6F 00 ?
Bueno, técnicamente, si. Creo que se podría, y de hecho, los primeros programadores querían ser capaces de guardar los "code points" de Unicode en "high-endian" o "low-endian" en función de si su procesador iba mas rápido en un sistema que en el otro. Entonces la gente estuvo forzada a adoptar la convención bizarra de guardar FE FF al principio de cada texto Unicode; esto se llama Unicode Byte Order Mark ( Marca de orden de bytes Unicode ), y, si tu estabas girando el orden tus bytes de mayor y menor peso, esta marca sería FF FE, así la persona que leyera tu texto sabría si tiene que girar el orden de los bytes o no. Ufff. No todos los textos Unicode tendría la marca de orden al principio, o sea que ya os podéis imaginar los problemas que conllevaría esto.
Durante un tiempo, esto parecía que debería suficiente, pero los programadores se estaban quejando y diciendo: "Ei! Mira todos estos ceros!", ya que ellos eran americanos y estaban mirando texto en inglés. El texto en inglés cumplía la propiedad de que rara vez habían "code points"por encima de U+00FF. También estaban los hippies liberales de California que querían conservar (grrr). Si fueran tejanos, no les habría importado el consumo del doble de memoria para guardar un texto en inglés ( chiste americano ). Pero los cobardes de California no podían soportar la idea de duplicar la cantidad de espacio almacenado para guardar textos. De todos modos habían muchos documentos antiguos por ahí almacenados en ANSI y DBCS. Y que iban a hacer, convertirlos todos? Ellos? Solo por esta razón hubo mucha gente que decidió hacer caso omiso a Unicode durante varios años, y por tanto la cosa empeoró.
Así, se inventó el concepto brillante de UTF-8. UTF-8 fue otro sistema para guardar "code points" en Unicode, pero solo usando 8 bits de memoria. En UTF-8, cada "code point" de 0 a 127 solo se guarda en un solo byte". Solo los "code points" de 128 para arriba se guardan en 2, 3, 4, 5 o 6 bytes.
Esto también tuvo un "efecto secundario" muy bueno en los textos escritos inglés. El texto era exactamente igual en UTF-8, que en ASCII, así que los americanos no verían nada extraño. Solo el resto del mundo debía pasar por el aro. Específicamente "Hello", que es: U+0048 U+0065 U+006C U+006C U+006F, se guardaría como: 48 65 6C 6C 6F!! Exactamente igual como se guardaría en ASCII y ANSI, y en todos los grupos de caracteres OEM del planeta! Ahora bien, si eres tan valiente como para utilizar letras acentuadas, o letras griegas o letras Klingon, tendrás que utilizar varios bytes para almacenar un "code point" único, pero los estadounidenses nunca se darán cuenta de eso.Hasta ahora te he dicho tres formas de codificación Unicode. Los métodos tradicionales guardalo-en-dos-bytes son llamados UCS-2 ( por que tiene 2 bytes ) o UTF-16 ( porque tiene 16 bytes ), y uno todavía tiene que averiguar si se trata de UCS-2 big-endian o UCS-2 low-endian. Y también tenemos el nuevo y popular estándar UTF-8 que tiene la agradable propiedad de funcionar perfectamente bien con el texto en ingles ( tanto ASCII como ANSI ) y con programas que no tienen ni idea de que existan otras cosas que no sean ASCII.
Hoy en día hay un montón de otras formas de codificar Unicode. Hay algo llamado UTF-7, que se parece mucho a UTF-8 pero que garantiza que el mayor bit va a ser siempre cero. Si tienes, por ejemplo, algún tipo de servidor de correo nazi, que cree que 7 bits son "suficientes, gracias", todavía puedes salir ileso y enviar tus e-mails codificándolos con UTF-7. También hay UCS-4, que guarda cada "code point" en 4 bytes, y tiene la bonita propiedad de que cada "code point" puede ser guardado en el mismo número de bytes, pero, caramba! Incluso la gente de Texas no sería tan osada como para gastar tanta memoria.
De hecho, ahora que estás pensando en la idea platónica que representan los "code points" en Unicode, te puedes dar cuenta que estos "code points" se pueden encodear en cualquier encoding de la "vieja escuela". Por ejemplo, podrías encodear "Hello" ( U+0048 U+0065 U+006C U+006C U+006F ) en ASCII, o el OEM de Grecia, o en la codificación ASCII del Hebreo, o con cualquier codificación anteriormente inventada. Solo con una pega: dejarás de ver algunas letras! Si no existe ningún equivalente para el "code point" de Unicode en el encoding en el que lo estas intentando transformar, normalmente vas a ver el símbolo de pregunta, "?", o quizás puedes llegar a ver el símbolo �. Te suena?
Hay cientos de encodings tradicionales, que solo pueden almacenar ALGUNOS de los "code points" de Unicode. Los "code points" que no tienen una representación en el encoding viejo, se cambian por símbolos de interrogación. Algunos encodings populares en inglés son: Windows-1252 ( el estándar Europeo para Windows 9x ), y el ISO 8859-1 ( también llamado Latin-1 ), también usado por los idiomas del oeste Europeo. Pero intenta almacenar Ruso, o Hebreo en estos encodings, y solo vas a ver un montón de símbolos de interrogación. UTF 7, 8, 16 y 32 tienen la propiedad de poder almacenar cualquier "code point" de manera correcta.
La cosa mas importante sobre los encodings
==========================================
Si has olvidado todo lo que te acabo de explicar, por favor aprende una cosa muy importante. No tiene ningún sentido tener una cadena de texto sin saber que encoding usa. Ya no puedes seguir pensando que "texto claro" es ASCII.
El texto claro (plain text) no existe.
Si tu tienes un texto, en memoria, o en un fichero, o en un e-mail DEBES saber en que encoding ha sido guardado, o no serás capaz de mostrar los caracteres correctamente.
Casi todos los problemas estúpidos "mi web parece un galimatías" o "mi amiga no puede leer mi correo electrónico cuando lleva acentos", se reducen a que un programador ingenuo que no comprendía el simple hecho de que si no me dices como has codificado el texto, ya sea en UTF-8, o ASCII, o ISO-8859-1 o Windows 1252 yo SIMPLEMENTE no puedo mostrar correctamente el texto ( ni saber donde el texto termina )!
¿Dónde podemos preservar la información sobre qué codificación usa el texto que mandamos? Bueno, hay maneras estándar para hacer esto. Por ejemplo, para un correo electrónico, uno espera encontrar en la cabecera un string que ponga:
Content-Type: text/plain; charset="UTF-8"
Para una página web, la idea original era que el servidor web devolviese una cabecera (HTTP) con el Content-Type, ( y no en el HTML ). De manera que uno ya sepa la codificación de la página antes de recibir el HTML.
Esto da problemas. Imagina que tienes un gran servidor web con muchos sitios, y con cientos de páginas con contribuciones de gente de todo el mundo, en diferentes idiomas. Y que todas utilizan la codificación que quiera que use el Microsfot FrontPage. El servidor web no nunca sabrá realmente qué encoding tiene cada archivo, por lo que no podrá mandar una cabecera con el Content-Type.
Sería conveniente que pudieses poner un Content-Type en el HTML donde va el fichero mismo, utilizando algún tipo de tag especial. Por supuesto esto llevó a la locura a los puristas... "¿Cómo se puede leer un fichero HTML hasta que no sepas que codificación lleva?!" Por suerte, casi cada encoding común usa los mismos caracteres entre 32 y 127, entonces siempre podemos empezar a leer HTML sin ver caracteres estaños:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Por lo que el meta tag tiene que estar estar justo después de declarar la sección head ya que, tan pronto como el navegador web vea este tag, va a parar de interpretar la página y volverá a empezar reinterpretando toda la página con el encoding que has especificado.
¿Que hacen los navegadores si no encuentran ningún Content-Type y ningún tag en el header HTML? Internet Exploiter hace algo bastante interesante: intenta adivinar, basado en la frecuencia en la que aparecen algunos bytes en los típicos encodings en diferentes idiomas. Ya que varios encodings de 8 bits intentaban poner sus letras de su idioma nativo entre el rango entre 128 y 255, y ya que todos los idiomas tienen diferentes características de frecuencia en el uso de determinadas letras en texto escrito, se podía adivinar mas o menos el encoding en el que ha sido escrito el texto. Es bastante raro, pero parece funcionar bastante bien para las páginas programadas por ingenuos programadores que necesitarían echarle un vistazo a lo que es el Content-Type de su página web. ¿ Que pasa? Que si no se ajusta bien el encoding ( la detección falla ), y si Internet Exploiter decide que el idioma es coreano, pues el usuario que ha cargado la página no puede entender nada. Esto prueba, creo, la Ley de Postel sobre: "conservador en lo que dices y liberal en lo que aceptas" no es un principio bueno para un trabajo de ingeniería. De todos modos, ¿Qué hace el pobre lector que entra en una página escrita en búlgaro y la ve en coreano? Va al menú View>Encoding y prueba diferentes codificaciones (hay varias docenas de codificaciones en el Este de Europa ), hasta que ve bien el texto. Esto si sabe que puede hacerlo, claro, y mucha gente ni lo sabe.
Para la última versión de CityDesk un sitio de administración web publicado por mi compañía, decidimos internamente utilizar Unicode UCS-2 (dos bytes), que es el tipo nativo de Visual Basic, COM y Windows NT/2000/XP para los tipos de datos string. En C++, declarábamos los strings como wchar_t, en vez de char, y usábamos la función wcs en vez de str. Para crear un literal UCS-2 en C, simplemente poníamos un L antes, así quedaba algo como: L"Hello".
Cuando CityDesk publicó su página, se convirtió todo en UTF-8, que siempre ha sido una codificación muy bien soportada por todos los navegadores. Aquí tenemos el muro de las 29 versiones en las que está ecodeada la página de "Joel on Software", y yo nunca he escuchado a ninguna persona que haya tenido algún problema al visitar mi página.
Este artículo se está haciendo demasiado largo, y me es imposible explicar todo lo relacionado con la codificación de caracteres en Unicode, pero creo que si has leído hasta aquí, has aprendido suficiente como para volver a programar, y usar antibióticos, en vez de sanguijuelas y hechizos.
--------------------------------------------------------------------------------------------------------

[1]: Teniendo en cuenta que mi nivel de inglés es bastante.... humilde. Aún así he hecho un gran esfuerzo para traducir del mejor modo que he podido el artículo. Se aceptan correcciones.
Nota: Se ha usado “cadena de texto” como sinónimo de “string”.
Nota2: Se ha cambiado intencionadamente “Internet Explorer(tm)(r)” por “Internet Exploiter”. Seguramente el autor no estaría de acuerdo con esto. Es un chiste fácil.
Nota 3: Si te ha gustado el artículo y eres un blogger, agradecería que creases un post mencionando el al artículo original ( o hacia esta traducción, o ambos ). Un mundo con mejor comprensión sobre el Unicode, es un mundo mejor. Gracias. ;)
domingo, 25 de julio de 2010
Mi dia a dia... o.... dentro de poco vuelvo.... o ... hecho en falta publicar un post...
Hace ya bastante que no digo nada. La verdad que me gustaría retomar el blog y seguir posteando cosas, a mi parecer, interesantes. Tengo que decir que estoy muy muy liado, ahora mismo. Tengo muchas cosas en marcha y una lista demasiada larga de "thinks to do".
Todavía me esperaré un poquito a volver a retomar el blog, al menos hasta que las cosas se calmen un poco y tenga mas cosas para publicar. Pero para ir haciendo boca os cuento en que ando metido:
Me compré un juguetito: un minibarebone. Es una chulada. Pequeño, silencioso, y de prestaciones moderadas. Cuando tenga tiempo ya os lo presentaré. El caso es que le he instalado un debian y lo tengo como servidor expuesto a internet. Es una gozada. Estoy instalando los servicios más basicos ( ssh, vsftpd, bind9, postfix y dovecot, apache + ssl ) y simulo que se trata de un servidor real que está a producción y que tiene bastantes accesos, osea que no me permito el hecho de reiniciar la máquina a menos que tenga que tocar algo de hardware, o cosas así. Una disfrute, vaya.
Por otra parte, al tener un servidor web propio, tengo que poner algo detrás, aparte de la página estática de saludo, y he pensado en varias cosas. Todas ellas para uso personal, pero van a ser públicas para quien quiera verlo.
Bueno, siento haber vomitado todo esto, pero la verdad que me apetecía escribir algo en el blog, y como es mío...
Saludos y, hasta.... pronto?
Todavía me esperaré un poquito a volver a retomar el blog, al menos hasta que las cosas se calmen un poco y tenga mas cosas para publicar. Pero para ir haciendo boca os cuento en que ando metido:
Me compré un juguetito: un minibarebone. Es una chulada. Pequeño, silencioso, y de prestaciones moderadas. Cuando tenga tiempo ya os lo presentaré. El caso es que le he instalado un debian y lo tengo como servidor expuesto a internet. Es una gozada. Estoy instalando los servicios más basicos ( ssh, vsftpd, bind9, postfix y dovecot, apache + ssl ) y simulo que se trata de un servidor real que está a producción y que tiene bastantes accesos, osea que no me permito el hecho de reiniciar la máquina a menos que tenga que tocar algo de hardware, o cosas así. Una disfrute, vaya.
Por otra parte, al tener un servidor web propio, tengo que poner algo detrás, aparte de la página estática de saludo, y he pensado en varias cosas. Todas ellas para uso personal, pero van a ser públicas para quien quiera verlo.
- La primera y como ejercicio puramente académico, un acortador de urls. Lo estoy haciendo usando pylons y mongo por detrás. De esto haré un pequeño manualillo para quien quiera iniciarse en esto de los sistemas model-view-controller y las bases de datos no relacionales.
- El segundo, y para satisfacer una necesidad personal, estoy haciendo una web ( en pylons también ) que sirve para guardar tus ficheros de configuración de tu PC ( .vimrc, .bashrc, etc..) de modo que tu puedas administrar tus ficheros de configuración, y descargarlos en donde quieras que estés o simplemente para tener un backup. Este proyectito todavía se está gestando, pero cuando tenga algo os lo enseño, lo prometo. Tengo idea de publicarlo bajo una licencia libre, por si alguien quiere usarlo también en su servidor=)
- Y la novedad, en lo que todavía no me he puesto pero no estaré mucho es con los Arduinos. Arduino es una plataforma de hardware libre, donde se puede programar microcontroladores para que hagan determinadas tareas. Desde robots que siguen líneas, apagado y encendido de luces en función de la luz exterior, controles para peceras, o hasta helicópteros a radio control. Una pasada. Todo es software libre y hay una comunidad enorme detrás. Están por llegar, y dentro de poco podré empezar a jugar con ellos. Prometo contar cosas también!
Bueno, siento haber vomitado todo esto, pero la verdad que me apetecía escribir algo en el blog, y como es mío...
Saludos y, hasta.... pronto?
domingo, 16 de mayo de 2010
Virtual Hosts en Apache2, para dummies
[Problema]
Visitante: "Escucha inEdit00!"
inEdit00: "Si, dime!"
Visitante: "Si, mira, que seguí tu manualillo sobre como poner arriba un servidor Apache y he estado haciendo mis cosillas. Ahora ya se HTML y CSS y he empezado a programar en PHP"
inEdit00: "Muy bien. Y cual es el problema?"
Visitante: "Pues mira, te cuento: ahora tengo dos páginas www.mipaginapersonal.com y www.lawebdemicurro.com, y, así como tu me enseñastes en el otro manual, he creado dos entradas en el fichero '/etc/hosts' así:"
127.0.0.1 www.lawebdemicurro.com
127.0.0.1 www.mipaginapersonal.com
Visitante: "Pero claro... estas dos URL's, apuntan hacia el directorio principal del servidor ( /var/www ) y puedo cargar un dominio, o el otro, pero no las dos a la vez!!"
inEdit00: "Bien, este problema que tienes se resuelve con lo que se llaman VirtualHosts. Te explico:"
[Explicación]
Cuando tu entras en una página web con tu navegador, haces una petición al servidor por REST ( órdenes del protocolo HTTP ), por ejemplo, si accedes a la URL: "http://localhost/index.html" realmente estás haciendo una petición al servidor tal que así:
Esto puedes verlo con programas como Wireshark, que se encargan de analizar los paquetes que viajan por la red, a bajo nivel. Bien, que significa esto?
Pues que del host "localhost" quieres el fichero "/index.html", así de simple.
Si haces una petición a la web "http://www.mipaginapersonal.com", haces una petición que sería así:
"GET" singnifica "dame", la barra ("/") significa el directorio principal ( que sería lo mismo que "/index.html" ) y el "Host" es la página que quieres cargar. En este caso, si tienes configurado el fichero "/etc/hosts" como tu me has dicho, te debería dar el contenido del fichero de "/var/www/index.html".
Otro ejemplo: Si vamos a la página web "http://www.lawebdemicurro.com" pasa lo mismo:
Dame el fichero "/" ( que Apache entiende como "/index.html" ) del Host "www.lawebdemicurro.com", y esto devuelve el fichero de "/var/www/index.html". Que es el mismo de antes!
Claro, así no puedes conseguir lo que te propones. Ya que los dos nombres de HOST distintos, apuntan al mismo sitio ( "/var/www" ).
Vale, ahora vamos a crear dos carpetas en el servidor, algo así:
$ sudo mkdir /var/www/mipaginapersonal.com
$ sudo mkdir /var/www/lawebdemicurro.com
Si te fijas, no he puesto las www. Es solo una preferencia personal. Pero son nombres de carpetas, les puedes poner los nombres que quieras. Bien, y ahora lo que haremos será crear un VirtualHost. Que me propongo? Algo así:
Cuando abramos www.mipaginapersonal.com abra la ruta /var/www/mipaginapersonal.com
Cuando abaramos www.laewebdemicurro.com abra la ruta /var/www/lawebdemicurro.com
inEdit00: "Te parece?"
Visitante: "Si, esto es jutsto lo que yo quiero!! Como se hace?"
inEdit00: "Bien, antes hagamos lo siguiente:"
$ sudo gedit /var/www/mipaginapersonal.com
Y añadimos aqui el siguiente texto "Bienvenido a mi página personal!!!". Guardamos y salimos.
$ sudo gedit /var/www/lawebdemicurro.com
Y añadimos aqui el siguiente texto "Bienvenido a la web de mi curro!!!". Guardamos y salimos.
[Virtual Hosts]
Bien, al lío, a por los virtual Hosts. Vamos a crear el siguiente fichero:
$ sudo gedit /etc/apache2/sites-aviable/lawebdemicurro.com
Y en este fichero añadiremos algo tal que así:
<VirtualHost *:80>
ServerName www.lawebdemicurro.com
ServerAlias www.lawebdemicurro.com
DocumentRoot /var/www/lawebdemicurro.com
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
Visitante: "Vale, que significa cada línea?"
inEdit00: Bueno, con esto "" decimos que estamos creando un virtual host que "escuchará" cualquier IP de origen "*" y escucha en el puerto 80.
"ServerName" y "ServerAlias" sirven para especificar el nombre del Host. Este debe ser exactamente el que tu quieras. Y el mismo que hayas puesto en el fichero /etc/hosts, ok?
Y aquí viene la importante "DocumentRoot /var/www/lawebdemicurro.com". Te imaginas lo que es, verdad? Aqui le decimos en que carpeta tiene que buscar cuando intren en el nombre de dominio seleccionado. Capito?
Visitante: "Si, ya veo!"
inEdit00: "Lo demás es un tema de permisos y no me he mirado con profundiad y no acabo de entender bien, la verdad. Tu dejalo igual y debería funcionar perfecto".
Visitante: "Bien, voy a probar!"
inEdit00 Piensa que tienes que hacer lo mismo con tu dominio "www.mipaginapersonal.com", eh?"
Visitante: "Haber, pone como sería la configuración..."
inEdit00: "Justo así"
$ sudo gedit /etc/apache2/sites-aviable/mipaginapersonal.com
<VirtualHost *:80>
ServerName www.mipaginapersonal.com
ServerAlias www.mipaginapersonal.com
DocumentRoot /var/www/mipaginapersonal.com
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
[Puesta apunto]
Visitante: "Bien, he reiniciado el apache como me dijistes ( primero con reload y después con restart ) y no funciona!"
inEdit00: "Yaaaa, prisas! Tate un momento, todavía falta algo. Ejecuta lo siguiente:"
$ cd /etc/apache2/sites-aviable
$ sudo a2ensite mipaginapersonal.com
$ sudo a2ensite lawebdemicurro.com
$ sudo service apache2 reload"
[Final]
inEdit00: "Y ya debería funcionar! Ahora si entras en 'www.lawebdemicurro.com' debería salirte el mensaje:
Bienvenido a la web de mi curro!!!
inEdit00: "Y si entras en 'www.mipaginapersonal.com' te debería mostrar:
Bienvenido a mi página personal!!!
inEdit00: "Bueno, ahora solo hace falta que te copies tus paginas con todos sus directorios dentros de las carpetas correspondientes de '/var/www' y ya está."
Visitante: "Gracias! Es justo lo que quería!"
inEdit00: "Un último detalle! Es muy importante que tengas una entrada en el fichero /etc/hosts para cada domino, de otro modo, si intentas entrar en: 'http://www.mipaginapersonal.com' y no está en el fichero hosts, no se encontrará, y la irá a buscar por DNS a ver si está en Internet (que no está, y si está no es la tuya seguro), ok?"
inEdit00: Fíjate en esto, Si accedes a :"
http://localhost/index.html estás pidiendo /var/www
http://www.lawebdemicurro.com/index.html estás pidiendo /var/www/lawebdemicurro.com/index.html
http://index.html/lawebdemicurro/index.html estás pidiendo /var/www/lawebdemicurro.com/index.html
inEdit00: "Lo entiendes?"
Visitante: "Si, si, claro. Como localhost es el directorio raíz y dentro hay carpetas, yo puedo acceder desde las dos rutas! Pero si quiero acceder desde un ordenador remoto deberé poner la URL completa y no localhost, porque sinó no funcionaría, verdad"
inEdit00: "Exactamente! Ala , hasta la próxima!"
Nota: Recuerta, TÚ eres el visitante, si tienes dudas o necesitas ayuda, no dudes en dejar comentarios!
Visitante: "Escucha inEdit00!"
inEdit00: "Si, dime!"
Visitante: "Si, mira, que seguí tu manualillo sobre como poner arriba un servidor Apache y he estado haciendo mis cosillas. Ahora ya se HTML y CSS y he empezado a programar en PHP"
inEdit00: "Muy bien. Y cual es el problema?"
Visitante: "Pues mira, te cuento: ahora tengo dos páginas www.mipaginapersonal.com y www.lawebdemicurro.com, y, así como tu me enseñastes en el otro manual, he creado dos entradas en el fichero '/etc/hosts' así:"
127.0.0.1 www.lawebdemicurro.com
127.0.0.1 www.mipaginapersonal.com
Visitante: "Pero claro... estas dos URL's, apuntan hacia el directorio principal del servidor ( /var/www ) y puedo cargar un dominio, o el otro, pero no las dos a la vez!!"
inEdit00: "Bien, este problema que tienes se resuelve con lo que se llaman VirtualHosts. Te explico:"
[Explicación]
Cuando tu entras en una página web con tu navegador, haces una petición al servidor por REST ( órdenes del protocolo HTTP ), por ejemplo, si accedes a la URL: "http://localhost/index.html" realmente estás haciendo una petición al servidor tal que así:
GET /index.html
Host: localhost
Esto puedes verlo con programas como Wireshark, que se encargan de analizar los paquetes que viajan por la red, a bajo nivel. Bien, que significa esto?
Pues que del host "localhost" quieres el fichero "/index.html", así de simple.
Si haces una petición a la web "http://www.mipaginapersonal.com", haces una petición que sería así:
GET /
Host: www.mipaginapersonal.com
"GET" singnifica "dame", la barra ("/") significa el directorio principal ( que sería lo mismo que "/index.html" ) y el "Host" es la página que quieres cargar. En este caso, si tienes configurado el fichero "/etc/hosts" como tu me has dicho, te debería dar el contenido del fichero de "/var/www/index.html".
Otro ejemplo: Si vamos a la página web "http://www.lawebdemicurro.com" pasa lo mismo:
GET /
Host: www.lawebdemicurro.com
Dame el fichero "/" ( que Apache entiende como "/index.html" ) del Host "www.lawebdemicurro.com", y esto devuelve el fichero de "/var/www/index.html". Que es el mismo de antes!
Claro, así no puedes conseguir lo que te propones. Ya que los dos nombres de HOST distintos, apuntan al mismo sitio ( "/var/www" ).
Vale, ahora vamos a crear dos carpetas en el servidor, algo así:
$ sudo mkdir /var/www/mipaginapersonal.com
$ sudo mkdir /var/www/lawebdemicurro.com
Si te fijas, no he puesto las www. Es solo una preferencia personal. Pero son nombres de carpetas, les puedes poner los nombres que quieras. Bien, y ahora lo que haremos será crear un VirtualHost. Que me propongo? Algo así:
Cuando abramos www.mipaginapersonal.com abra la ruta /var/www/mipaginapersonal.com
Cuando abaramos www.laewebdemicurro.com abra la ruta /var/www/lawebdemicurro.com
inEdit00: "Te parece?"
Visitante: "Si, esto es jutsto lo que yo quiero!! Como se hace?"
inEdit00: "Bien, antes hagamos lo siguiente:"
$ sudo gedit /var/www/mipaginapersonal.com
Y añadimos aqui el siguiente texto "Bienvenido a mi página personal!!!". Guardamos y salimos.
$ sudo gedit /var/www/lawebdemicurro.com
Y añadimos aqui el siguiente texto "Bienvenido a la web de mi curro!!!". Guardamos y salimos.
[Virtual Hosts]
Bien, al lío, a por los virtual Hosts. Vamos a crear el siguiente fichero:
$ sudo gedit /etc/apache2/sites-aviable/lawebdemicurro.com
Y en este fichero añadiremos algo tal que así:
<VirtualHost *:80>
ServerName www.lawebdemicurro.com
ServerAlias www.lawebdemicurro.com
DocumentRoot /var/www/lawebdemicurro.com
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
Visitante: "Vale, que significa cada línea?"
inEdit00: Bueno, con esto "
"ServerName" y "ServerAlias" sirven para especificar el nombre del Host. Este debe ser exactamente el que tu quieras. Y el mismo que hayas puesto en el fichero /etc/hosts, ok?
Y aquí viene la importante "DocumentRoot /var/www/lawebdemicurro.com". Te imaginas lo que es, verdad? Aqui le decimos en que carpeta tiene que buscar cuando intren en el nombre de dominio seleccionado. Capito?
Visitante: "Si, ya veo!"
inEdit00: "Lo demás es un tema de permisos y no me he mirado con profundiad y no acabo de entender bien, la verdad. Tu dejalo igual y debería funcionar perfecto".
Visitante: "Bien, voy a probar!"
inEdit00 Piensa que tienes que hacer lo mismo con tu dominio "www.mipaginapersonal.com", eh?"
Visitante: "Haber, pone como sería la configuración..."
inEdit00: "Justo así"
$ sudo gedit /etc/apache2/sites-aviable/mipaginapersonal.com
<VirtualHost *:80>
ServerName www.mipaginapersonal.com
ServerAlias www.mipaginapersonal.com
DocumentRoot /var/www/mipaginapersonal.com
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
[Puesta apunto]
Visitante: "Bien, he reiniciado el apache como me dijistes ( primero con reload y después con restart ) y no funciona!"
inEdit00: "Yaaaa, prisas! Tate un momento, todavía falta algo. Ejecuta lo siguiente:"
$ cd /etc/apache2/sites-aviable
$ sudo a2ensite mipaginapersonal.com
$ sudo a2ensite lawebdemicurro.com
$ sudo service apache2 reload"
[Final]
inEdit00: "Y ya debería funcionar! Ahora si entras en 'www.lawebdemicurro.com' debería salirte el mensaje:
Bienvenido a la web de mi curro!!!
inEdit00: "Y si entras en 'www.mipaginapersonal.com' te debería mostrar:
Bienvenido a mi página personal!!!
inEdit00: "Bueno, ahora solo hace falta que te copies tus paginas con todos sus directorios dentros de las carpetas correspondientes de '/var/www' y ya está."
Visitante: "Gracias! Es justo lo que quería!"
inEdit00: "Un último detalle! Es muy importante que tengas una entrada en el fichero /etc/hosts para cada domino, de otro modo, si intentas entrar en: 'http://www.mipaginapersonal.com' y no está en el fichero hosts, no se encontrará, y la irá a buscar por DNS a ver si está en Internet (que no está, y si está no es la tuya seguro), ok?"
inEdit00: Fíjate en esto, Si accedes a :"
http://localhost/index.html estás pidiendo /var/www
http://www.lawebdemicurro.com/index.html estás pidiendo /var/www/lawebdemicurro.com/index.html
http://index.html/lawebdemicurro/index.html estás pidiendo /var/www/lawebdemicurro.com/index.html
inEdit00: "Lo entiendes?"
Visitante: "Si, si, claro. Como localhost es el directorio raíz y dentro hay carpetas, yo puedo acceder desde las dos rutas! Pero si quiero acceder desde un ordenador remoto deberé poner la URL completa y no localhost, porque sinó no funcionaría, verdad"
inEdit00: "Exactamente! Ala , hasta la próxima!"
Nota: Recuerta, TÚ eres el visitante, si tienes dudas o necesitas ayuda, no dudes en dejar comentarios!
Instalando Apache2, para dummies [I]
[Disclaimer]
Hace nade que dije que dejaba el blog, porque no tenía cosas interesantes que contar y falta de tiempo. Dije que escribiría esporádicamente. Pues este fin de semana he tenido algo de tiempo libre y ha salido algo así:
[Introducción]
Esto quiere ser un pequeño manualillo, sobre la instalación Apache. Me gusta empezar con lo básico y después ir subiendo el nivel. (si tengo tiempo)
Bueno, como introducción diremos que Apache es un servidor web que se encarga de servir contenido web, ya sea estático o dinámico. Hay muchos servidores web, pero Apache es uno de los más usados en el mundo, ya sea para webs modestas o para webs con mucho tráfico. Al final el manualillo debes ser capaz de empezar a aprender HTML, PHP, JavaScript o CSS ( o todos a la vez! ).
[Instalación]
Para empezar tenemos que instalar Apache ( y PHP, ya que estamos ):
$ sudo aptitude install apache2 php5 libapache2-mod-php5
Para ver si la instalación ha ido bien abrimos nuestro navegador por defecto y entramos en:
http://localhost
Debería salir una de mis frases preferidas en informática: "It works"
[Configuración y gestión]
Bien, con apache instalado vamos a aprender unas comandas básicas para gestionarlo, antes de ponernos a jugar con el.
Si queremos [apagar/encender/reiniciar] el servicio Apache 2 podemos hacer:
$ sudo service apache2 stop
$ sudo service apache2 start
$ sudo service apache2 restart
Cuando iniciamos el servidor apache, éste carga todas las configuraciones a memória, lo que significa que si hacemos un cambio en los ficheros de configuración ( que se encuentran en /etc/apache2 ), los cambios no tendrán efecto hasta el próximo reinicio de Apache. Es importante acordarse de reiniciar el servicio después de cada modificación! Para no tener que hacer un restart ( que realmente hace un "stop" y para luego hacer un "start" ) tenemos el comando siguiente:
$ sudo service apache2 reload
Este nos cargará los nuevos ficheros de configuración a memória si todo ha ido bien.
Es bastante típico encontrarse con un error tal que así: Editamos el fichero "/etc/apache2/apache2.conf" ( podría ser cualquier otro ) y ponemos una línea nuevo con "ErrorrrLevel debug", que está mal escrito a propósito. Si ahora reiniciamos apache nos da un mensajito, nada amistoso a mi parecer, que reza algo así:
inedit@wally:/etc/apache2$ sudo service apache2 reload
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration
...fail!
Bueno, realmente el servicio sigue corriendo con la configuración antigua, no se ha roto nada. Para comprobar si todos los ficheros de configuración són correctos podemos ejecutar el comando:
$ apache2ctl configtest
El error sería exactamente el mismo que hemos visto antes haciendo un "reload":
inedit@wally:/etc/apache2$ apache2ctl configtest
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration
Es una buena práctica ejecutar este comando para ver si todo se ha configurado correctamente.
Que pasa si hacemos un "sudo service apache2 restart" en un servidor que está en producción? Osea, en un servidor que puede estar teniendo conexiones en el mismo momento que reiniciamos? Pues facil, que los clientes van a recibir un precioso error en su navegador. Y claro, no queremos que esto ocurra. Para ello usa siempre que puedas (es la manera educada de decir que lo uses SIEMPRE) "reload". Pero aún así hay un comando que nos garantiza que no van a perderse las conexiones activas con el servidor. Este comando es:
$ sudo apache2ctl graceful
[Creación de contenido y URL's]
Visitante: "Si, pero yo he entrado en esta página esperando hacer cosas chulas con Apache, y tu solo me hablas de configuracioneees".
inEdit00: "Ya lo seee, impacienteee! Vamos a hacer un brake:"
En la carpeta "/var/www" es donde se almacena el contenido de tu página web. Esto significa que si haces un:
http://localhost/index.html estás accediendo a /var/www/index.html
del mismo modo que si pones:
http://localhost/foo.html estás accediendo a /var/www/foo.html
o que si pones:
http://127.0.0.1/imagenes/foo.jpg estás accediendo a /var/www/imagenes/foo.jpg
Pillas la idea? Es evidente que estos ejemplos no van a funcionar si no tienes los ficheros "index.html", "foo.html" o la carpeta "imágenes" con una foto dentro!
Visitante: "Por que has puesto "localhost" y después '127.0.0.1'? Me confunde."
inEdit00: "127.0.0.1" designa tu ordenador, esto se llama loopback ( prueba a hacer "ifconfig lo" ). Osea, es una IP que "apunta" al mismo equipo. Todos los equipos tienen esta configuración. Como tu tienes instalado el servidor web de Apache en tu equipo, necesitas conectarte a el. Si tienes Apache instalado en un PC fijo y quieres acceder al servidor desde un portátil de tu misma red puedes hacer algo tal que así: deberás buscar tu dirección IP ( ejecuta "ifconfig" para saber que IP local tienes ) que será algo así: 192.168.1.96 ( por ejemplo ). Entonces desde el portátil tienes que poner en el navegador "http://192.168.1.96" y deberías ver "IT WORKS", o lo que contenga el fichero "/var/www/index.html" . Capito?
Visitante: "...o sea, que si en mi portátil pongo la IP del PC fijo puedo ver lo que sirve Apache... interesante"
inEdit00: "Claro, siempre que Apache esté funcionando! A partir de ahora se va a ejecutar como demonio ( en segundo plano ) cada vez que inicies el PC fijo"
Visitante: "Ei! Esto no funciona! He hecho un 'http://localhost' en el portátil y no tira!"
inEdit00: "Claro, alma de cántaro. 'localhost' designa el mismo ordenador. Si pones esto en el portátil, él intenta conectarse a si mismo, y como no tienes ningún servidor web instalado, no funciona! Usa la IP del PC fijo, que para esto están"
Visitante: "..ah, si... tiene sentido."
Visitante: "entiendo. Entonces localhost es parecido a '127.0.0.1'?"
inEdit00: "Acertaste! De hecho quiero que veas esto. Ejecuta el siguiente comando:"
$ cat /etc/hosts
inedit@wally:~/hola$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 linuxjan.ib
127.0.0.1 js.com
192.168.1.36 ofelia
Bueno, a ti te deberían salir menos entradas que a mi. Qué es esto? Pues es una relación clave-valor (IP-nombre). A la izquierda se encuentran las IP's y a la derecha los nombres de dominio. Osea, si te fijas tengo asignados diferentes nombres para "127.0.0.1": "localhost, linuxjan.ib, js.com". Lo que significa que si pongo "linuxjan.ib" en mi navegador, se dirige a '127.0.0.1' igual que si pongo 'localhost'. Esto sirve para no tener que recordar IP's, sino nombres de dominio. Puedes ver que el último elemento de la lista es diferente del resto. Lo que yo hago aqui es decirle que la dirección IP "192.168.1.36" se llama "ofelia", para no tener que acordarme de su IP.
inEdit: "Que te parece?"
Visitante: "osea que si modifico localhost..."
inEdit: "yo no haría esto! Mucho programas usan localhost como referencia a la misma máquina, mejor deja la entrada donde está"
Visitante: "pero puedo añadir elementos a la lista? Como por ejemplo: '127.0.0.1 www.paginapersonaldeprueba.com' ?"
inEdit: "claro. Pruebalo. Cuando accedas a la URL que hayas elegido, deberías ver lo de 'It works!'"
Visitante: "y también puedo añadir '127.0.0.1 www.google.com'?"
inEdit: 'si pero...
Visitante: "Pues voy a probarlo! Mola. Pero... ostia! El google ha dejado de funcionar!!!!"
inEdit: "... pero si pones un nombre de dominio que ya exista, este se resolverá primero con las entradas de tu fichero "/etc/hosts" y si allí no se encuentra, se intentará resolver por DNS. Puedes arreglarlo quitando la línea del fichero."
Visitante: "No, la dejo! Y ahora voy a putear a mi hermana quitándole el google"
inEdit: ".... ¬¬"
(dos minutos después)
Visitante: "No lo entiendo, a mi no me funciona pero a ella si!"
inEdit: "claro, macho! Porque el fichero /etc/hosts está en tu PC, y no en el suyo. Esto solo son cambios locales, si tu pones una entrada así: '127.0.0.1 srv.com' esto solo funcionará en tu PC. Ok?"
Visitante: "Vale, lo entiendo. Los cambios solo son locales."
inEdit. "Exacto. Sigamos:"
A partir de ahora ya puedes empezar a crear tus páginas creando ficheros dentro de "/var/www". También puedes ( debes! ) crear carpetas para distinguir las imágenes de las hojas de estilos ( CSS ) del JavaScript! Si haces esto:
$ sudo mkdir /var/www/sub-folder
Y después creas el fichero "index.html" dentro así:
$ sudo gedit /var/www/sub-folder/index.html
Y pones como contenido algo así:
<>
<>
<>Estamos en sub folder!< /p>
< /body>
< /html>
Nota: he puesto dos espacios antes de cada "tag" para que blogger no lo interprete. Se debe escribir sin doble espaciado.
Para acceder a este contenido puedes hacerlo así ( en tu navegador ):
http://localhost/sub-folder
http://localhost/sub-folder/index.html
Apache se encarga de cargar el fichero "index.html" ( si existe! ) si como nombre de la ruta se le especifica una carpeta.
[Despedida]
Bueno, y esto es todo por hoy. Ahora puedes buscar por internet cualquier manual sobre:
Hace nade que dije que dejaba el blog, porque no tenía cosas interesantes que contar y falta de tiempo. Dije que escribiría esporádicamente. Pues este fin de semana he tenido algo de tiempo libre y ha salido algo así:
[Introducción]
Esto quiere ser un pequeño manualillo, sobre la instalación Apache. Me gusta empezar con lo básico y después ir subiendo el nivel. (si tengo tiempo)
Bueno, como introducción diremos que Apache es un servidor web que se encarga de servir contenido web, ya sea estático o dinámico. Hay muchos servidores web, pero Apache es uno de los más usados en el mundo, ya sea para webs modestas o para webs con mucho tráfico. Al final el manualillo debes ser capaz de empezar a aprender HTML, PHP, JavaScript o CSS ( o todos a la vez! ).
[Instalación]
Para empezar tenemos que instalar Apache ( y PHP, ya que estamos ):
$ sudo aptitude install apache2 php5 libapache2-mod-php5
Para ver si la instalación ha ido bien abrimos nuestro navegador por defecto y entramos en:
http://localhost
Debería salir una de mis frases preferidas en informática: "It works"
[Configuración y gestión]
Bien, con apache instalado vamos a aprender unas comandas básicas para gestionarlo, antes de ponernos a jugar con el.
Si queremos [apagar/encender/reiniciar] el servicio Apache 2 podemos hacer:
$ sudo service apache2 stop
$ sudo service apache2 start
$ sudo service apache2 restart
Cuando iniciamos el servidor apache, éste carga todas las configuraciones a memória, lo que significa que si hacemos un cambio en los ficheros de configuración ( que se encuentran en /etc/apache2 ), los cambios no tendrán efecto hasta el próximo reinicio de Apache. Es importante acordarse de reiniciar el servicio después de cada modificación! Para no tener que hacer un restart ( que realmente hace un "stop" y para luego hacer un "start" ) tenemos el comando siguiente:
$ sudo service apache2 reload
Este nos cargará los nuevos ficheros de configuración a memória si todo ha ido bien.
Es bastante típico encontrarse con un error tal que así: Editamos el fichero "/etc/apache2/apache2.conf" ( podría ser cualquier otro ) y ponemos una línea nuevo con "ErrorrrLevel debug", que está mal escrito a propósito. Si ahora reiniciamos apache nos da un mensajito, nada amistoso a mi parecer, que reza algo así:
inedit@wally:/etc/apache2$ sudo service apache2 reload
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration
...fail!
Bueno, realmente el servicio sigue corriendo con la configuración antigua, no se ha roto nada. Para comprobar si todos los ficheros de configuración són correctos podemos ejecutar el comando:
$ apache2ctl configtest
El error sería exactamente el mismo que hemos visto antes haciendo un "reload":
inedit@wally:/etc/apache2$ apache2ctl configtest
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration
Es una buena práctica ejecutar este comando para ver si todo se ha configurado correctamente.
Que pasa si hacemos un "sudo service apache2 restart" en un servidor que está en producción? Osea, en un servidor que puede estar teniendo conexiones en el mismo momento que reiniciamos? Pues facil, que los clientes van a recibir un precioso error en su navegador. Y claro, no queremos que esto ocurra. Para ello usa siempre que puedas (es la manera educada de decir que lo uses SIEMPRE) "reload". Pero aún así hay un comando que nos garantiza que no van a perderse las conexiones activas con el servidor. Este comando es:
$ sudo apache2ctl graceful
[Creación de contenido y URL's]
Visitante: "Si, pero yo he entrado en esta página esperando hacer cosas chulas con Apache, y tu solo me hablas de configuracioneees".
inEdit00: "Ya lo seee, impacienteee! Vamos a hacer un brake:"
En la carpeta "/var/www" es donde se almacena el contenido de tu página web. Esto significa que si haces un:
http://localhost/index.html estás accediendo a /var/www/index.html
del mismo modo que si pones:
http://localhost/foo.html estás accediendo a /var/www/foo.html
o que si pones:
http://127.0.0.1/imagenes/foo.jpg estás accediendo a /var/www/imagenes/foo.jpg
Pillas la idea? Es evidente que estos ejemplos no van a funcionar si no tienes los ficheros "index.html", "foo.html" o la carpeta "imágenes" con una foto dentro!
Visitante: "Por que has puesto "localhost" y después '127.0.0.1'? Me confunde."
inEdit00: "127.0.0.1" designa tu ordenador, esto se llama loopback ( prueba a hacer "ifconfig lo" ). Osea, es una IP que "apunta" al mismo equipo. Todos los equipos tienen esta configuración. Como tu tienes instalado el servidor web de Apache en tu equipo, necesitas conectarte a el. Si tienes Apache instalado en un PC fijo y quieres acceder al servidor desde un portátil de tu misma red puedes hacer algo tal que así: deberás buscar tu dirección IP ( ejecuta "ifconfig" para saber que IP local tienes ) que será algo así: 192.168.1.96 ( por ejemplo ). Entonces desde el portátil tienes que poner en el navegador "http://192.168.1.96" y deberías ver "IT WORKS", o lo que contenga el fichero "/var/www/index.html" . Capito?
Visitante: "...o sea, que si en mi portátil pongo la IP del PC fijo puedo ver lo que sirve Apache... interesante"
inEdit00: "Claro, siempre que Apache esté funcionando! A partir de ahora se va a ejecutar como demonio ( en segundo plano ) cada vez que inicies el PC fijo"
Visitante: "Ei! Esto no funciona! He hecho un 'http://localhost' en el portátil y no tira!"
inEdit00: "Claro, alma de cántaro. 'localhost' designa el mismo ordenador. Si pones esto en el portátil, él intenta conectarse a si mismo, y como no tienes ningún servidor web instalado, no funciona! Usa la IP del PC fijo, que para esto están"
Visitante: "..ah, si... tiene sentido."
Visitante: "entiendo. Entonces localhost es parecido a '127.0.0.1'?"
inEdit00: "Acertaste! De hecho quiero que veas esto. Ejecuta el siguiente comando:"
$ cat /etc/hosts
inedit@wally:~/hola$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 linuxjan.ib
127.0.0.1 js.com
192.168.1.36 ofelia
Bueno, a ti te deberían salir menos entradas que a mi. Qué es esto? Pues es una relación clave-valor (IP-nombre). A la izquierda se encuentran las IP's y a la derecha los nombres de dominio. Osea, si te fijas tengo asignados diferentes nombres para "127.0.0.1": "localhost, linuxjan.ib, js.com". Lo que significa que si pongo "linuxjan.ib" en mi navegador, se dirige a '127.0.0.1' igual que si pongo 'localhost'. Esto sirve para no tener que recordar IP's, sino nombres de dominio. Puedes ver que el último elemento de la lista es diferente del resto. Lo que yo hago aqui es decirle que la dirección IP "192.168.1.36" se llama "ofelia", para no tener que acordarme de su IP.
inEdit: "Que te parece?"
Visitante: "osea que si modifico localhost..."
inEdit: "yo no haría esto! Mucho programas usan localhost como referencia a la misma máquina, mejor deja la entrada donde está"
Visitante: "pero puedo añadir elementos a la lista? Como por ejemplo: '127.0.0.1 www.paginapersonaldeprueba.com' ?"
inEdit: "claro. Pruebalo. Cuando accedas a la URL que hayas elegido, deberías ver lo de 'It works!'"
Visitante: "y también puedo añadir '127.0.0.1 www.google.com'?"
inEdit: 'si pero...
Visitante: "Pues voy a probarlo! Mola. Pero... ostia! El google ha dejado de funcionar!!!!"
inEdit: "... pero si pones un nombre de dominio que ya exista, este se resolverá primero con las entradas de tu fichero "/etc/hosts" y si allí no se encuentra, se intentará resolver por DNS. Puedes arreglarlo quitando la línea del fichero."
Visitante: "No, la dejo! Y ahora voy a putear a mi hermana quitándole el google"
inEdit: ".... ¬¬"
(dos minutos después)
Visitante: "No lo entiendo, a mi no me funciona pero a ella si!"
inEdit: "claro, macho! Porque el fichero /etc/hosts está en tu PC, y no en el suyo. Esto solo son cambios locales, si tu pones una entrada así: '127.0.0.1 srv.com' esto solo funcionará en tu PC. Ok?"
Visitante: "Vale, lo entiendo. Los cambios solo son locales."
inEdit. "Exacto. Sigamos:"
A partir de ahora ya puedes empezar a crear tus páginas creando ficheros dentro de "/var/www". También puedes ( debes! ) crear carpetas para distinguir las imágenes de las hojas de estilos ( CSS ) del JavaScript! Si haces esto:
$ sudo mkdir /var/www/sub-folder
Y después creas el fichero "index.html" dentro así:
$ sudo gedit /var/www/sub-folder/index.html
Y pones como contenido algo así:
<>
<>
<>Estamos en sub folder!< /p>
< /body>
< /html>
Nota: he puesto dos espacios antes de cada "tag" para que blogger no lo interprete. Se debe escribir sin doble espaciado.
Para acceder a este contenido puedes hacerlo así ( en tu navegador ):
http://localhost/sub-folder
http://localhost/sub-folder/index.html
Apache se encarga de cargar el fichero "index.html" ( si existe! ) si como nombre de la ruta se le especifica una carpeta.
[Despedida]
Bueno, y esto es todo por hoy. Ahora puedes buscar por internet cualquier manual sobre:
- HTML: para contenido estático.
- CSS: para estilo ( colores, formatos, dimensiones, efectos, etc... )
- JavaScript: para validaciones, para hacer peticiones asíncronas al servidor, modificación/creación de objetos del DOM en tiempo real..etc ( muy recomendado usar MooTools )
- PHP: lenguaje de programación muy asequible para empezar ( por dificultad ) y muy fácil coger malas costumbres. Las birrias funcionan, aún siendo birrias. Pero bueno, por algo se tiene que empezar.
martes, 11 de mayo de 2010
Me preguntaba...
...hasta cuando duraría la broma. Muy señores mios: todo se acaba.
Empezar con el blog fue algo divertido, compartía lo que iba haciendo y que encontraba que podía ser de interés para otros. Yo he disfrutado mucho haciendo esto. Pero desgraciadamente ya no puedo llevarlo con el ritmo de antes. Ahora estoy currando ( en prácticas ) y aprendiendo un montón. Me encantaría poder compartir mis conocimientos y todo lo que estoy aprendiendo ahora con todos vosotros, pero me temo que no tengo tiempo para dedicarme, y todo va muy deprisa.
Es por esto que digo oficialmente que el blog queda en estado de hibernación. No es un adiós, es un "hasta luego". No quiere decir que haga un post ocasional, pero seguro que será algo extraordinario. Y volveré! Con mas cosas nuevas para compartir con todos ustedes. Gracias por estar aquí.
¡¡Saludos!!!
P.D::
Siempre que un blogger al que seguía ha dicho que no publicaría más, me sabe mal. Pero se entiende que la gente tenga vida también. Yo seguro que no soy muy leído, pero aquí os dejo una lista de los blogs que sigo y que mas me gustan para que me podáis reemplazar y no lloréis tanto mi pérdida ( xD ). Ahí van:
[INFORMÁTICA]
[SISTEMAS]


Empezar con el blog fue algo divertido, compartía lo que iba haciendo y que encontraba que podía ser de interés para otros. Yo he disfrutado mucho haciendo esto. Pero desgraciadamente ya no puedo llevarlo con el ritmo de antes. Ahora estoy currando ( en prácticas ) y aprendiendo un montón. Me encantaría poder compartir mis conocimientos y todo lo que estoy aprendiendo ahora con todos vosotros, pero me temo que no tengo tiempo para dedicarme, y todo va muy deprisa.
Es por esto que digo oficialmente que el blog queda en estado de hibernación. No es un adiós, es un "hasta luego". No quiere decir que haga un post ocasional, pero seguro que será algo extraordinario. Y volveré! Con mas cosas nuevas para compartir con todos ustedes. Gracias por estar aquí.
¡¡Saludos!!!
P.D::
Siempre que un blogger al que seguía ha dicho que no publicaría más, me sabe mal. Pero se entiende que la gente tenga vida también. Yo seguro que no soy muy leído, pero aquí os dejo una lista de los blogs que sigo y que mas me gustan para que me podáis reemplazar y no lloréis tanto mi pérdida ( xD ). Ahí van:
[INFORMÁTICA]
- http://www.kriptopolis.org/
- http://www.ubuntizandoelplaneta.com/
- http://phyx.wordpress.com/
- http://120linux.com/
- http://gnometips.wordpress.com/

- http://www.muylinux.com/
- http://www.linuxzone.es/
- http://www.tribulinux.com/
- http://gallir.wordpress.com/
- http://www.forat.info/
[SISTEMAS]
- http://zonasystem.blogspot.com/
- http://blog.s21sec.com/
- http://www.logadmin.net/
- http://www.tail-f.com.ar/
- http://rm-rf.es/
- http://mundowdg.com/blog/
- http://www.tiraecol.net/modules/comic/
- http://geekandpoke.typepad.com/geekandpoke/
- http://rufadas.com/

- http://www.dosisdiarias.com/
- http://www.estonoeh.es/
- http://www.dosisdiarias.com/


domingo, 2 de mayo de 2010
Androide Libre, sorteo de Nexus One
Muy señores mios, hoy he visto que sortean en www.elandroidelibre.com un Nexus One, ni mas ni menos!
La verdad sea dicha, normalmente no participo en estos sorteos, pero la verdad que un Nexus One es un buen filón. Lo mejor de todo? Que tiene Android. En el trabajo hemos estado jugando con Android y la verdad que se puede hacer de todo! Ya viene con Python instalado por defecto con todas sus librerías preparadas para ser usadas. También incluye la típica consola, lo que convierte al SO en un buen candidado para administrar un sistema de manera remota, en caso de urgencia ( ver los, reiniciar servicios, etc... ).
Aparte de todos los sensores, como el acelerometro, que supongo que dan mucho juego cuando programas aplicaciones visuales.
Bueno, que si me toca un Nexus One ya haré un par de posts sobre como es el sistema y que tal se puede programar en el.
Saludos!
La verdad sea dicha, normalmente no participo en estos sorteos, pero la verdad que un Nexus One es un buen filón. Lo mejor de todo? Que tiene Android. En el trabajo hemos estado jugando con Android y la verdad que se puede hacer de todo! Ya viene con Python instalado por defecto con todas sus librerías preparadas para ser usadas. También incluye la típica consola, lo que convierte al SO en un buen candidado para administrar un sistema de manera remota, en caso de urgencia ( ver los, reiniciar servicios, etc... ).
Aparte de todos los sensores, como el acelerometro, que supongo que dan mucho juego cuando programas aplicaciones visuales.
Bueno, que si me toca un Nexus One ya haré un par de posts sobre como es el sistema y que tal se puede programar en el.
Saludos!
domingo, 25 de abril de 2010
Dandole caña a VIM
Venga va, una de VIM. Como todo el mundo conocerá, VIM es uno de los grades editores de texto modo consola que existen. En todas las máquina UNIX viene instalado VI por defecto, que es su versión little ( de hecho VIM es la versión ampliada ). Bien, hay un montón de manuales sobre VIM en internet, muchísimos. Pero una buena herramienta para aprender a usar el vim es el vimtutor. Es un comando que ejecutas en la consola y se te va a abrir un manual/tutorial para que vayas siguiendo. Muy útil.
Instalar el VIM:
$ sudo aptitude install vim
Bien, este post es una recopilación de comandos que uso en Normal mode, que me ayudan a trabajar mucho mas rápido. Es de nivel medio-avanzado. Si nunca has usado VIM, ejecuta "vimtutor" en un terminal y peléate con el durante un par de días, mejor.
Para empezar vamos a ver los típicos de borrar:
dd = Borra la línea actual
d = Borra desde donde estás hasta el fin de la línea
d3 Borra la línea actual más las tres líneas inferiores a la actual
Estos mismos comandos se pueden hacer con solo copia, y no borrado:
yy = Copia la línea actual.
Y = Lo mismo que "yy"
y = Copia hasta el final
y3 = Copia la línea actual más las tres de arriba.
Pero para hacer el copiado de una manera mas humana tenemos el modo VISUAL. Este se activa pulsando la tecla "v". Con el modo VISUAL activado podemos, desde nuestra posición actual, mover las flechas de dirección y ir seleccionando un texto deseado. Veamos un ejemplo:
vy = Esto nos pone vim en modo VISUAL, seleccionamos hasta el final de la línea y vamos marcando las tres líneas de abajo para ser copiadas. Finalizamos con "y" para copiar. Si pulsásemos "d" en vez de "y", borraríamos el texto seleccionado.
Y si queremos copiar todo un párrafo? Pues muy simple. Para movernos al inicio del párrafo, en normal mode ( Pulsar Esc ) pulsamos "{". De este modo estaremos situados al inicio del párrafo. Ahora, para seleccionarlo debemos ponernos en modo visual y pulsar la tecla "}". Y el comando "y". Quedaría algo como lo siguiente:
{v}y
Esto se puede simplificar y ahorrarnos ponernos en modo visual, haciendo uso de "y" primero. Seria algo así:
{y} = Nos situamos al inicio del párrafo, le damos a copiar y le decimos hasta donde. Con "}" estamos diciendo que queremos copiar hasta el final de párrafo actual. La misma manera de hacer una cosa, pero de dos modos distintos.
Si queremos copiar desde un sitio, digamos A, hasta un sitio B, tenemos un par de comandos muy buenos.
Para empezar nos situamos en A, y lo "marcamos" con el siguiente comando:
ma
ahora, para nos movemos hasta B y pulsamos, para copiar o para borrar los comandos:
d'a = borrar
y'a = copiar
Osea, marcamos el inicio y después borramos o copiamos desde el final.
Otra cosa que puede parecer una tontería pero que va bastante bien es lo siguiente. En Normal mode pulsar
:10 = Esto nos mueve la línea número 10
:+15 = Esto nos mueve 15 lineas adelante de la línea actual.
Mas comandos interesantes. Para moverte por un texto, si el cursor se encuentra en la parte de arriba y tu quieres bajar tiene que "recorrerte" toda la pantalla ya visible con el cursor para "empujar" la pantalla por la parte de abajo, esto se soluciona con los siguientes comandos:
Control + e = Para bajar
Control + y = Para subir
Y ahora los mas simples, pero que se usan mucho.
o: inserta una línea nueva justo por debajo de la línea actual
O: inserta una línea nueva justo por encima de la línea actual
p: pega justo por debajo de la línea actual
P: pega por encima de la línea actual
Para salir y guardar del documento actual se tiene que pulsar ":wq". Un modo mas simple para hacer esto mismo es pulsando ZZ. Hace lo mismo. Para guardar, cada vez tenemos que pulsar:
:w
para ahorrarnos esto, podemos hacer uso del comando nmap:
:nmap ññ :w
"" se tiene que escribir también. Ahora, cuando pulsemos ññ en el teclado, se va a ejecutar el comando ":w". Bonito, verdad? Si queremos hacer que esta opción esté siempre disponible al inicio del vim, tenemos que ediar el fichero ~/.vimrc y añadir la linea mencionada anteriormente.
Me tomo la libertad de darte un consejo: No intentes memorizar un comando. Apúntate en un papelito un par de comandos que encuentres útiles y tenlo cerca de modo que cuando quieras usarlo sepas que lo tienes ahí. En una semana te sabrás todos los comandos que te resultan más útiles de memoria, los otros seguramente no merezca la pena aprendérselos, ya que los usas mucho menos. Y cada semana, busca algún comando nuevo. Y practica mucho, mucho!
Y ahora te pregunto: cuales son tus atajos/trucos que usas? Deja tu comentario. Saludos!
Instalar el VIM:
$ sudo aptitude install vim
Bien, este post es una recopilación de comandos que uso en Normal mode, que me ayudan a trabajar mucho mas rápido. Es de nivel medio-avanzado. Si nunca has usado VIM, ejecuta "vimtutor" en un terminal y peléate con el durante un par de días, mejor.
Para empezar vamos a ver los típicos de borrar:
dd = Borra la línea actual
d
d3
Estos mismos comandos se pueden hacer con solo copia, y no borrado:
yy = Copia la línea actual.
Y = Lo mismo que "yy"
y
y3
Pero para hacer el copiado de una manera mas humana tenemos el modo VISUAL. Este se activa pulsando la tecla "v". Con el modo VISUAL activado podemos, desde nuestra posición actual, mover las flechas de dirección y ir seleccionando un texto deseado. Veamos un ejemplo:
v
Y si queremos copiar todo un párrafo? Pues muy simple. Para movernos al inicio del párrafo, en normal mode ( Pulsar Esc ) pulsamos "{". De este modo estaremos situados al inicio del párrafo. Ahora, para seleccionarlo debemos ponernos en modo visual y pulsar la tecla "}". Y el comando "y". Quedaría algo como lo siguiente:
{v}y
Esto se puede simplificar y ahorrarnos ponernos en modo visual, haciendo uso de "y" primero. Seria algo así:
{y} = Nos situamos al inicio del párrafo, le damos a copiar y le decimos hasta donde. Con "}" estamos diciendo que queremos copiar hasta el final de párrafo actual. La misma manera de hacer una cosa, pero de dos modos distintos.
Si queremos copiar desde un sitio, digamos A, hasta un sitio B, tenemos un par de comandos muy buenos.
Para empezar nos situamos en A, y lo "marcamos" con el siguiente comando:
ma
ahora, para nos movemos hasta B y pulsamos, para copiar o para borrar los comandos:
d'a = borrar
y'a = copiar
Osea, marcamos el inicio y después borramos o copiamos desde el final.
Otra cosa que puede parecer una tontería pero que va bastante bien es lo siguiente. En Normal mode pulsar
:10 = Esto nos mueve la línea número 10
:+15 = Esto nos mueve 15 lineas adelante de la línea actual.
Mas comandos interesantes. Para moverte por un texto, si el cursor se encuentra en la parte de arriba y tu quieres bajar tiene que "recorrerte" toda la pantalla ya visible con el cursor para "empujar" la pantalla por la parte de abajo, esto se soluciona con los siguientes comandos:
Control + e = Para bajar
Control + y = Para subir
Y ahora los mas simples, pero que se usan mucho.
o: inserta una línea nueva justo por debajo de la línea actual
O: inserta una línea nueva justo por encima de la línea actual
p: pega justo por debajo de la línea actual
P: pega por encima de la línea actual
Para salir y guardar del documento actual se tiene que pulsar ":wq". Un modo mas simple para hacer esto mismo es pulsando ZZ. Hace lo mismo. Para guardar, cada vez tenemos que pulsar:
:w
para ahorrarnos esto, podemos hacer uso del comando nmap:
:nmap ññ :w
"
Me tomo la libertad de darte un consejo: No intentes memorizar un comando. Apúntate en un papelito un par de comandos que encuentres útiles y tenlo cerca de modo que cuando quieras usarlo sepas que lo tienes ahí. En una semana te sabrás todos los comandos que te resultan más útiles de memoria, los otros seguramente no merezca la pena aprendérselos, ya que los usas mucho menos. Y cada semana, busca algún comando nuevo. Y practica mucho, mucho!
Y ahora te pregunto: cuales son tus atajos/trucos que usas? Deja tu comentario. Saludos!
Suscribirse a:
Entradas (Atom)