Report inadequate content

Textos grandes a partir de caracteres básicos en terminal

Estaba haciendo un script para automatizar el proceso de conexión a una base de datos, en producción.

Uno de esos scripts que conviene usar con cuidad así que pensé en poner un aviso que se mostrara al ejecutarlo:

[user~]$ cat prod_mysql.sh
echo "CUIDAOOOOOOOOO!!!!!" mysql -h localhost -u user_prod -plucksoytuhijo main_data

Pero al ejecutarlo pensé que ese aviso no era tan visible com me gustaría así que recordé una herramienta que usaba hace muchos años. Su nombre es figlet y, casualidades de la vida, todavía está disponible para correr en mi CentOS 6.3 http://www.figlet.org/

La instalación de figlet en CentOS es muy sencilla:

cd /tmp
wget http://pkgs.repoforge.org/figlet/figlet-2.2.2-1.el6.rf.x86_64.rpm
sudo rpm -U figlet-2.2.2-1.el6.rf.x86_64.rpm

Y ahora sólo me queda adaptar mi script:

[user~]$ cat prod_mysql.sh
figlet "CUIDAOOO!"
mysql -h localhost -u user_prod -plucksoytuhijo main_data

Mucho mejor:

[user~]$ ./prod_mysql.sh
  ____ _   _ ___ ____    _    ___   ___   ___  _
 / ___| | | |_ _|  _ \  / \  / _ \ / _ \ / _ \| |
| |   | | | || || | | |/ _ \| | | | | | | | | | |
| |___| |_| || || |_| / ___ \ |_| | |_| | |_| |_|
 \____|\___/|___|____/_/   \_\___/ \___/ \___/(_)

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18432
Server version: 5.1.61 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
{
}

Llamadas cURL a través de distintas interfaces


 - Si tu servidor web dispone de varias interfaces de red y quieres que ciertas peticiones que haces con cURL salgan a través de una IP específica puedes modificar el flag CURLOPT_INTERFACE de cURL pásandole la IP.

Un ejemplo tonto podría ser:

...
// Todas mis interfaces de red:
$interfaces = array(
        '91.121.157.41',
        '178.33.161.225',
        '188.165.128.67',
        '178.33.166.125',
        '178.33.163.125',
);
// Salir aleatoriamente por una de ellas:
$rand_interface = $interfaces[rand(0,count($interfaces)-1)];
curl_setopt($curl_handle, CURLOPT_INTERFACE, $rand_interface );
...

Esto te puede servir tanto para balancear carga, como para forzar que una petición venga de un orígen único. Especialmente útil para hacer cosas feas en servidores con IP failover.

En una máquina con IP Failover la lista de interface de red puede ser:

cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 91.121.157.41
        netmask 255.255.255.0
        network 91.121.157.0
        broadcast 91.121.157.255
        gateway 91.121.157.254


auto eth0:0
iface eth0:0 inet static
        address 178.33.161.225
        netmask 255.255.255.255

auto eth0:1
iface eth0:1 inet static
        address 188.165.128.67
        netmask 255.255.255.255


auto eth0:2
iface eth0:2 inet static
        address 178.33.166.125
        netmask 255.255.255.255

auto eth0:3
iface eth0:3 inet static
        address 178.33.163.125
        netmask 255.255.255.255

Copy/clone/duplicate a mysql database script

 TAGS:This is a simple script that duplicates your entire database. There are many ways in which you can take advantage of having an exact replica of your production database.

In short, the behaviour of the script is the following (in this order, all piped):

  1. Delete the COPY database if possible to start with a fresh one
  2. Create the COPY database
  3. Dump the PRODUCTION database
  4. Inject the output of the dump into the COPY database
Read more

Varnish allow/reject connections with IPs list (ACL)

 TAGS:In a web server you can use directives to deny the unwanted eye to look at your content. This is an example of how Apache would handle a virtual host that only accepts connections from a series of IPs, but in Varnish that won't work.

        Order Deny,Allow
        Deny from all
        # Barcelona IPs
        Allow from 89.140.xxx.xxx/27
        # Japan IP
        Allow from 222.229.xxx.xxx/32

The reason that this won't work in Varnish is because the IP Apache is receiving is 127.0.0.1. (Varnish is the one connecting to Apache, not the client). The real client IP comes in the header X-HTTP-FORWARDED-FOR. If you want to fix this situation with Varnish in the middle you have basically two options:

Read more
{
}

Evitar que Chrome lance a Google tu url como búsqueda

El problema

Como desarrollador cada vez me siento más cómodo trabajando con Google Chrome pero hay una cosa que muchas veces me hace perder algo de tiempo:

En ocasiones, al intentar buscar una url poco "normal", como puede ser en un dominio típico en un entorno de desarrollo, Chrome detecta que no es una url válida y la lanza contra Google en forma de búsqueda.

Un ejemplo

Queremos acceder a nuestra working copy con una url como ésta: development_area/test_script.php

 TAGS:

 

 

Cuando pulsamos Enter, Chrome nos lleva a esta pantalla por tratarse de un dominio que, bajo su opinión, es inválido:

 TAGS:

 

 

 

 

 

La solución

La solución pasa por cambiar el buscador por defecto de Chrome.

Vayamos a chrome://chrome/settings/ y pulsemos en "Administrar motores de búsqueda..."

 TAGS:

 

 

 

 

 

 

 Ahora, elige cualquiera de los que hay y lo modificamos escribiendo 'null' en el campo del medio y http://%s en el de la derecha. Para poder editarlo sólo hay que pulsar sobre lo que ya hay escrito.

Ahora pulsa en "Establecer como predeterminado". 

 TAGS:

 

Lo sé!, es una de esas pequeñas cosas que mejorán tu vida ;).

 

Fuente: http://superuser.com/questions/354338/force-chrome-to-open-urls-as-urls-instead-of-searching

Determining the client IP with Varnish in the middle

If you implement Varnish in your application one of the early things that you discover is that  any IP functionalities you had are now gone. Some examples are:

  • GEOIP does not resolve the country
  • Apache logs write 127.0.0.1 as request client IP (or another IP of your LAN)
  • My own PHP logic cannot longer apply filters by IP

Why? Well, it's easy to answer. That's because your Apache or Ngnix will receive the request from Varnish, not from the real client as it used to be.

But that has an easy fix. All you need to do is to tell Varnish to send the client IP to the backend. This can be easily accomplished by setting in your VLC (/etc/varnish/default.vcl) the following:

sub vcl_recv {

     remove req.http.X-Forwarded-For;
     set req.http.X-Forwarded-For = client.ip;
...

With this change your  application will be able to get the client IP and resolve correctly the country using GeoIP. When your application needs the client IP you only have to access to the header X-Forwareded-For.

Now,  you might want to see the original IP in the apache logs too. To do that you have to use a custom log that prints the X-Forwareded-For header. Just add inside your Virtualhost declaration:

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" varnish
CustomLog /var/log/httpd/access_combined_SOMEDOMAIN.log varnish

You should also have in mind that this configuration is appended, so it might happen that you vcl has already a line like this, so you are doing it twice. See the commented code in the default.vcl file.

The latest VCL file includes already the client.ip, just that it might appear twice! Copy all the file and tune the lines you like

Mine looks like this

sub vcl_recv {

     remove req.http.X-Forwarded-For;
     set req.http.X-Forwarded-For = client.ip;

     # Ignore all requests from Working Copies
     if ( req.http.host ~ "([a-z]{2,3}\.development\.lan)$" )
     {
        return(pipe);
     }

     unset req.http.Cookie;

#Copy paste...

     if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE") {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
     }
     if (req.request != "GET" && req.request != "HEAD") {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }
     if (req.http.Authorization || req.http.Cookie) {
         /* Not cacheable by default */
         return (pass);
     }
     return (lookup);

 }

 

After that Varnish will shine again.

Puppet Syntax highlighting under Textmate

Add some color to your puppet scripts opened in TextMate! Fire this in a terminal:

mkdir -p ~/Application\ Support/TextMate/Bundles
git clone https://github.com/masterzen/puppet-textmate-bundle.git Puppet.tmbundle
mv Puppet.tmbundle/ ~/Library/Application\ Support/TextMate/Bundles/
rm -fr Puppet.tmbundle

And voilà!

 -

Varnish VCL: Delete ALL cookies and other magic

This morning Javi Callón gave me a great introduction in few minutes to the Varnish in steroids world, I really appreciate it.  I'd like to share this snippet which might be very interesting for you if you are new to the Varnish magic too.

This has been my first contact with Varnish ever, and I have to say I am quite amazed on how the application is responding now in terms of performance. Do not take this snippet as a definitive solution to your problems.

I wrote an article yesterday on how to install Varnish. Truth is that if you install Varnish and you do not tune the VCL file chances are that Varnish is not caching anything because of the cookies. In a dynamic application there are a lot of factors that have to be taken (headers, user-agents, variations...)

This sample VCL tries to address the following problems:

  • Ignore a specific host (do not cache)
  • Remove ALL the cookies in the caching (the application does not need any of them)
  • Change the varnish cache of the images to 5 minutes
  • Special case when the URL contains a GET parameter ?rev=
  • Add in the response headers number of hits and if was a HIT or a MISS

Open the file/etc/varnish/default.vcl and add the following. It is recommended to leave the rest of the comments as they are for future reference of what Varnish does by default.

The code is commented so you properly understand what it does and you can remove any pieces you don't need.

# You already have a block like this one when you installed Varnish, keep it safe:
backend default {
  .host = "127.0.0.1";
  .port = "8080";
}

# ADD THE FOLLOWING
# -----------------

# 2 things are done here:
# First, ignore any request to a specific host. For instance, you don't want Varnish on a specific host.
# Second, remove cookies, because my application does not rely on cookies at all.
sub vcl_recv {

     # Varnish will Ignore any request to this host  (e.g: xx.mydomain.com)
     if ( req.http.host ~ "([a-z0-9]{2}\.mydomain\.com)$" )
     {
        return(pipe);
     }

     #Goodbye incoming cookies:
     unset req.http.Cookie;

}


sub vcl_fetch {
    # Remove cookies that destroy cache:    
     unset beresp.http.Set-Cookie;

     # 5 minutes (300s) cache for images
    if ( req.url ~ "\.(jpg|jpeg|png|gif)$" )
     {
        set beresp.ttl = 300 s;
     }

    # This is very specific of SIFO.me framework, but you can recycle it:
    # Any static URL containing ?rev= (this is JS and CSS) cache it almost forever.
    # The following regexp will find urls like http://.../file.js?rev=1747c3872495221156287e2000a0d110
    if ( req.url ~ "\?rev=[a-f0-9]{32}$" )
    {
       set beresp.ttl = 600000 s;
    }
}

# Add some debug info headers when delivering the content:
# X-Cache: if content was served from Varnish or not
# X-Cache-Hits: Number of times the cached page was served
sub vcl_deliver {

        # Was a HIT or a MISS?
        if ( obj.hits > 0 )
        {
                set resp.http.X-Cache = "HIT";
        }
        else
        {
                set resp.http.X-Cache = "MISS";
        }

        # And add the number of hits in the header:
        set resp.http.X-Cache-Hits = obj.hits;
}

Try if the configuration syntax is OK with:

/etc/init.d/varnish configtest

And then restart the service (also wipes the cache).

/etc/init.d/varnish restart

The new headers should appear and you will be able to see what Varnish is doing with a simple CURL or with any browser Inspector. Example:

[root@mnm1 mnm]# curl --head http://yourhost,com
HTTP/1.1 200 OK
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Cache-Control: public, must-revalidate, max-age=30, s-maxage=43200
Vary: Accept-Encoding
Content-Type: text/html; charset=UTF-8
Date: Tue, 09 Oct 2012 13:38:41 GMT
X-Varnish: 1572155458 1572155457
Age: 12
Via: 1.1 varnish
Connection: keep-alive
X-Cache: HIT
X-Cache-Hits: 1

Have in mind that all these functions are appended to the default behaviour. So they are adding extra things, but not preventing the default Varnish workflow take action.

In the cases where the time to live of the cache (TTL) is not set ,Varnish will cache it for 2 minutes (look for "120 s" in the deafault.vcl code).

All in all, it seems to me that for the huge benefit that Varnish adds to a project, the investment of time and resources you have to put on are ridiculous (half morning if your dynamic app doesn't have excessive magic). Do not be scared and try to add Varnish at least in your static files, then move to the dynamics.