Tienes problemas para iniciar httpd y no hay errores en los logs?, Tienes otro programa que que se congela y no tienes ni idea de que pueda estar pasando? es buen momento para empezar a usar strace.

Strace es una utilidad que se usa para correr un comando y visualizar todas sus interacciones con el sistema de forma que puedes ver exactamente que esta haciendo el programa desde que inicia hasta que sale incluso puede ser usado para hacer pruebas de rendimiento y estabilidad. En este articulo lo usaremos solo como una herramienta de diagnostico para ver por que un programa se congela.

El comando strace es fácil de usar, simplemente ejecuta strace al iniciar el servicio o programa que deseas diagnosticar, por ejemplo:

strace date

Esto te debería de dar una salida de bastantes lineas en el terminal. Veamos que pasa cuando una aplicación da error, intentemos correr man sin ningún parámetro.

$ man What manual page do you want?

Ahora veamos que hace man para llegar a ese mensaje:

execve("/usr/bin/man", ["man"], [/* 23 vars */]) = 0 brk(0)                                  = 0x9e89000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7869000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=24131, ...}) = 0 ...
open("/usr/share/locale/en_US.UTF-8/man", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/man", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/man", O_RDONLY) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=5830, ...}) = 0
mmap2(NULL, 5830, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb7865000
close(4)                                = 0
write(2, "What manual page do you want?\n", 30) = 30 ...

Gracias a que man dio como salida "What manual page do you want?" sabemos cual es el error, pero si no nos hubiese dado este mensaje, como sabemos lo que esta pasando? aquí es cuando strace nos ayuda. La salida del strace es mucho mas larga que el párrafo que tenemos arriba pero lo recorte solo para mostrar lo que nos interesa en este ejemplo. Si se fijan el error "-1 ENOENT (No such file or directory)" se repite unas tres veces esto en algunos casos es un indicativo de lo que puede estar pasando.

Identificar los errores es relativamente fácil, por lo general tienen un -1 como salida y no todos los errores son fatales pero nos pueden dar pistas de lo que este mal con el programa

Algunos paramentos interesantes Puedes usar -u seguido del nombre del usuario para ejecutarlo como ese usuario en especifico cosa que es ideal para identificar correctamente problemas de permisos y lo mas seguro es que estés corriendo strace como root pero la mayoría de los servicios tienen sus propios usuarios para correr.

El parámetro -p seguido del PID es útil cuando el proceso que queremos examinar ya esta corriendo.

Personalmente suelo correrlo con estos parámetros:

strace -f -F -v -s 8192  -o <archivo>
  • -f Permite hacerle strace a los posibles forks que haga un programa, por ejemplo httpd.
  • -F Cumple la misma función que -f pero siempre lo pongo por cuestión de costumbre.
  • -v Nos da una salida detallada.
  • -s 8192 Asigno el valor de 8192 como limite de longitud de las cadenas que se van a imprimir. Por defecto es 32 y yo quiero la mayor cantidad de información posible.
  • -o La salida va a ser redirigida a un archivo.

Fedora sale de su fase alfa y entra en beta

La popular distribución de Linux Fedora, ha anunciado hoy su cambio de alfa a beta, aunque no es el método oficial, los usuarios Alfa pueden ejecutar yum clean all y seguidamente un yum upgrade para actualizar, si necesitan algo de documentación pueden revisar Fedora Project wiki: Yum Upgrade FAQ que aunque algo desactualizado seguramente responderá a muchas de sus preguntas.

La opción de menor problemática vendría siendo el instalar desde cero, con un medio físico como CD, DVD o USB esto lo pueden hacer descargando los archivos necesarios desde http://torrent.fedoraproject.org/.

Estamos en los preparativos para la apertura del 7mo Congreso Nacional de Sofwtare Libre - Venezuela 2011. El cual inicia su recorrido por las 11 sede del país este 29 de abril en la ciudad de San Felipe.

El recorrido será de la siguiente manera:
* 29 – 30 de Abril - Yaracuy: San Felipe
* 06 – 07 de Mayo - Anzoátegui: Puerto La Cruz
* 13 – 14 de Mayo - Sucre: Carúpano
* 20 – 21 de Mayo - Monagas: Maturín
* 03 – 04 de Junio - Táchira: San Cristóbal
* 10 – 11 de Junio - Mérida: Mérida
* 24 – 25 de Junio - Lara: Barquisimeto
* 01 – 02 de Julio - Falcón: Coro
* 08 – 09 de Julio - Aragua: Maracay
* 15 – 16 de Julio - Carabobo: Valencia
* 29 – 30 de Julio - Dist. Capital: Caracas
Para mayor información visita su página oficial: CNSL7
Para inscribirte aquí

I’ve lately spent some time developing a webapp for mobile devices to interact with some of the data published by the Gijón City Council. More specifically, data about local public land transportation schedule and live arrivals. The way they are presenting that information for mobile devices at the moment is very very heavy and slow, so I thought it may be useful to do something simpler for personal usage.

Basically, it is a simple web service that intensively caches data (to avoid stressing the data origin with many requests) and a fancy AJAX-powered frontend with some CSS with mobile browsers in mind (works flawlessly on Android’s browser and Mobile Safari). Additionally, if you add it as a bookmark to your iPhone’s home screen it behaves like a native application (you know, splash screen, custom icon, taskbar and so on).

I’m now working on client-side caching using HTML5 caching for offline usage. This way the application will boot way faster. It’s almost done, but it still needs some debugging.

I don’t intend to make it public for now. However, if you find it useful feel free to drop me a line. Beta testers are always welcome (but unfortunately won’t be rewarded).

This is how it looks like at the moment. The source will be released soon.

Update (23:26): Android screenshots provided by Javier Pozueco. Thanks buddy!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Hace unas semanas hemos comprado directamente el fabricante (Asia) un nuevo modelo de ZeroClient o también conocido como MultiPoint/MultiSeat: MWS8840 Afortunadamente el chipset es el mismo que el anterior MWS300 y funciona correctamente. Es más, con gran sorpresa veo que los vídeos de Youtube funcionan a pantalla completa . El dispositivo tiene una entrada USB (que se conecta al servidor de terminales)  una entrada de alimentación (5V - 3A), entrada de micro, salida de audio y 4 puertos frontales USB 2.0 (en dos de ellos se conecta el teclado y el ratón). Además este modelo trae una peana para colgarlo en la parte trasera de un monitor TFT o ponerlo en vertical. Aquí podeis ver unas cuantas fotos. El tamaño de la caja es de aproximadamente 10cm x 10cm          En breve lanzaremos desde Thinetic una completa y económica solución comercial con estos aparatos tan prometedores, y todo ello con Software Libre .

Google search box completion

*lol*

Nowadays it’s very usual to find websites offering hints while you’re typing on a search box. Google is a pretty good example of it. But, how could it be implemented?

This feature could be implemented either in the client side or in the server side. If the word list is big (usually it is), it’s recommended to keep the lookup logic in the server side to save some bytes while transferring the page to the client and also to save some computing power using server-side caches (cool when you plan to serve many requests).

Either way, there should be a data structure somewhere containing the word list and an algorithm to do the lookup. The simplest approach may be to use a list to store the words and issue something like this when you want to get a list of hints for a given prefix:

filter(lambda x: x.startsWith(prefix), word_list)

That’s Python’s filter, but it works the same way the well-known Haskell’s first-order function filter does. It builds a new list with the elements of the original list (word_list) that match the predicate (the lambda function).

Although the results can (and should) be cached, the very first lookup (or when the cache expires) would be very inefficient because the entire list must be traversed and that operation will take linear time. Not bad, but when the size of the problem gets bigger (i.e. more and more words in the database) the lookup process may be too slow, especially whether you’re serving several users at the same time. If the list was sorted, the execution time could be improved a little bit by writing a more sophisticated algorithm, but let’s keep it that way for now.

Fortunately, there are better and faster ways to face the problem. If you don’t want to write code (usually the best choice) you may use some high-performance indexing engine such as Apache Lucene. But if you prefer the ‘do-it-yourself’ way (for learning purposes), a search tree (more specifically, a trie or a prefix tree) is a good approach.

I’ve poorly benchmarked both alternatives (the list and the tree) and as expected the tree is pretty quicker generating hints. What I did was to feed both data structures with the content of an American English word list holding ~640k words (debian package wamerican-insane).

So, assuming four is a reasonable minimum prefix length, I measured the time it would take to get a list of words prefixed by hous (yes, just one, remember I said this was a poor benchmark? ;). Unsurprisingly, it took around 230 times longer for the list alternative to generate the hints (438.96 ms vs 1.92 ms). Wow.

My implementation of the tree is as follows. The API is quite straightforward, the “hot” methods are put and get_hints. I’ve stripped off the test suite for space reasons.

Usage example:

>>> tree = HintSearchTree()
>>> tree.put("nacho")
>>> tree.put("nachos")
>>> tree.put("nachete")
>>> tree.get_hints("nach")
['nachete', 'nacho', 'nachos']
>>> tree.get_hints("nacho")
['nacho', 'nachos']
>>> tree.delete("nacho")
>>> tree.get_hints("nacho")
['nachos']
>>> tree.count_words()
2
>>> tree.get_hints("n")
['nachete', 'nachos']
>>> tree.is_indexed("nachete")
True
>>> tree.is_indexed("nach")
False
>>> tree.empty()
False
class HintSearchTreeNode(object):
class HintSearchTreeNode(object):
  def __init__(self, parent=None, terminal=False):
    self._children = {}
    self._terminal = terminal
    self._parent = parent
 
  @property
  def children(self):
    return self._children
 
  @property
  def terminal(self):
    return self._terminal
 
  @terminal.setter
  def terminal(self, value):
    self._terminal = value
 
  @property
  def parent(self):
    return self._parent
 
class HintSearchTree(object):
  def __init__(self):
    self._root = HintSearchTreeNode()
 
  def put(self, word):
    """Adds a word to the tree."""
    # TODO: Sanitize 'word'
    if len(word) &gt; 0:
      self._put(self._root, word)
 
  def count_words(self):
    """Retrieves the number of indexed words in the tree."""
    return self._count_words(self._root)
 
  def is_indexed(self, word):
    """Returns True if 'word' is indexed."""
    node = self._find(self._root, word)
    return node is not None and node.terminal is True
 
  def get_hints(self, prefix):
    """Returns a list of words prefixed by 'prefix'."""
    return self._match_prefix(self._root, prefix)
 
  def delete(self, word):
    """Deletes 'word' (if exists) from the tree."""
    terminal = self._find(self._root, word)
    if terminal is not None:
      terminal.terminal = False
      self._prune(terminal.parent, word)
 
  def empty(self):
    """Returns True if the tree contains no elements."""
    return len(self._root.children) == 0
 
  def _put(self, node, word, depth=0):
    next_node = node.children.get(word[depth])
    if next_node is None:
      next_node = HintSearchTreeNode(parent=node)
      node.children[word[depth]] = next_node
    if len(word)-1 == depth:
      next_node.terminal = True
    else:
      self._put(next_node, word, depth+1)
 
  def _count_words(self, node):
    words = 1 if node.terminal is True else 0
    for k in node.children:
      words += self._count_words(node.children[k])
    return words
 
  def _match_prefix(self, node, prefix):
    terminal = self._find(node, prefix)
    if terminal is not None:
      return self._harvest_node(terminal, prefix)
    else:
      return []
 
  def _harvest_node(self, node, prefix, path=""):
    hints = []
    if node.terminal is True:
      hints.append(prefix + path)
    for k in node.children:
      hints.extend(self._harvest_node(node.children[k], prefix, path+k))
    return hints
 
  def _find(self, node, word, depth=0):
    if depth == len(word):
      return node
    else:
      child = node.children.get(word[depth])
      if child is not None:
        return self._find(child, word, depth+1)
      else:
        return None
 
  def _prune(self, node, word):
    if self._count_words(node.children[word[-1]]) == 0:
      del node.children[word[-1]]
      if len(node.children) == 0 and node.parent is not None \
          and node.terminal is not True:
        self._prune(node.parent, word[:-1])

The code is released in the public domain.

Exportar tu shell script a HTML, con sintaxis resaltada en colores es posible con la ayuda de Vim y este comando:

vim -f +"syn on" +"run! syntax/2html.vim" +"wq" +"q" hola.sh

Esta linea convierte hola.sh a hola.sh.html, el parámetro -f forza a Vim a permanecer en el primer plano, cosa que es útil si Vim va a ser utilizado por otro programa como un cliente de correos o en nuestro caso este script.

Activar el coloreado de sintaxis y ejecutar el plugin 2html.vim seria la segunda parte de este script. Aquí pasa algo peculiar, plugin 2html.vim divide la pantalla de Vim donde la parte superior es el código HTML y la inferior es el documento original. Seguidamente se le envía wq para salvar y salir de la primera ventana y se le envía q para que termine con la ventana restante.

La salida de esta linea seria hola.sh.html y luce así:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>/tmp/hola.sh.html</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v1">
<meta name="syntax" content="bash">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,prevent_copy=">
<meta name="colorscheme" content="none">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; }
body { font-family: monospace; color: #000000; background-color: #ffffff; }
* { font-size: 1em; }
.Comment { color: #0000c0; }
.Constant { color: #c00000; }
.Statement { color: #af5f00; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">#!/bin/bash</span>
<span class="Comment"># orvtech.com</span>
<span class="Statement">echo</span><span class="Constant"> </span><span class="Statement">&quot;</span><span class="Constant">Este script sera convertido</span><span class="Statement">&quot;</span>
<span class="Statement">echo</span><span class="Constant"> </span><span class="Statement">&quot;</span><span class="Constant">a HTML usando Vim</span><span class="Statement">&quot;</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
#!/bin/bash
# orvtech.com
echo "Este script sera convertido"
echo "a HTML usando Vim"

Incorporar este script en un bucle para que convierta todos los shell scripts a HTML es fácil, con un bucle for, lo podemos hacer, quedaría así:

for ARCHIVO in `ls *.sh`
  do echo -e "Convirtiendo $ARCHIVO a HTML"  vim -f +"syn on" +"run! syntax/2html.vim" +"wq" +"q" $ARCHIVO
done
Trabajando con Ruby On Rails me ha tocado escribir código usando HAML. Particularmente no me agrada mucho (entre otras cosas porque no tiene soporte multilínea, porque no identa correctamente las cadenas de texto plano, porque agrega otra capa más de interpretación a la aplicación, etc) pero cuando toca usarlo es bueno hacerlo con un buen soporte. Y cuando hablo de soporte me refiero al resaltado de sintaxis.

Para escribir código usualmente uso un editor de texto (Gedit o Geany), así que en ésta receta explicaré como agregar soporte para el resaltado de sintaxis en Gedit.

Primero agregamos soporte para que las extensiones usadas comúnmente en Rails sean reconocidas por el sistema. Abrimos una terminal y escribimos:

wget http://dl.dropbox.com/u/16349833/rails.xml 
sudo cp rails.xml /usr/share/mime/packages/rails.xml
sudo update-mime-database /usr/share/mime

Luego agregamos los archivos de definición de sintaxis en la carpeta del sourceview de GTK ejecutando:

wget http://dl.dropbox.com/u/16349833/gedit_rails_syntax.zip
sudo unzip gedit_rails_syntax.zip -d /usr/share/gtksourceview-2.0/language-specs


Ahora con nuestro editor de texto favorito (y como root) abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/ruby.lang para modificar el sourceview de GTK y agregar soporte para nuevas extensiones. Buscamos la línea:

*.rb

Y la cambiamos por:

*.rb;*.rake;*.rjs

Por último, abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/html.lang y buscamos la línea que dice:

*..html;*.htm

Y la cambiamos por:

*.html;*.htm;*.erb;*.rhtml

Cerramos todas las instancias de Gedit y al abrir de nuevo ya nuestro código HAML debería verse resaltado.


Existen recetas que instalan una serie de plugins (con soporte para haml, rjs, etc) y te dejan al Gedit como TextMate, pero como no me gusta TextMate entonces prefiero hacerlo a patica xD

Espero que la receta les haya servido de ayuda.

Referencias:
http://groups.google.com/group/haml/browse_thread/thread/6c8babd81a46b6b8/b5100d80d9182c71?pli=1
http://blog.adsdevshop.com/2008/04/19/erb-syntax-highlighting-in-gedit/

After almost a year without publishing a single post, it seems this week I’m going to beat all my records.

A week ago, I wanted to prank my brother for a while. Nothing sophisticated… just some Iptables rules, Tinyproxy and HTTP magic. To go ahead with my evil plans, I needed “something” able to redirect a HTTP request. Actually, there are several ways to do that: Apache redirects, Tornado, Netcat* and so on. These alternatives are fast, bulletproof and time-saving, but not fun.

As many of you probably know, I didn’t get a job yet. That necessary means that I’ve got plenty of free time to waste. So… what did I do? I wrote some Perl and today I’m publishing the source code just in case someone finds it useful somehow. Like the previous entry, it’s published in the public domain.

The script just collects connections, issues 301 back (Moved Permanently) and sets Location to the URI specified as a command line argument (option -u). It lacks some security checks (left as an exercise to the reader) but it does what it is supposed to do. You may likely spot some silly bugs as I haven’t spent much time reading it again. Reports are welcome!

For those wondering, the prank was a big success. I’m afraid I can’t spare any detail by now but it turns out my bro is still thinking that his computer has been cracked.

Example invocation:

$ perl redir.pl -p 7070 -v -t 3 -u http://31337.pl
2011/02/24 21:41:54 Listening on port 7070
2011/02/24 21:41:54 Redirecting HTTP requests to: ‘http://31337.pl’
2011/02/24 21:41:54 3 thread(s) working under the hood

And finally the source code:

use warnings;
use threads;
 
use Thread::Queue;
use POSIX;
 
use IO::Socket::INET;
use HTTP::Request;
use HTTP::Status qw(:constants status_message);
 
use Getopt::Long;
use DateTime::Format::HTTP;
use Data::Validate::URI qw(is_http_uri);
use Log::Log4perl qw(:easy);
 
use constant MAX_THREADS => 10;
use constant MAX_LEN_HEADERS_BUFFER => 8*1024;
use constant DEFAULT_REDIRECT_URI => "http://www.example.org";
use constant DEFAULT_PORT => 80;
use constant DEFAULT_POOL_SIZE => 3;
 
my $redir_uri = DEFAULT_REDIRECT_URI;
my $server_port = DEFAULT_PORT;
my $thread_pool_size = DEFAULT_POOL_SIZE;
my $verbose;
 
GetOptions('url=s' => \$redir_uri, 
           'port=i' => \$server_port,
           'threads=i' => \$thread_pool_size,
           'verbose'  => \$verbose) or exit -1;
 
die "Invalid redirect URI (e.g. http://www.example.org)\n" unless is_http_uri($redir_uri);
die "Invalid port (e.g. 8080)\n" unless 0 < $server_port && $server_port < 2**16;
die "Invalid pool size (should be in [1..".MAX_THREADS."])\n" 
            unless 0 < $thread_pool_size && $thread_pool_size <= MAX_THREADS;
 
Log::Log4perl->easy_init( level => $verbose? $DEBUG : $INFO );
 
my $pending = Thread::Queue->new(); 
 
my $lsock = IO::Socket::INET->new( LocalPort => $server_port,
                                   Proto => 'tcp',
                                   Listen => 1,
                                   Reuse => 1 ) or die "Couldn't bind listening socket ($!)\n"; 
 
INFO("Listening on port $server_port\n");
INFO("Redirecting HTTP requests to: '$redir_uri'\n");
 
my @workers = ();
for (1..$thread_pool_size) {
    if ($thread = threads->create("worker")) {
        push(@workers, $thread);
    }
}
 
DEBUG(sprintf("%d thread(s) working under the hood\n", $#workers+1));
 
# Set a tidy shutdown just in case an external agent SIG{INT,TERM}s the process
$SIG{'INT'} = $SIG{'TERM'} = sub {
    # Dirty hack. threads->kill() does not wake up the thread :(
    for (1..@workers) {
        $pending->enqueue(-1);
    }
    for (@workers) {
        DEBUG(sprintf("Worker %d terminated: %d clients served\n", $_->tid, $_->join())); 
    }
    close($lsock); 
    exit 0; 
};
 
while(1) {
    my $csock = $lsock->accept() or next;
    $pending->enqueue(POSIX::dup(fileno $csock));
    DEBUG(sprintf("New client enqueued: %s:%s\n", $csock->peerhost, $csock->peerport));
    close($csock);
}
 
sub worker {
    my $clients_served = 0;
    while(my $fd = $pending->dequeue) { # API promises thread safety :-)
        if ($fd == -1) {
            return $clients_served;
        }
 
        my $sock = IO::Socket::INET->new_from_fd($fd, "r+");
        DEBUG(sprintf("Dequeued client %s:%d by worker %d.\n", $sock->peerhost,
                            $sock->peerport, threads->tid()));
 
        my $buf = "";
        while(<$sock>) {
            # CAUTION: there isn't any self protection against very long lines
            last if /^\r\n$/;
            $buf .= $_;
            goto BYE if length $buf > MAX_LEN_HEADERS_BUFFER;
        }
 
        if (my $request = HTTP::Request->parse($buf)) {
            INFO(sprintf("[%s] %s {%s}\n", $request->method, $request->uri, $sock->peerhost));
        }
 
        printf $sock "HTTP/1.1 %d %s\r\n", 
            HTTP_MOVED_PERMANENTLY, status_message(HTTP_MOVED_PERMANENTLY);
        printf $sock "Date: %s\r\n", DateTime::Format::HTTP->format_datetime;
        print $sock "Location: $redir_uri\r\n";
        print $sock "Server: Simple HTTP Redirection/0.1 ($^O)\r\n";
        print $sock "Connection: close\r\n";
        print $sock "\r\n";
 
BYE:  
        $clients_served++;
        close($sock);
    }
}

(*) just an approach, may drop connections:

while [ 1 ]; 
 do echo -e "HTTP/1.1 301 Moved Permanently\r\nLocation: http://31337.pl\r\n\r\n" | nc -l 7070; 
done