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

<channel>
	<title>tail -f &#124; sysadmin &#187; servicios</title>
	<atom:link href="http://www.tail-f.com.ar/category/servicios/feed" rel="self" type="application/rss+xml" />
	<link>http://www.tail-f.com.ar</link>
	<description>Noticias y recursos para sysadmins Unix</description>
	<lastBuildDate>Mon, 28 Nov 2011 21:44:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Sencillo parser para Apache mod_status en Python</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html#comments</comments>
		<pubDate>Sun, 31 Jul 2011 01:01:46 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[mod_status]]></category>
		<category><![CDATA[parser]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=455</guid>
		<description><![CDATA[Cuánto hace que no actualizo este blog!! Hoy estuve jugando un poco con Python y me puse a hacer un pequeño script que supongo que a otros les podrá servir como base para hacer algo más interesante. Precisamente, tengo planes para hacer algo más interesante, pero como recién están en veremos, les voy pasando esta [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif"><img class="size-full wp-image-37 alignright" title="apache1" src="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif" alt="" width="210" height="210" /></a></p>
<p>Cuánto hace que no actualizo este blog!! Hoy estuve jugando un poco con Python y me puse a hacer un pequeño script que supongo que a otros les podrá servir como base para hacer algo más interesante. Precisamente, tengo planes para hacer algo más interesante, pero como recién están en veremos, les voy pasando esta pequeña base a ver si alguien me gana de mano <img src='http://www.tail-f.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Como muchos sabrán, Apache (y otros web servers) tiene un módulo llamado <a href="http://httpd.apache.org/docs/2.2/mod/mod_status.html">mod_status</a> que nos permite ver en tiempo real el estado del servidor (los requests que se están procesando, el uso del CPU, el estado de las conexiones, etc.). Esta información puede ser muy útil para hacer diagnósticos cuando está habiendo algún tipo de problema, para hacer monitoreo, etc. El módulo nos muestra una página web con la información y tiene dos interfaces: una está pensada para ser vista por seres humanos y otra para ser consultada por scripts (para ver esta segunda sólo hace falta pasarle el parámetro &#8220;?auto&#8221; en la URL). El problema es que esta segunda interfaz no nos muestra a qué dominios (virtual hosts) están dirigidos los requests que se están procesando (o si hay forma de que lo muestre yo no la encontré). Entonces me puse a hacer un sencillo script en Python para parsear la página &#8220;para seres humanos&#8221;.</p>
<p>Por suerte Python nos ofrece muchas herramientas muy útiles para este tipo de cosas, así que no me tuve que esforzar demasiado. En este caso utilicé <a href="http://docs.python.org/library/urllib2.html">urllib2</a> para acceder a la página de mod_status y <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> para parsear el HTML. Por si no lo conocen, BeautifulSoup es un muy poderoso parser para XML/HTML hecho en Python. No viene con el código fuente sino que hay que instalarlo, pero hacerlo es muy fácil:</p>
<p>En Debian/Ubuntu:</p>
<pre>apt-get install python-beautifulsoup</pre>
<p>En CentOS/RedHat:</p>
<pre>yum install python-BeautifulSoup</pre>
<p>Con easy_install:</p>
<pre>easy_install BeautifulSoup</pre>
<p>El código tiene una clase Status que es la que hace la magia y una función main() que utiliza la clase para parsear una URL e imprimir algunos datos a modo de ejemplo.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">urllib2</span><br />
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> itemgetter<br />
<span class="kw1">from</span> BeautifulSoup <span class="kw1">import</span> BeautifulSoup</p>
<p><span class="kw1">class</span> Status <span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; _url = <span class="kw2">None</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span> <span class="br0">&#40;</span><span class="kw2">self</span>, url<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._url = url</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> fetch <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span><span class="kw2">self</span>._url<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> parse <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; html = <span class="kw2">self</span>.<span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; soup = BeautifulSoup<span class="br0">&#40;</span>html<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;server_info&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span>i.<span class="kw3">string</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">for</span> i <span class="kw1">in</span> soup.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&#8216;dt&#8217;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; requests = soup.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">&#8216;table&#8217;</span><span class="br0">&#41;</span>.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&#8216;tr&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; keys = <span class="br0">&#91;</span>i.<span class="kw3">string</span> <span class="kw1">for</span> i <span class="kw1">in</span> requests.<span class="me1">pop</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> tr <span class="kw1">in</span> requests:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> n, td <span class="kw1">in</span> <span class="kw2">enumerate</span><span class="br0">&#40;</span>tr<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req<span class="br0">&#91;</span>keys<span class="br0">&#91;</span>n<span class="br0">&#93;</span><span class="br0">&#93;</span> = td.<span class="kw3">string</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> status</p>
<p><span class="kw1">def</span> main <span class="br0">&#40;</span>argv<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>argv<span class="br0">&#41;</span> &lt; <span class="nu0">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Usage %s &quot;</span>%argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span></p>
<p>&nbsp; &nbsp; status = Status<span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; data = status.<span class="me1">parse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;SERVER INFORMATION&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;==================&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> v <span class="kw1">in</span> data<span class="br0">&#91;</span><span class="st0">&#8216;server_info&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> v</p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;REQUESTS BY VHOST&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;=================&quot;</span><br />
&nbsp; &nbsp; entries = <span class="br0">&#91;</span>i<span class="br0">&#91;</span><span class="st0">&#8216;VHost&#8217;</span><span class="br0">&#93;</span> <span class="kw1">for</span> i <span class="kw1">in</span> data<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; requests = <span class="kw2">sorted</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="br0">&#40;</span>entries.<span class="me1">count</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span>, i<span class="br0">&#41;</span> <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">list</span><span class="br0">&#40;</span><span class="kw2">set</span><span class="br0">&#40;</span>entries<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>, reverse=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="st0">&quot;%d: %s&quot;</span>%<span class="br0">&#40;</span>a,b<span class="br0">&#41;</span> <span class="kw1">for</span> a,b <span class="kw1">in</span> requests<span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
<p>La forma de uso es:</p>
<pre>python status.py "http://localhost/server-status"</pre>
<p>Y en este caso la salida del script es algo así:</p>
<pre>SERVER INFORMATION
==================
Server Version: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e-fips-rhel5 DAV/2
Server Built: May 26 2011 15:14:47
Current Time: Sunday, 31-Jul-2011 00:53:59 ART
Restart Time: Saturday, 30-Jul-2011 12:07:12 ART
Parent Server Generation: 0
Server uptime:  12 hours 46 minutes 47 seconds
Total accesses: 407813 - Total Traffic: 3.7 GB
CPU Usage: u2.05 s3.23 cu52 cs0 - .125% CPU load
8.86 requests/sec - 85.0 kB/second - 9.6 kB/request
10 requests currently being processed, 8 idle workers
REQUESTS BY VHOST
=================
9: www.tail-f.com.ar
5: www.otro-dominio.com.ar
4: www.not-a-domain.com.ar
3: www.algunlado.com.ar
2: subdominio.dominio.com.ar
1: www.pepe.com.ar
1: www.no-votes-a-macri.com.ar
1: www.asd.com.ar
1: localhost</pre>
<p>Obviamente esto no es una aplicación funcional, sino un ejemplo que espero que les sirva para hacer algo más copado. Yo seguiré jugando y si hago algo un poco más interesante, ya se los mostraré.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Nginx como Proxy Reverso en servidor Directadmin</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/nginx/nginx-como-proxy-reverso-en-servidor-directadmin.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/nginx/nginx-como-proxy-reverso-en-servidor-directadmin.html#comments</comments>
		<pubDate>Sat, 18 Sep 2010 04:04:05 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[nginx]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[proxy reverso]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=434</guid>
		<description><![CDATA[En esta oportunidad voy a explicar cómo instalar Nginx como proxy reverso en un servidor de hosting con Directadmin. ¿Qué es un proxy reverso? Un proxy reverso en este caso es, básicamente, un servidor web que se interpone como una capa entre el cliente y un backend, de manera de optimizar la conexión. Típicamente el [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_37" class="wp-caption alignright" style="width: 310px"><strong><a href="../wp-content/uploads/apache1.gif"><img class="size-medium wp-image-37  " title="Apache" src="/wp-content/uploads/apache1-300x300.gif" alt="Apache" width="300" height="300" /></a></strong><p class="wp-caption-text">Apache</p></div>
<p>En esta oportunidad voy a explicar cómo instalar Nginx como proxy reverso en un servidor de hosting con Directadmin.</p>
<p><strong>¿Qué es un proxy reverso?</strong></p>
<p>Un proxy reverso en este caso es, básicamente, un servidor web que se interpone como una capa entre el cliente y un backend, de manera de optimizar la conexión. Típicamente el proxy es un servidor muy liviano que funciona de frontend, atiende las peticiones de los clientes HTTP y deriva el procesamiento en un backend que podría ser un servidor Apache. Según la configuración que apliquemos, un proxy nos permite introducir mayor seguridad en nuestra red, hacer balanceo de carga, hacer cache, etc.</p>
<p>También optimiza el manejo de memoria. Pensemos que Apache lanza un thread o proceso por cada nuevo cliente, el cual se cierra recién cuando termina la transferencia de datos. Si el cliente tiene una conexión lenta, por más que Apache funcione rápido, el proceso queda corriendo hasta que se terminen de enviar los datos. Un frontend liviano como Nginx nos permite que el proceso que espere al cliente sea mucho más liviano que uno de Apache.</p>
<p>Por último, como indican en <a href="http://systemadmin.es/2009/08/slowloris-ataque-de-denegacion-de-servicio-para-apache-1x-y-2x">sysadmin.es</a>, un proxy Nginx nos sirve para prevenir ataques de denegación de servicio utilizando <a href="http://ha.ckers.org/slowloris/">slowloris</a>.</p>
<p><strong>Un proxy reverso en un servidor de hosting</strong></p>
<div id="attachment_437" class="wp-caption alignleft" style="width: 131px"><a href="../wp-content/uploads/nginx.gif"><img class="size-full wp-image-437  " title="nginx" src="/wp-content/uploads/nginx.gif" alt="Nginx" width="121" height="32" /></a><br />
<p class="wp-caption-text">Nginx</p></div>
<p>Los proxies se suelen utilizar en arquitecturas para servir sitios de alta demanda. En esos casos es común, por ejemplo, hacer que Apache sirva el contenido dinámico y un servidor más liviano (lighttpd o nginx) sirva contenido estático. Pero en un servidor de hosting esto no es tan sencillo, pues al alojarse varios sitios en un mismo equipo nuestra configuración debe ser lo más genérica posible para que sirva a la mayor parte de nuestros clientes. Como veremos, podemos definir algún tipo de cache, pero también tiene que ser bastante genérico para no causar problemas. Además tenemos que pensar en la integración con el panel de control que estemos usando. Yo uso Directadmin y este panel no tiene (aún) una integración nativa con otro web server que no sea Apache.</p>
<p><strong>Nginx + Apache + Directadmin</strong></p>
<p>La opción que les presento es para utilizar Nginx como proxy reverso, manejando las conexiones de los clientes y haciendo un muy básico cache del contenido estático. La guía está pensada para CentOS, pero en otros sistemas operativos no debería ser muy distinto.</p>
<p>Primero instalamos Nginx. El proceso es muy sencillo.</p>
<pre># cd /usr/src
# wget http://nginx.org/download/nginx-0.7.67.tar.gz
# tar zxvf nginx-0.7.67.tar.gz
# cd nginx-0.7.67
# ./configure --prefix=/usr \
              --conf-path=/etc/nginx/nginx.conf \
              --error-log-path=/var/log/nginx/error.log \
              --http-log-path=/var/log/nginx/access.log \
              --pid-path=/var/run/nginx/nginx.pid \
              --lock-path=/var/run/nginx/nginx.lock \
              --with-http_stub_status_module \
              --with-openssl=/usr/lib/openssl
# make &amp;&amp; make install</pre>
<p>Creamos el directorio para guardar el cache de contenido estático:</p>
<pre># mkdir -p /var/tmp/nginx
# chown apache:apache /var/tmp/nginx</pre>
<p>Lo más importante es configurar Nginx. Para ello modificaremos /etc/nginx/nginx.conf para que quede algo similar a esto:</p>
<p><strong>Importante:</strong> reemplazar __SERVER_IP__ por la IP del servidor y __SERVER_HOSTNAME__ por el nombre del servidor.</p>
<pre>user  apache;
worker_processes  1;

events {
    worker_connections  8192;
}

http {
    server_tokens off;

    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;

    keepalive_timeout  75 20;

    gzip  on;

    server_names_hash_bucket_size 64;
    reset_timedout_connection on;

    client_max_body_size 100m;

    # Main cache data
    proxy_cache_path  /var/tmp/nginx/cache  levels=1:2   keys_zone=staticfilecache:180m  max_size=500m;
    proxy_temp_path /var/tmp/nginx/proxy;
    proxy_connect_timeout 30;
    proxy_read_timeout 120;
    proxy_send_timeout 120;
    proxy_cache_key "$scheme$host$request_uri";

    server {
        listen       __SERVER_IP__:81;
        server_name  __SERVER_HOSTNAME__ _;

        #charset koi8-r;
        charset off;

        access_log off;
        #access_log  /var/log/nginx/access.log  main;

        # Main reverse proxy for most requests
        location / {
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                    proxy_pass              http://__SERVER_IP__;    # apache here

                    client_max_body_size       16m;
                    client_body_buffer_size    128k;

                    #proxy_buffering     off;
                    proxy_buffering     on;  

                    proxy_connect_timeout      90;
                    proxy_send_timeout         90;
                    proxy_read_timeout         120;
                    proxy_buffer_size          8k;
                    proxy_buffers              32 32k;
                    proxy_busy_buffers_size    64k;
                    proxy_temp_file_write_size 64k;

                    error_page              502 503 /50x.html;
        }

        # Proxy cache for static files
        location ~* \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ {
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                    proxy_pass              http://__SERVER_IP__;    # apache here

                    client_max_body_size       16m;
                    client_body_buffer_size    128k;

                    #proxy_buffering     off;
                    proxy_buffering     on;  

                    proxy_connect_timeout      90;
                    proxy_send_timeout         90;
                    proxy_read_timeout         120;
                    proxy_buffer_size          8k;
                    proxy_buffers              32 32k;
                    proxy_busy_buffers_size    64k;
                    proxy_temp_file_write_size 64k;

                    # Proxy cache data
                    proxy_cache_valid 200 120m;
                    expires 864000;
                    proxy_cache staticfilecache;

                    error_page              502 503 /50x.html;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /var/www/html;
        }

    }

}</pre>
<p>Por supuesto esta es una configuración básica que debería adaptarse al caso específico. Es importante notar lo siguiente:</p>
<ul>
<li>Nginx escucha en el puerto 81 y Apache en el 80. Esto es importante para no tener que hacer cambios en la configuración de Directadmin.</li>
<li>Se definen 3 Locations. Las primeras dos son proxies que le pasan requests al Apache esuchando en el puerto 80. La segunda aplica solamente a los requests de archivos estáticos y hace un cache en /var/tmp/nginx. Este cache es manejado siguiendo los headers HTTP correspondientes.</li>
</ul>
<p>Ahora necesitamos instalar un módulo de Apache, mod_rpaf, para poder usar el header X-Real-IP.</p>
<pre># cd /usr/src
# wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz
# tar zxvf mod_rpaf-0.6.tar.gz
# cd mod_rpaf-0.6
# apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c</pre>
<p>Y luego agregamos esto al httpd.conf</p>
<pre>
LoadModule rpaf_module /usr/lib/apache/mod_rpaf-2.0.so
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1 __SERVER_IP__
RPAFheader X-Forwarded-For</pre>
<p>Reemplazando __SERVER_IP__ por la IP del servidor.</p>
<p>También vamos a necesitar un script para el init del Nginx. Como no encontré uno hecho, hice este:</p>
<pre>#!/bin/bash
#
# Name: NginX, tsj5j
#
# Function:     Start up NginX
#
# chkconfig: - 85 15
# description: NginX starter

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

prog="nginx"
nginx=/usr/sbin/nginx

start () {
        echo -n $"Starting $prog: "
        $nginx
        RETVAL=$?
        return $RETVAL
}

stop () {
        echo -n $"Stopping $prog: "
        killproc $nginx
        RETVAL=$?
        return $RETVAL
}

reload () {
        echo -n $"Reloading $prog: "
        killproc $nginx -HUP
        RETVAL=$?
        return $RETVAL
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        sleep 1
        start
        ;;
  reload)
        reload
        ;;
  graceful)
        reload
        ;;
esac

exit $RETVAL;</pre>
<p>Una vez ubicado ese contenido en un archivo /etc/init.d/nginx lo habilitamos</p>
<pre># chkconfig --add nginx
# chkconfig nginx on
# service nginx start</pre>
<p>Y nos falta una única cosa. Tenemos Apache corriendo en el puerto 80 y Nginx en el 81. ¿Cómo hacemos que Nginx atienda las peticiones de nuestros clientes? Creamos una ruta en iptables para que redirija el tráfico del puerto 81 al 80:</p>
<pre># iptables -t nat -A PREROUTING -p tcp -s ! __SERVER_IP__ --dport 80 -j REDIRECT --to-ports 81
# service iptables save</pre>
<p>Reemplazando __SERVER_IP__ por la IP del servidor.</p>
<p>Y listo, ahora nuestro Nginx va a recibir todo el tráfico HTTP y negociar con el Apache para devolverlo a los clientes.</p>
<p><strong>Verificar que atienda Nginx</strong></p>
<p>Comprobar que Nginx esté atendiendo las peticiones en el puerto 80 es muy sencillo de hacer con curl. Por ejemplo, probándolo contra la URL de este blog.</p>
<pre># curl -I http://www.tail-f.com.ar
HTTP/1.1 200 OK
<strong>Server: nginx</strong>
Date: Sat, 18 Sep 2010 04:09:23 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Keep-Alive: timeout=20
Vary: Cookie,Accept-Encoding,User-Agent
X-Pingback: http://www.tail-f.com.ar/xmlrpc.php
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Pragma: no-cache</pre>
<p>Como vemos el servidor que atiende es Nginx.</p>
<p><strong>Referencias:</strong></p>
<ul>
<li><a href="http://nginx.org">Sitio de Nginx</a></li>
<li><a href="http://stderr.net/apache/rpaf/">Sitio de mod_rpaf</a></li>
<li><a href="http://directadmin.com/forum/showthread.php?t=27344">HOWTO: Using Nginx &#8211; best practices!</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/nginx/nginx-como-proxy-reverso-en-servidor-directadmin.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Instalar Monit: monitoreo de servicios para servidores Unix</title>
		<link>http://www.tail-f.com.ar/servicios/instalar-monit-monitoreo-de-servicios-para-servidores-unix.html</link>
		<comments>http://www.tail-f.com.ar/servicios/instalar-monit-monitoreo-de-servicios-para-servidores-unix.html#comments</comments>
		<pubDate>Sun, 04 Apr 2010 14:40:47 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[servicios]]></category>
		<category><![CDATA[Monit]]></category>
		<category><![CDATA[Monitoreo]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=364</guid>
		<description><![CDATA[Hoy voy a explicar cómo instalar Monit, un software muy completo para monitoreo de servicios (locales y remotos) de cualquier sistema Unix. Con él podremos estar atentos ante posibles problemas en alguno de nuestros servidores y realizar algunas tareas automaticamente. ¿Qué es Monit? De acuerdo con su propia definición, Monit es una utilidad gratuita y [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/monit-logo.gif"><img class="alignright size-full wp-image-365" title="Monit" src="http://www.tail-f.com.ar/wp-content/uploads/monit-logo.gif" alt="Monit" width="269" height="115" /></a>Hoy voy a explicar cómo instalar <a href="http://mmonit.com/monit/">Monit</a>, un software muy completo para monitoreo de servicios (locales y remotos) de cualquier sistema Unix. Con él podremos estar atentos ante posibles problemas en alguno de nuestros servidores y realizar algunas tareas automaticamente.</p>
<p><strong>¿Qué es Monit?</strong></p>
<p>De acuerdo con su propia definición, Monit es una utilidad gratuita y Open Source para administrar y monitorear procesos, archivos, directorios y filesystems en un sistema Unix. Realiza tareas automáticas de mantenimiento y reparación y puede ejecutar acciones significativas durante situaciones de error.</p>
<p>Está desarrollado en C (pueden ver el <a href="http://code.google.com/p/monit/source/browse/">código fuente en Google Code</a>) y su demonio corre de manera casi imperceptible para el sistema, en tanto consume muy pocos recursos.</p>
<p>Para más información, se puede consultar el <a href="http://mmonit.com/monit/">sitio oficial de Monit</a> y su <a href="http://mmonit.com/monit/documentation/monit.html">manual online</a> (ambos en inglés).</p>
<p><strong>Instalación</strong></p>
<p>La instalación de Monit es muy sencilla.</p>
<pre># cd /usr/src
# wget http://mmonit.com/monit/dist/monit-5.1.1.tar.gz
# tar zxvf monit-5.1.1.tar.gz
# cd monit-5.1.1
# ./configure --prefix=/usr
# make &amp;&amp; make install</pre>
<p>Luego, si estamos instalando en CentOS o algún Linux similar, vamos a querer copiar el archivo rc.</p>
<pre># cp contrib/rc.monit /etc/init.d/monit
# chown root:root /etc/init.d/monit
# chmod 755 /etc/init.d/monit
# chkconfig --add monit
# chkconfig monit on</pre>
<p><strong>Configuración</strong></p>
<p>Una vez instalado podemos pasar a la configuración, que será lo más importante del proceso. Para ello yo suelo crear un archivo inicial /etc/monitrc que tiene la configuración general del Monit, y luego dentro de una carpeta /etc/monit creo un archivo por cada servicio que quiero monitorear.</p>
<p>Les dejo aquí mi configuración.</p>
<p>Archivo: /etc/monitrc</p>
<pre>set daemon  120
set logfile syslog facility log_daemon
set mailserver localhost

set alert administrator@domain.com                      # receive all alert
set alert anotheradmin@domain2.com

set httpd port 2812 and
   use address localhost  # only accept connection from localhost
    allow localhost        # allow localhost to connect to the server and
#    allow admin:monit      # require user 'admin' with password 'monit'
#
#
###############################################################################
## Services
###############################################################################
##
## Check general system resources such as load average, cpu and memory
## usage. Each test specifies a resource, conditions and the action to be
## performed should a test fail.
#
  check system fqdn.domain.com
    if loadavg (1min) &gt; 5 then alert
    if loadavg (5min) &gt; 10 then alert
    if loadavg (1min) &gt; 20 then exec "/bin/bash /root/handle_high_load.sh"
    if memory usage &gt; 75% then alert
    if cpu usage (user) &gt; 70% for 3 cycles then alert
    if cpu usage (system) &gt; 30% for 3 cycles then alert
    if cpu usage (wait) &gt; 20% for 3 cycles then alert

include /etc/monit/*.monitrc</pre>
<p>Algunas cosas para anotar de esta primera parte. El daemon va a revisar cada 120 segundos los servicios, va a loguear en Syslog y va enviar mails usando el mailserver local. Cuando haya alguna alerta, la enviará a administrador@domain.com y anotheradmin@domain2.com. Luego habilito el servicio web que ofrece monit para que escuche en la IP local (esto es para poder utilizar todas las opciones del comando `monit`). Por último defino las reglas para el chequeo del sistema, cuyo FQDN es fqdn.domain.com (acá iría el hostname de su servidor). Las reglas son bastante sencillas. En algunos casos lo que hago es enviar una alerta y si el loadavg es más de 20 ejecuto un script para controlarlo.</p>
<p>La última línea incluye todos los archivos *.monit del directorio /etc/monit. Que es lo que vamos a ver ahora.</p>
<p>Archivo: /etc/monit/httpd.monitrc</p>
<pre>#
# Monitor Apache (httpd)
#
check process httpd with pidfile /var/run/httpd.pid
    start program = "/sbin/service httpd start"
    stop program  = "/sbin/service httpd stop"
    if cpu &gt; 80% for 3 cycles then alert
    if totalmem &gt; 1500.0 MB for 5 cycles then alert
    if children &gt; 250 then alert
    if children &gt; 255 for 5 cycles then stop
    if cpu usage &gt; 95% for 3 cycles then restart
    if failed port 80 protocol http then restart

check file httpd.conf with path /etc/httpd/conf/httpd.conf
    if changed checksum then alert</pre>
<p>Aquí defino un proceso de nombre &#8220;httpd&#8221; con un pidfile en /var/run/httpd.pid. Luego defino los comandos para iniciar y detener el proceso. Y luego las acciones a realizar según el evento. En algunos casos será &#8220;alert&#8221; (enviar aviso por mail), en otros &#8220;restart&#8221; (reinicar el proceso). Hay otras opciones que podrán ver en la <a href="http://mmonit.com/monit/documentation/monit.html">documentación</a>. Por último agrego una verificación del archivo httpd.conf. Si se modifica me notificará por mail.</p>
<p>De la misma forma, en el directorio /etc/monit tengo archivos similares para MySQL, SMTP, POP3, IMAP, SSH, etc. Y además tengo archivos para controlar algunos servicios externos. Esto es por una cuestión básica: hasta ahora estamos haciendo todos chequeos locales, si el servidor se cae o por alguna razón no puede enviarme las alertas, podría nunca enterarme de qué pasa. Entonces voy a agregar este otro archivo para controlar un servidor externo que me diga si los servicios están accesibles.</p>
<p>Archivo: server1.monitrc</p>
<pre># server1.domain.com check
check host server1.domain.com with address 1.2.3.4
      if failed icmp type echo count 10 with timeout 15 seconds
         then alert
      if failed port 21 proto ftp then alert
      if failed port 25 proto smtp then alert
      if failed port 80 proto http then alert
      if failed port 110 proto pop then alert</pre>
<p>Aquí estoy monitreando el servidor server1.domain.com con IP 1.2.3.4 (este archivo debería estar en otro servidor con Monit, por ejemplo, servidor2.domain.com). Lo primero que intento es hacer un Echo ICMP. Lamentablemente Monit no soporta hacer ping, pero un echo ICMP es lo más cercano que nos permite. Si falla 10 veces seguidas, le pido que me avise (la cantidad de veces tan alta es para asegurarme de no recibir una alerta por un paquete perdido y llenar mi mail de alertas inútiles que no me permitan ver las importantes). Luego agrego que testee los principales puertos a través de los protocolos correspondientes y que si falla me avise.</p>
<p><strong>Iniciando Monit</strong></p>
<p>Una vez que tenemos la configuración, ya podemos probarlo. Para ello iniciaremos el servicio, veremos si se inicia correctamente en el log y veremos el status.</p>
<p>Iniciamos:</p>
<pre># service monit start</pre>
<p>Luego vemos en syslog:</p>
<pre>Apr  4 11:35:23 fqdn monit[24820]: Starting monit daemon with http interface at [localhost:2812]
Apr  4 11:35:23 fqdn monit[24822]: Starting monit HTTP server at [localhost:2812]
Apr  4 11:35:23 fqdn monit[24822]: monit HTTP server started
Apr  4 11:35:23 fqdn monit[24822]: 'fqdn.domain.com' Monit started</pre>
<p>Monit inició y tiene su servidor HTTP escuchando en localhost:2812. Ahora veamos el resumen del status de los servicios.</p>
<pre># monit status
The Monit daemon 5.0.3 uptime: 1m 

System 'fqdn.domain.com' running
Process 'sshd'                      running
File 'sshd_config'                  accessible
Process 'exim'                      running
File 'exim.conf'                    accessible
Process 'mysqld'                    running
File 'my.cnf'                       accessible
Process 'httpd'                     running
File 'httpd.conf'                   accessible
Remote Host 'fqdn.domain.com' online with all services</pre>
<p>Para ver los comandos disponibles:</p>
<pre># monit -h</pre>
<p>Al mismo tipo de información podremos acceder por vía web si accedemos a http://localhost:2812. También, si queremos acceder desde afuera, podemos configurar Monit para que escuche en otra IP (por ejemplo, 0.0.0.0) y definir un método de autenticación (para que no pueda acceder cualquiera).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/instalar-monit-monitoreo-de-servicios-para-servidores-unix.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Python: Ver dominios de Apache que más transferencia consumen</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html#comments</comments>
		<pubDate>Thu, 11 Mar 2010 01:47:12 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[access_log]]></category>
		<category><![CDATA[log]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=361</guid>
		<description><![CDATA[Hace un rato publiqué un post con un script para ver qué dominios de Apache consumen mayor transferencia. El script en BASH toma unos 7 segundos en procesar 750 archivos de uno de mis servidores. Ahora hice una versión en Python, para la que me dieron algunos consejos los chicos de PyAr, y toma aproximadamente [...]]]></description>
			<content:encoded><![CDATA[<p>Hace un rato publiqué un post con un script para ver <a href="http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/ver-dominios-de-apache-que-mas-transferencia-consumen.html">qué dominios de Apache consumen mayor transferencia</a>. El script en <a href="http://www.tail-f.com.ar/tag/bash">BASH</a> toma unos 7 segundos en procesar 750 archivos de uno de mis servidores. Ahora hice una versión en <a href="http://www.tail-f.com.ar/tag/python">Python</a>, para la que me dieron algunos consejos los chicos de <a href="http://python.org.ar/pyar/">PyAr</a>, y toma aproximadamente 4 segundos en procesar los mismos archivos. Aquí les dejo el código:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="st0">&quot;&quot;</span><span class="st0">&quot; Access Log Parser</p>
<p>Parses all the files in a directory<br />
treating them as access_log files<br />
and outputs the list of files sorted<br />
by transfered megabytes. Useful for<br />
identifying heavy users.</p>
<p>Usage:<br />
./access_log_parser.py &lt;base_dir&gt;<br />
base_dir = directory where the access_log files are<br />
&quot;</span><span class="st0">&quot;&quot;</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">time</span><br />
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> itemgetter</p>
<p><span class="kw1">def</span> main <span class="br0">&#40;</span>args<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Main</p>
<p>&nbsp; &nbsp; Main function of the script.<br />
&nbsp; &nbsp; This is where the magic happens.<br />
&nbsp; &nbsp; It takes the script arguments<br />
&nbsp; &nbsp; and returns an exit code.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Parameter checking</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>args<span class="br0">&#41;</span> &lt; <span class="nu0">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Usage: %s &lt;base_dir&gt;&quot;</span> % args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">isdir</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; base_dir = args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">print</span> <span class="st0">&quot;%s is not a directory&quot;</span> % args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> <span class="nu0">2</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Init vars</span><br />
&nbsp; &nbsp; t1 = <span class="kw3">time</span>.<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; mbyte = <span class="nu0">1048576.0</span><br />
&nbsp; &nbsp; domains = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Start processing files</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> item <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; path = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>base_dir, item<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">isfile</span><span class="br0">&#40;</span>path<span class="br0">&#41;</span> <span class="kw1">and</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">getsize</span><span class="br0">&#40;</span>path<span class="br0">&#41;</span> &gt; <span class="nu0">0</span>:</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes = <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init_date = <span class="kw2">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = <span class="kw2">None</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Process file lines</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> line <span class="kw1">in</span> <span class="kw2">open</span><span class="br0">&#40;</span>path, <span class="st0">&#8216;r&#8217;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> init_date <span class="kw1">is</span> <span class="kw2">None</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init_date = data<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += <span class="kw2">long</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="nu0">9</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">ValueError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">pass</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; domains.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#123;</span><span class="st0">&#8216;domain&#8217;</span>: item, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;mbytes&#8217;</span>: bytes / mbyte, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;init_date&#8217;</span>: init_date, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;end_date&#8217;</span>: data<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Print out sorted information</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> domain <span class="kw1">in</span> <span class="kw2">sorted</span><span class="br0">&#40;</span>domains, key=itemgetter<span class="br0">&#40;</span><span class="st0">&#8216;mbytes&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;%.2f MB | From: %s | To: %s | %s&quot;</span> % \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>domain<span class="br0">&#91;</span><span class="st0">&#8216;mbytes&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;init_date&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;end_date&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;domain&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Generated in %d seconds&quot;</span> % <span class="br0">&#40;</span><span class="kw3">time</span>.<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> &#8211; t1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
<p>Para ejecutarlo:</p>
<pre>./access_log_parser.py /tmp/domain_logs
...
544.30 MB | From: 10/Mar/2010:02:48:33 | To: 10/Mar/2010:18:13:25 | dominio1.com.ar.log
602.34 MB | From: 10/Mar/2010:00:23:09 | To: 10/Mar/2010:23:39:45 | dominio2.com.ar.log
944.03 MB | From: 10/Mar/2010:00:49:35 | To: 10/Mar/2010:23:39:57 | dominio3.com.ar.log
Generated in 3 seconds
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ver dominios de Apache que más transferencia consumen</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/ver-dominios-de-apache-que-mas-transferencia-consumen.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/ver-dominios-de-apache-que-mas-transferencia-consumen.html#comments</comments>
		<pubDate>Wed, 10 Mar 2010 19:07:44 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[BASH]]></category>
		<category><![CDATA[access_log]]></category>
		<category><![CDATA[logs]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=350</guid>
		<description><![CDATA[Frecuentemente me encuentro ante la necesidad de saber qué dominios de los que tengo alojados en mis servidores consumen más tráfico HTTP. Como éste es el tipo de tráfico más importante y que más incide en el desempeño general de mis servidores, saber qué dominios transfieren más datos por HTTP me orienta en la búsqueda [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/nerd.jpg"><img class="alignright size-medium wp-image-354" title="nerd" src="http://www.tail-f.com.ar/wp-content/uploads/nerd-300x227.jpg" alt="" width="300" height="227" /></a>Frecuentemente me encuentro ante la necesidad de saber qué dominios de los que tengo alojados en mis servidores consumen más tráfico HTTP. Como éste es el tipo de tráfico más importante y que más incide en el desempeño general de mis servidores, saber qué dominios transfieren más datos por HTTP me orienta en la búsqueda de heavy users. Para ello hice un script hace algún tiempo, y ahora lo estuve revisando, retocando y simplificando, y decidí compartirlo.</p>
<p>En el entorno de <a href="http://www.tail-f.com.ar/tag/directadmin">Directadmin</a>, los logs de <a href="http://www.tail-f.com.ar/tag/apache">Apache</a> se encuentran en /var/log/httpd. Allí hay una carpeta &#8220;domains&#8221; que guarda los logs de cada dominio. Por cada dominio hay tres logs: dominio.com.log, dominio.com.error.log y dominio.com.bytes. El primero es el access_log, el segundo el error_log y el tercero solamente guarda la cantidad de bytes de cada request. La opción más sencilla es trabajar con este último tipo de logs, pero el problema que tienen es que no indican la fecha. Si bien se supone que los logs de Directadmin rotan una vez por día, alguna vez me ha pasado que por razones que nunca pude descubrir, algunos logs no rotaban y generaban ciertas confusiones. Por lo tanto, el script que dejo usa los access_logs. Además esta opción es reutilizable en otras implementaciones de Apache que no tengan archivos de bytes.</p>
<p>El código:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="re3"># Access Log Parser</span><br />
<span class="re3">#</span><br />
<span class="re3"># Parses all the files <span class="kw1">in</span> a directory</span><br />
<span class="re3"># treating them <span class="kw2">as</span> access_log files</span><br />
<span class="re3"># and outputs the list of files sorted</span><br />
<span class="re3"># by transfered megabytes. Useful for</span><br />
<span class="re3"># identifying heavy <span class="kw2">users</span>.</span><br />
<span class="re3">#</span><br />
<span class="re3"># Usage:</span><br />
<span class="re3"># ./access_log_parser.<span class="kw2">sh</span> &lt;base_dir&gt;</span><br />
<span class="re3"># base_dir = directory where the access_log files are</span></p>
<p><span class="kw1">if</span> <span class="br0">&#91;</span> -z $<span class="nu0">1</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;Usage: $0 &quot;</span><br />
&nbsp; &nbsp; <span class="kw3">exit</span> <span class="nu0">1</span><br />
<span class="kw1">fi</span></p>
<p><span class="re2">BASE_DIR=</span>$<span class="nu0">1</span><br />
<span class="re2">T1=</span>`<span class="kw2">date</span> +%s`<br />
<span class="kw1">for</span> <span class="kw2">file</span> <span class="kw1">in</span> <span class="re1">$BASE_DIR</span>/*;<br />
<span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="re2">size=</span>`<span class="kw2">stat</span> -c %s <span class="re1">$file</span>`<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re1">$size</span> -gt <span class="nu0">0</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">from=</span>`<span class="kw2">head</span> <span class="nu0">-1</span> <span class="re1">$file</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{print($4)}&#8217;</span> |sed <span class="st0">&#8216;s/^<span class="es0">\[</span>//&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">to=</span>`<span class="kw2">tail</span> <span class="nu0">-1</span> <span class="re1">$file</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{print($4)}&#8217;</span> |sed <span class="st0">&#8216;s/^<span class="es0">\[</span>//&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">bytes=</span>`<span class="kw2">cat</span> <span class="re1">$file</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{a+=$10}END{print a}&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">mbytes=</span>`<span class="kw3">echo</span> <span class="re1">$bytes</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{print $1 / 1048576}&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> &nbsp;<span class="st0">&quot;$mbytes MB ($bytes bytes) | From: $from | To: $to | ${file:${#BASE_DIR}+1}&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">fi</span><br />
<span class="kw1">done</span> \<br />
| <span class="kw2">sort</span> -nb<br />
<span class="re2">T=</span>`<span class="kw2">date</span> +%s`</div>
<p>Un detalle importante: el script levanta todos los archivos de un directorio que se especifica por parámetro. Esto es así porque yo lo invoco desde otro script:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="re3">#!/bin/bash</span><br />
<span class="re2">LOG_DIR=</span>/var/log/httpd/domains/<br />
<span class="re2">TMP=</span>/tmp/domain_logs<br />
<span class="kw1">if</span> <span class="br0">&#91;</span> ! -d <span class="re1">$TMP</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw2">mkdir</span> -p <span class="re1">$TMP</span><br />
<span class="kw1">fi</span></p>
<p><span class="kw2">rm</span> -f <span class="re1">$TMP</span>/*</p>
<p><span class="kw3">cd</span> <span class="re1">$LOG_DIR</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> `<span class="kw2">ls</span> *.log |grep -v error`; <span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="kw2">ln</span> <span class="re1">$i</span> <span class="re1">$TMP</span>/<span class="re1">$i</span><br />
<span class="kw1">done</span><br />
/root/access_log_parser.<span class="kw2">sh</span> <span class="re1">$TMP</span></div>
<p>Este último script lo que hace es crear un directorio temporal (si no existe). Vaciar su contenido. Y luego generar hardlinks a todos los access_logs de /var/log/httpd/domains. De esta forma, no me tengo que preocupar por si los logs son modificados mientras yo estoy ejecutando el script. Por último, ejecuta mi primer script (access_log_parser.sh) y le pasa como parámetro el directorio temporal donde están los access_logs.</p>
<p>Por último, la salida del script sería algo así:</p>
<pre>...
186.995 MB (196078184 bytes) | From: 10/Mar/2010:00:27:47 | To: 10/Mar/2010:16:51:09 | dominio1.com.ar.log
187.096 MB (196184596 bytes) | From: 10/Mar/2010:03:24:55 | To: 10/Mar/2010:16:51:24 | dominio2.com.ar.log
245.692 MB (257626221 bytes) | From: 10/Mar/2010:02:53:50 | To: 10/Mar/2010:16:39:54 | dominio3.com.log
273.46 MB (286743390 bytes) | From: 10/Mar/2010:02:48:33 | To: 10/Mar/2010:14:59:29 | dominio4.com.ar.log
306.344 MB (321224473 bytes) | From: 10/Mar/2010:00:23:09 | To: 10/Mar/2010:16:51:20 | dominio5.com.ar.log
444.097 MB (465669066 bytes) | From: 10/Mar/2010:00:49:35 | To: 10/Mar/2010:16:51:20 | dominio6.com.ar.log
Generated in 6 seconds</pre>
<p>Les dejo, de yapa, la opción del script utilizando los logs de bytes. Como dije, esta opción es un poco más sencilla y veloz, pero no nos dice las fechas de los logs.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="re3">#!/bin/bash</span></p>
<p><span class="kw1">if</span> <span class="br0">&#91;</span> -z $<span class="nu0">1</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;Usage: $0 &quot;</span><br />
&nbsp; &nbsp; <span class="kw3">exit</span> <span class="nu0">1</span><br />
<span class="kw1">fi</span></p>
<p><span class="re2">BASE_DIR=</span>$<span class="nu0">1</span><br />
<span class="re2">T1=</span>`<span class="kw2">date</span> +%s`<br />
<span class="kw1">for</span> <span class="kw2">file</span> <span class="kw1">in</span> <span class="re1">$BASE_DIR</span>/*.bytes;<br />
<span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="re2">size=</span>`<span class="kw2">stat</span> -c %s <span class="re1">$file</span>`<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re1">$size</span> -gt <span class="nu0">0</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">bytes=</span>`<span class="kw2">cat</span> <span class="re1">$file</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{a+=$1}END{print a}&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">mbytes=</span>`<span class="kw3">echo</span> <span class="re1">$bytes</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{print $1 / 1048576}&#8217;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> &nbsp;<span class="st0">&quot;$mbytes MB ($bytes bytes) ${file:${#BASE_DIR}+1}&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">fi</span><br />
<span class="kw1">done</span> \<br />
| <span class="kw2">sort</span> -nb<br />
<span class="re2">T=</span>`<span class="kw2">date</span> +%s`<br />
<span class="kw3">echo</span> <span class="st0">&quot;Generated in $(($T-$T1)) seconds&quot;</span></div>
<p>Y la salida sería así:</p>
<pre># ./parser.sh /var/log/httpd/domains
...
181.716 MB (190543470 bytes) dominio1.com.bytes
187.115 MB (196203973 bytes) dominio2.com.ar.bytes
189.093 MB (198278283 bytes) dominio3.com.ar.bytes
245.692 MB (257626221 bytes) dominio4.com.bytes
273.472 MB (286756234 bytes) dominio5.com.ar.bytes
314.32 MB (329588717 bytes) dominio6.com.ar.bytes
444.516 MB (466108759 bytes) dominio7.com.ar.bytes
Generated in 2 seconds</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/ver-dominios-de-apache-que-mas-transferencia-consumen.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grave exploit para Apache descubierto</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/grave-exploit-para-apache-descubierto.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/grave-exploit-para-apache-descubierto.html#comments</comments>
		<pubDate>Mon, 08 Mar 2010 21:31:30 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[custombuild]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=348</guid>
		<description><![CDATA[Leo en Slashdot que se descubrió un grave exploit para Apache. De acuerdo con la nota de ZDNet, la compañía de seguridad &#8220;Sense of Security&#8221; descubrió un serio bug en el servidor web Apache que podría permitir a un atacante remoto obtener control sobre una base de datos. Una vulnerabilidad existente en el módulo &#8220;mod_isapi&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif"><img class="size-medium wp-image-37 alignright" title="apache1" src="http://www.tail-f.com.ar/wp-content/uploads/apache1-300x300.gif" alt="" /></a></p>
<p>Leo en <a href="http://tech.slashdot.org/story/10/03/08/1258200/Serious-Apache-Exploit-Discovered">Slashdot</a> que se descubrió un grave exploit para Apache. De acuerdo con la <a href="http://www.zdnet.com.au/news/security/soa/Apache-bug-prompts-update-advice/0,130061744,339301617,00.htm">nota de ZDNet</a>, la compañía de seguridad &#8220;Sense of Security&#8221; descubrió un serio bug en el servidor web Apache que podría permitir a un atacante remoto obtener control sobre una base de datos. Una vulnerabilidad existente en el módulo &#8220;mod_isapi&#8221; del core de Apache podría permitirle a un atacante obtener privilegios de administrador, comprometiendo seriamente la seguridad de la información.</p>
<p>La nota de ZDNet no da muchos detalles del bug, pero indica que comprometería especialmente a los servidores Windows. Por otra parte, el <a href="http://www.senseofsecurity.com.au/advisories/SOS-10-002">reporte de Sense of Security</a> es más detallado e incluye una &#8220;prueba de concepto&#8221; acerca de cómo explotar el bug.</p>
<p>Se recomienda actualizar a la <a href="http://httpd.apache.org/download.cgi#apache22">versión 2.2.15 de Apache</a> que corrige el bug.</p>
<p><a href="http://www.tail-f.com.ar/tag/directadmin">Directadmin</a> ya ha hecho los cambios correspondientes, así que con <a href="http://www.tail-f.com.ar/2008/11/22/paneles-de-control/directadmin/custombuild-en-directadmin.html">Custombuild</a> podemos actualizar rápida y fácilmente a la nueva versión siguiendo el <a href="http://www.tail-f.com.ar/paneles-de-control/directadmin/actualizar-software-con-custombuild-para-directadmin.html">procedimiento</a> que explique recientemente.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/grave-exploit-para-apache-descubierto.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>httping: herramienta para medir la latencia de un servidor web</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/httping-herramienta-para-medir-la-latencia-de-un-servidor-web.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/httping-herramienta-para-medir-la-latencia-de-un-servidor-web.html#comments</comments>
		<pubDate>Mon, 08 Mar 2010 19:40:58 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[httpd]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[httping]]></category>
		<category><![CDATA[latencia]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=343</guid>
		<description><![CDATA[El otro día, Pablo Morales me pasó el dato de httping. Se trata de una herramienta similar al ping, pero que en vez de enviar paquetes por ICMP a una IP, envía peticiones HTTP a un servidor web. De esta forma podemos medir la latencia del servicio. Instalación En Debian/Ubuntu podemos instalar el paquete httping: [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/web_server.jpg"><img class="alignright size-medium wp-image-344" title="Web server" src="http://www.tail-f.com.ar/wp-content/uploads/web_server-300x225.jpg" alt="" width="240" height="180" /></a>El otro día, <a href="http://blog.pablo-morales.com/">Pablo Morales</a> me pasó el dato de <a href="http://www.vanheusden.com/httping/">httping</a>. Se trata de una herramienta similar al <a href="http://es.wikipedia.org/wiki/Ping">ping</a>, pero que en vez de enviar paquetes por ICMP a una IP, envía peticiones HTTP a un servidor web. De esta forma podemos medir la <a href="http://es.wikipedia.org/wiki/Latencia">latencia</a> del servicio.</p>
<p><strong>Instalación</strong></p>
<p>En Debian/Ubuntu podemos instalar el paquete httping:</p>
<pre># sudo apt-get install httping</pre>
<p>Para otras distribuciones, accediendo a la <a href="http://www.vanheusden.com/httping/">página de httping</a> encontrarán RPMs y el tar.gz con los fuentes. Descargando los fuentes solamente hace falta descomprimirlo y darle &#8220;make &amp;&amp; make install&#8221;.</p>
<p><strong>Ejemplo de uso</strong></p>
<p>Usarlo es muy sencillo. Por ejemplo, para pingear un servidor local:</p>
<pre>elbarto@tarantino:~$ httping -c 5 -g http://localhost
PING localhost:80 (http://localhost):
connected to localhost:80, seq=0 time=1.56 ms
connected to localhost:80, seq=1 time=1.30 ms
connected to localhost:80, seq=2 time=1.30 ms
connected to localhost:80, seq=3 time=1.27 ms
connected to localhost:80, seq=4 time=1.19 ms
--- http://localhost ping statistics ---
5 connects, 5 ok, 0.00% failed
round-trip min/avg/max = 1.2/1.3/1.6 ms</pre>
<p>El parámetro &#8220;-c 5&#8243; define la cantidad de pings a realizar. Esto es igual que el ping de Linux.</p>
<p>También puedo pingear esta web.</p>
<pre>httping -c 5 -g http://www.tail-f.com.ar
PING www.tail-f.com.ar:80 (http://www.tail-f.com.ar):
connected to www.tail-f.com.ar:80, seq=0 time=55.48 ms
connected to www.tail-f.com.ar:80, seq=1 time=45.74 ms
connected to www.tail-f.com.ar:80, seq=2 time=34.24 ms
connected to www.tail-f.com.ar:80, seq=3 time=41.79 ms
connected to www.tail-f.com.ar:80, seq=4 time=40.31 ms
--- http://www.tail-f.com.ar ping statistics ---
5 connects, 5 ok, 0.00% failed
round-trip min/avg/max = 34.2/43.5/55.5 ms</pre>
<p>En este caso los tiempos son mayores, y tenemos que tener en cuenta dos cosas. En primer lugar, hay una diferencia por la conexión (no es lo mismo conectarme a localhost que a un servidor externo). En segundo lugar, este blog es un sitio dinámico hecho en PHP que realiza una serie de operaciones antes de mostrar el resultado. Pero, ¿cómo sabemos qué toma más tiempo, si la conexión o el procesamiento del sitio?. Para ello podemos separar ambos tiempos con el parámetro -S.</p>
<pre>httping -c 5 -Sg http://www.tail-f.com.ar
PING www.tail-f.com.ar:80 (http://www.tail-f.com.ar):
connected to www.tail-f.com.ar:80, seq=0 time=25.96+22.93=48.89 ms
connected to www.tail-f.com.ar:80, seq=1 time=22.74+17.37=40.11 ms
connected to www.tail-f.com.ar:80, seq=2 time=21.90+20.39=42.29 ms
connected to www.tail-f.com.ar:80, seq=3 time=25.36+18.01=43.37 ms
connected to www.tail-f.com.ar:80, seq=4 time=27.81+15.85=43.66 ms
--- http://www.tail-f.com.ar ping statistics ---
5 connects, 5 ok, 0.00% failed
round-trip min/avg/max = 40.1/43.7/48.9 ms</pre>
<p>Aquí vemos primero el tiempo de conexión, luego el de procesamiento y por último el total. En este caso, por lo general toma un poco más la conexión que el procesamiento, aunque es bastante parejo.</p>
<p>Otra cosa a tener en cuenta es que en este tipo de pruebas que venimos haciendo, el httping envía una petición HEAD al servidor. Para enviar un GET (que obtenga todo el contenido de la página), debemos agregar el parámetro &#8220;-G&#8221;. Por ejemplo:</p>
<pre>elbarto@tarantino:~$ httping -c 5 -Gg http://www.tail-f.com.ar
PING www.tail-f.com.ar:80 (http://www.tail-f.com.ar):
connected to www.tail-f.com.ar:80, seq=0 time=210.41 ms
connected to www.tail-f.com.ar:80, seq=1 time=211.78 ms
connected to www.tail-f.com.ar:80, seq=2 time=194.49 ms
connected to www.tail-f.com.ar:80, seq=3 time=184.41 ms
connected to www.tail-f.com.ar:80, seq=4 time=210.62 ms
--- http://www.tail-f.com.ar ping statistics ---
5 connects, 5 ok, 0.00% failed
round-trip min/avg/max = 184.4/202.3/211.8 ms</pre>
<p>Aquí los tiempos se incrementan, lógicamente, porque el tamaño de los paquetes traficados es mucho mayor.</p>
<p>Por último, podemos usar httping para hacer pruebas de stressing, con la opción &#8220;flood connect&#8221; (-f) que envía peticiones sin esperar respuesta.</p>
<pre>elbarto@tarantino:~$ httping -fg http://www.tail-f.com.ar
PING www.tail-f.com.ar:80 (http://www.tail-f.com.ar):
connected to www.tail-f.com.ar:80, seq=0 time=51.54 ms
connected to www.tail-f.com.ar:80, seq=1 time=48.47 ms
connected to www.tail-f.com.ar:80, seq=2 time=56.07 ms
connected to www.tail-f.com.ar:80, seq=3 time=55.58 ms
connected to www.tail-f.com.ar:80, seq=4 time=55.99 ms
connected to www.tail-f.com.ar:80, seq=5 time=52.46 ms
connected to www.tail-f.com.ar:80, seq=6 time=56.06 ms
connected to www.tail-f.com.ar:80, seq=7 time=52.99 ms
connected to www.tail-f.com.ar:80, seq=8 time=52.54 ms
connected to www.tail-f.com.ar:80, seq=9 time=76.56 ms
connected to www.tail-f.com.ar:80, seq=10 time=63.04 ms
connected to www.tail-f.com.ar:80, seq=11 time=53.01 ms
connected to www.tail-f.com.ar:80, seq=12 time=36.00 ms
connected to www.tail-f.com.ar:80, seq=13 time=48.93 ms
connected to www.tail-f.com.ar:80, seq=14 time=42.78 ms
connected to www.tail-f.com.ar:80, seq=15 time=44.82 ms
connected to www.tail-f.com.ar:80, seq=16 time=52.41 ms
connected to www.tail-f.com.ar:80, seq=17 time=56.62 ms
connected to www.tail-f.com.ar:80, seq=18 time=48.44 ms
connected to www.tail-f.com.ar:80, seq=19 time=53.05 ms
connected to www.tail-f.com.ar:80, seq=20 time=54.13 ms
^Cconnected to www.tail-f.com.ar:80, seq=21 time=60.53 ms
--- http://www.tail-f.com.ar ping statistics ---
22 connects, 22 ok, 0.00% failed
round-trip min/avg/max = 36.0/53.3/76.6 ms</pre>
<p>Luego tiene muchas otras opciones interesantes, como configuración de la salida para integrarse con Nagios y la posibilidad de definir un User-Agent y un Referer específicos en los requests. Les recomiendo instalarlo y hacer &#8220;man httping&#8221; para ver todas las opciones.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/httping-herramienta-para-medir-la-latencia-de-un-servidor-web.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tips Apache: ver configuración desde la línea de comandos</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/tips-apache-ver-configuracion.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/tips-apache-ver-configuracion.html#comments</comments>
		<pubDate>Mon, 01 Mar 2010 16:19:28 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=327</guid>
		<description><![CDATA[A veces queremos saber algunas cosas de la configuración de Apache, pero no queremos revisar el httpd.conf ni seguir sus includes. El binario httpd acepta algunos parámetros que nos pueden servir, proveyéndonos esa información. Dejo un par de ejemplos. Verificar sintaxis de los archivos de configuración Muy facilmente podemos pedirle al Apache que verifique la [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_37" class="wp-caption alignright" style="width: 220px"><a href="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif"><img class="size-medium wp-image-37 " title="apache1" src="http://www.tail-f.com.ar/wp-content/uploads/apache1-300x300.gif" alt="" width="210" height="210" /></a><p class="wp-caption-text">Apache Web Server</p></div>
<p>A veces queremos saber algunas cosas de la configuración de Apache, pero no queremos revisar el httpd.conf ni seguir sus includes. El binario httpd acepta algunos parámetros que nos pueden servir, proveyéndonos esa información. Dejo un par de ejemplos.</p>
<p><strong>Verificar sintaxis de los archivos de configuración</strong></p>
<p>Muy facilmente podemos pedirle al Apache que verifique la sintaxis de los archivos de configuración. Esto es útil por si hicimos una modificación de la que no estamos seguros y queremos verificarla antes de reiniciar el servicio (y dejar a los clientes sin servicio hasta que lo resolvamos).</p>
<p>Comando:</p>
<pre>httpd -t</pre>
<p>Salida:</p>
<pre>Syntax OK</pre>
<p><strong>Obtener versión de Apache</strong></p>
<p>La más sencilla y obvia, para ver la versión de Apache sólo basta con:</p>
<pre>httpd -v</pre>
<p>Y la salida es algo así:</p>
<pre>Server version: Apache/2.2.14 (Unix)
Server built:   Jan 28 2010 12:43:06</pre>
<p><strong>Ver información de compilación</strong></p>
<p>Eventualmente podemos querer tener algunos datos sobre cómo fue compilado Apache.<br />
Esta es una versión más completa de lo que ofrece httpd -v.<br />
Entre otros datos, nos sirve para saber qué módulo de MPM está usando Apache.</p>
<p>Comando:</p>
<pre>httpd -V</pre>
<p>Salida:</p>
<pre>Server version: Apache/2.2.14 (Unix)
Server built:   Jan 28 2010 12:43:06
Server's Module Magic Number: 20051115:23
Server loaded:  APR 1.3.9, APR-Util 1.3.9
Compiled using: APR 1.3.9, APR-Util 1.3.9
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/etc/httpd"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_PIDLOG="/var/logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="/var/logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"</pre>
<p><strong>Ver módulos</strong></p>
<p>Hay dos alternativas diferentes para ver los módulos. Por un lado podemos ver todos los módulos que están compilados con Apache. Por otro lado, podemos ver todos los módulos que carga Apache (esto incluye módulos compilados aparte).</p>
<p>Módulos compilados</p>
<pre>httpd -l</pre>
<p>Esto no muestra el listado de módulos compilados en el binario de Apache:</p>
<pre>Compiled in modules:
  core.c
  mod_authn_file.c
  mod_authn_default.c
  mod_authz_host.c
  mod_authz_groupfile.c
  mod_authz_user.c
  mod_authz_default.c
  mod_auth_basic.c
  mod_include.c
  mod_filter.c
  mod_deflate.c
  mod_log_config.c
  mod_logio.c
  mod_env.c
  mod_headers.c
  mod_unique_id.c
  mod_setenvif.c
  mod_version.c
  mod_proxy.c
  mod_proxy_connect.c
  mod_proxy_ftp.c
  mod_proxy_http.c
  mod_proxy_scgi.c
  mod_proxy_ajp.c
  mod_proxy_balancer.c
  mod_ssl.c
  prefork.c
  http_core.c
  mod_mime.c
  mod_dav.c
  mod_status.c
  mod_autoindex.c
  mod_asis.c
  mod_suexec.c
  mod_cgi.c
  mod_dav_fs.c
  mod_dav_lock.c
  mod_negotiation.c
  mod_dir.c
  mod_actions.c
  mod_userdir.c
  mod_alias.c
  mod_rewrite.c
  mod_so.c</pre>
<p>Módulos cargados:</p>
<pre>httpd -M</pre>
<p>Así veremos todos los módulos que carga Apache:</p>
<pre>Loaded Modules:
 core_module (static)
 authn_file_module (static)
 authn_default_module (static)
 authz_host_module (static)
 authz_groupfile_module (static)
 authz_user_module (static)
 authz_default_module (static)
 auth_basic_module (static)
 include_module (static)
 filter_module (static)
 deflate_module (static)
 log_config_module (static)
 logio_module (static)
 env_module (static)
 headers_module (static)
 unique_id_module (static)
 setenvif_module (static)
 version_module (static)
 proxy_module (static)
 proxy_connect_module (static)
 proxy_ftp_module (static)
 proxy_http_module (static)
 proxy_scgi_module (static)
 proxy_ajp_module (static)
 proxy_balancer_module (static)
 ssl_module (static)
 mpm_prefork_module (static)
 http_module (static)
 mime_module (static)
 dav_module (static)
 status_module (static)
 autoindex_module (static)
 asis_module (static)
 suexec_module (static)
 cgi_module (static)
 dav_fs_module (static)
 dav_lock_module (static)
 negotiation_module (static)
 dir_module (static)
 actions_module (static)
 userdir_module (static)
 alias_module (static)
 rewrite_module (static)
 so_module (static)
 python_module (shared)
 evasive20_module (shared)
 qos_module (shared)
 php5_module (shared)
Syntax OK</pre>
<p>Aquí se puede notar la diferencia entre los módulos compilados con el Apache (linkeados como &#8216;static&#8217;) y los compilados como objetos compartidos que se cargan en tiempo de ejecución (&#8216;shared&#8217;).</p>
<p><strong>Ver virtual hosts</strong></p>
<p>También podemos ver todos los virtual hosts que están configurados en el Apache.</p>
<pre>httpd -S</pre>
<p>Esto nos va a mostrar una lista como esta:</p>
<pre>VirtualHost configuration:
1.1.1.1:80       is a NameVirtualHost
         default server localhost (/etc/httpd/conf/extra/httpd-vhosts.conf:29)
         port 80 namevhost localhost (/etc/httpd/conf/extra/httpd-vhosts.conf:29)
         port 80 namevhost www.midominio.com (/usr/local/directadmin/data/users/usuario/httpd.conf:11)
1.1.1.1:443      is a NameVirtualHost
         default server localhost (/etc/httpd/conf/extra/httpd-vhosts.conf:38)
         port 443 namevhost localhost (/etc/httpd/conf/extra/httpd-vhosts.conf:38)
         port 443 namevhost www.midominio.com (/usr/local/directadmin/data/users/usuario/httpd.conf:48)</pre>
<p>En el ejemplo vemos un hipotético servidor (usando Directadmin) con IP 1.1.1.1, y los virtual hosts para el puerto 80 y el 443, tanto los default como los que corresponden al dominio &#8220;www.midominio.com&#8221; del usuario llamado &#8220;usuario&#8221;.</p>
<p><strong>Nota sobre diferentes distribuciones</strong></p>
<p>El artículo lo escribí pensando en CentOS y otras distros donde el binario de Apache se llama httpd. En Debian y sus derivados, el binario es apache o apache2. Todos los comandos que comenté acá se pueden correr invocando esos binarios o apachectl (que en algunos casos puede ser apache2ctl).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/tips-apache-ver-configuracion.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Apache: 15 años</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/apache-15-anos.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/apache-15-anos.html#comments</comments>
		<pubDate>Tue, 23 Feb 2010 18:19:48 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Noticias]]></category>
		<category><![CDATA[aniversario]]></category>
		<category><![CDATA[historia]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=322</guid>
		<description><![CDATA[Un 23 de Febrero, pero del año 1995, nacía Apache, el servidor HTTP multiplataforma y de código abierto más usado en el mundo. En sus inicios, Apache consistía solamente en un conjunto de parches a aplicar al servidor de NCSA, pero luego su código fue reescrito por completo. Dicen que su nombre se debe a que [...]]]></description>
			<content:encoded><![CDATA[<p>Un 23 de Febrero, pero del año 1995, nacía <a href="http://www.apache.org/" target="_blank"><strong>Apache</strong></a>, el servidor HTTP multiplataforma y de código abierto más usado en el mundo.</p>
<p><a href="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif"><img class="size-medium wp-image-37 alignright" title="apache1" src="http://www.tail-f.com.ar/wp-content/uploads/apache1-300x300.gif" alt="" width="180" height="180" /></a></p>
<p>En sus inicios, Apache consistía solamente en un conjunto de parches a aplicar al servidor de NCSA, pero luego su código fue reescrito por completo.</p>
<p>Dicen que su nombre se debe a que querían que tuviese la connotación de algo que es firme y enérgico pero no agresivo, y la tribu Apache fue la última en rendirse al que pronto se convertiría en gobierno de EEUU, y en esos momentos la preocupación de su grupo era que llegasen las empresas y “civilizasen” el paisaje que habían creado los primeros ingenieros de internet.</p>
<p>En el <a href="http://blogs.apache.org/foundation/entry/the_apache_software_foundation_announces2"><strong>blog de la Fundación Apache</strong></a>, comentan hoy el aniversario y relatan un poco su historia.</p>
<p>Tomado de <a href="http://www.ubuntips.com.ar/2010/02/23/15-anos-de-apache/">Ubuntips</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/apache-15-anos.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mod_wsgi + Python 2.6 en CentOS</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_wsgi-python-2-6-en-centos.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_wsgi-python-2-6-en-centos.html#comments</comments>
		<pubDate>Sun, 14 Feb 2010 22:08:19 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[mod_wsgi]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=313</guid>
		<description><![CDATA[Guía de instalación de mod_wsgi con Apache y Python 2.6 en CentOS.]]></description>
			<content:encoded><![CDATA[<div id="attachment_100" class="wp-caption alignright" style="width: 221px"><a href="http://www.tail-f.com.ar/wp-content/uploads/python-logo.gif"><img class="size-full wp-image-100" title="Python" src="http://www.tail-f.com.ar/wp-content/uploads/python-logo.gif" alt="" width="211" height="71" /></a><p class="wp-caption-text">Python</p></div>
<p>Hace algún tiempo publiqué un artículo donde explicaba cómo instalar <a href="http://www.tail-f.com.ar/2009/03/14/servicios/httpd/apache-httpd-servicios/mod_python-python-26-en-centos.html">mod_python con Python 2.6 en CentOS</a>, por el problemita que tiene yum que no funciona con la última versión de Python. Pues bien, últimamente por lo que he venido leyendo, una alternativa mejor a mod_python es <a href="http://code.google.com/p/modwsgi">mod_wsgi</a>, pues aparentemente funciona bastante mejor, más rápido y es la opción recomendada para usar con Apache y <a href="http://www.djangoproject.com/">Django</a>.</p>
<p>Por lo tanto, dejo esta guía muy sencilla de cómo instalar mod_wsgi con Python 2.6 en CentOS.</p>
<p>Descargar mod_wsgi, descomprimir y configurar</p>
<pre># cd /usr/src
# wget http://modwsgi.googlecode.com/files/mod_wsgi-3.1.tar.gz
# tar zxvf mod_wsgi-3.1.tar.gz
# cd mod_wsgi-3.1
# ./configure --with-python=/usr/bin/python2.6</pre>
<p>Esa última línea es la clave para que utilice la instalación correcta de Python (ver el <a href="http://www.tail-f.com.ar/2009/03/14/servicios/httpd/apache-httpd-servicios/mod_python-python-26-en-centos.html">artículo anterior</a> para saber cómo instalar Python 2.6 sin pisar la versión actual).</p>
<p>Luego compilamos e instalamos</p>
<pre># make &amp;&amp; make install</pre>
<p>Agregamos la línea para cargar el módulo en el httpd.conf</p>
<pre>LoadModule wsgi_module        lib/apache/mod_wsgi.so</pre>
<p>Y reiniciamos el Apache</p>
<pre>service httpd restart</pre>
<p>Luego para configurar un virtual host para que utilice mod_wsgi no es tan sencillo, pero tampoco es demasiado complicado. Básicamente hay que generar un archivo .wsgi, que no es más que un archivo Python que va a ser el que se integre con mod_wsgi y luego configurarlo en el httpd.conf. Lo que hay que tener en cuenta es que mod_wsgi no sirve contenido estático, por lo cual uno debe configurar por un lado el handling del código python y por otro los archivos estáticos. Si bien es algo distinto a lo que solemos hacer con mod_php, es algo bastante lógico y es una buena práctica pensar en servir por separado el contenido dinámico y el estático.</p>
<p>Como es un poco complejo, lo mejor es leer la guía correspondiente. En el <a href="http://code.google.com/p/modwsgi/">sitio de mod_wsgi</a> van a ver que hay mucha documentación. Particularmente, la guía de <a href="http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango">integración con Django</a> es muy útil.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_wsgi-python-2-6-en-centos.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

