<?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; httpd</title>
	<atom:link href="http://www.tail-f.com.ar/category/servicios/httpd/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>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>
		<item>
		<title>mod_python + Python 2.6 en CentOS</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_python-python-26-en-centos.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_python-python-26-en-centos.html#comments</comments>
		<pubDate>Sat, 14 Mar 2009 21:03:06 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[mod_python]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Python 2.6]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=258</guid>
		<description><![CDATA[Hace algún tiempo escribí un pequeño artículo sobre cómo instalar mod_python en Apache 2.2. El tema es que, lógicamente, cada tanto uno quiere actualizar Python para tener las últimas correcciones de bugs y los últimos features. En mi caso quería instalar Python 2.6.1 en un CentOS. El tema es que con yum no veía ninguna [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_166" class="wp-caption alignright" style="width: 278px"><img class="size-full wp-image-166" title="mod_python" src="http://www.tail-f.com.ar/wp-content/uploads/mod_python.gif" alt="mod_python" width="268" height="164" /><p class="wp-caption-text">mod_python</p></div>
<p>Hace algún tiempo escribí un pequeño artículo sobre <a href="http://www.tail-f.com.ar/2009/01/01/servicios/httpd/apache-httpd-servicios/instalar-mod_python-para-apache-22.html">cómo instalar mod_python en Apache 2.2</a>. El tema es que, lógicamente, cada tanto uno quiere actualizar Python para tener las últimas correcciones de bugs y los últimos features. En mi caso quería instalar Python 2.6.1 en un CentOS. El tema es que con yum no veía ninguna actualización, pero tenía Python 2.4.x instalado y yo quería lo último. Me bajé el código, lo compilé, lo instalé y al rato me di cuenta que al hacer eso había roto el yum (que está escrito en Python). Así fue que llegué a darme cuenta de cómo instalar Python 2.6.1 por separado, y recompilar mod_python para que trabaje con esa versión, y esto es lo que quería compartir con ustedes.</p>
<p><strong>Primero: Instalar Python 2.6 en una ubicación alternativa</strong></p>
<p>Lo primero que vamos a hacer es descargar, compilar e instalar Python 2.6 en una ruta alternativa, es decir, sin pisar la instalación actual de Python 2.4 que viene con CentOS.</p>
<pre># cd /usr/src
# wget http://www.python.org/ftp/python/2.6.1/Python-2.6.1.tgz
# tar zxvf Python-2.6.1.tgz
# cd Python-2.6.1/
# ./configure --prefix=/usr
# make
# make altinstall</pre>
<p>La clave está justamente en el último paso. En vez de hacer &#8220;make install&#8221;, hacemos &#8220;make altinstall&#8221; para que se instale sin sobreescribir la versión actual de Python. Básicamente lo que hace es instalar todas las libs en /usr/lib/python2.6 (esto lo hace de todas formas), y luego crear el binario /usr/bin/python2.6 pero sin sobreescribir /usr/bin/python.</p>
<p>Editado el 10/03/2010: En algunos casos puede ser necesario agregar al configure de Python la opción &#8211;enable-shared. Gracias Orcen!</p>
<p><strong>Segundo: Recompilar mod_python</strong></p>
<p>Ahora queda recompilar mod_python contra la nueva versión de python.</p>
<pre># cd /usr/src
# wget http://www.apache.org/dist/httpd/modpython/mod_python-3.3.1.tgz
# tar -zxvf mod_python-3.3.1.tgz
# cd mod_python-3.3.1
# ./configure --with-python=/usr/bin/python2.6
# make
# make install</pre>
<p>La clave aquí está en el configure al que le pasamos el parámetro de qué binario de Python debe usar.</p>
<p><strong>Tercero: Reiniciar Apache y probar</strong></p>
<p>Por último queda reiniciar Apache y repetir <a href="http://www.tail-f.com.ar/2009/01/01/servicios/httpd/apache-httpd-servicios/instalar-mod_python-para-apache-22.html">la prueba explicada en el artículo anterior</a>.</p>
<pre># service httpd restart</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/mod_python-python-26-en-centos.html/feed</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
	</channel>
</rss>

