La línea de comandos. Ese gran desconocido.

2010 agosto 29
tags: ,
por rafadc

Hoy estoy en uno de esos días ASCII. ¿Por qué no? Vamos a tunear, cual R5, la línea de comandos un poquito a ver qué nos pasa. En mi caso uso bash sobre Mac pero supongo que sobre linux y windows (en caso que useis cygwin) será todo exactamente igual así que nadie debería sentirse discriminado. Yo estoy aún en proceso de adaptar todo esto a Windows. Si tengo que hacer algo raro lo pondré aquí.

Hay mucha gente que hace estas cosas de preparar mucho su consola y luego ponerlo en internet. No teneis más que buscar “dotfiles” y vereis centenares de ejemplos.

Los ficheros de arranque

A poco que hayais toqueteado la línea de comandos sabreis que hay varios ficheros que lanzan automáticamente para nosotros varios comandos que podemos utilizar para personalizar nuestro entorno. Es el caso de .bashrc o .bash_profile . Personalmente siempre me había preguntado cual era la diferencia entre ellos pero nunca me había preocupado de mirarlo… hasta hoy.

  • .bashrc: Se ejecuta cada vez que lanzamos bash. Es decir, cada vez que ejecutemos un script, cada vez que abramos una sesión ssh, cada vez que hagamos un login… Normalmente meteremos toda la configuración aquí.
  • .bash_profile: Se ejecuta cada vez que iniciamos sesión interactiva. Normalmente, si existe, solo tendremos una línea que cargará el .bashrc así que tampoco nos tendremos que preocupar mucho.

Con esto ya tenemos bastante para juguetear con nuestro entorno. De todos modos yo prefiero crearme una carpeta /bin/.bash en mi carpeta home y poder separar en varios ficheros tranquilamente. Curiosamente en windows solo me deja crear una carpeta que empiece con punto desde la línea de comandos.

La estructura de ficheros

El caso es que así podemos separar en ficheros la configuración de nuestra consola y podemos dejarlo todo ordenadito. Vamos a hacer algo bastante simple:

Yo tengo esta estructura creada en mi carpeta home. Luego puedo hacer vínculos simbólicos a los archivos .bashrc y .bash_profile. Prefiero tenerlo todo en una carpeta porque intento tener todo metido en un control de versiones para mis distintas máquinas. Entonces tan solo tenemos que editar el bashrc de la carpeta .bash y añadir unas sencillas líneas para arrancar nuestro ecosistema.

Como el .bashrc solo se ejecuta cuando arrancamos la máquina conviene que el .bash_profile sencillamente lance el bashrc porque, particularmente, no necesito ninguna diferencia entre lanzar una shell o la configuración del sistema.

.bash_profile


if [ -f ~/.bashrc ]; then

. ~/.bashrc

fi

Y voy a hacer la primera advertencia escribiendo scripts de bash. El 99% de los errores que se suelen cometer son por falta de espacios en blanco. Por ejemplo, en el if, entre el corchete y el -f hay un espacio en blanco que es obligatorio.

Entonces en el bash_profile tan solo comprobamos si existe el bashrc para ejecutarlo después.

Con el punto estamos lanzando otro fichero. El punto es equivalente al comando “source“. Sencillamente nos permite organizarnos en varios ficheros por si tu script se alarga. Con el “-f” estamos comprobando si existe o no un fichero.

.bashrc


if [ $OSTYPE = 'darwin10.0' ]; then
. ~/.bash/macEnv
else if [ $OSTYPE = 'cygwin' ]; then
. ~/.bash/winEnv
fi
fi
. ~/.bash/config
. ~/.bash/aliases

En las primeras líneas dependiendo del SO en el que estemos lanzaremos uno u otro script de variables de entorno. Algunas de las cosas que haremos son dependientes del sistema operativo. La más evidente es el tema de las rutas. Si utilizas muchas variables de entorno con rutas a lo mejor merece la pena crear varios ficheros env uno por operativo. Bash nos indica el tipo de sistema operativo en el que estamos con la variable OSTYPE. Habra multitud de ejemplos a lo largo de este post.

Dependiendo del caso puede que en lugar de diferenciar por el operativo te interese, personalmente, diferenciar por nombre de máquina. Como yo suelo guardar todo en el mismo sitio siempre me gusta más así.

La variables de entorno

Empezamos el juego. En nuestros ficheros env setearemos las variables de entorno. Por ejemplo el env de mi mac podría ser algo así.

envMac


export PATH=$PATH:/sw/bin:~/bin

export EDITOR='mvim'

export DROPBOXFOLDER='~/Dropbox'

Con esto tenemos asignadas las variables PATH y EDITOR. Por defecto, si asignamos una variable en un script de bash solo es accesible desde el entorno del script. Para que esta variable esté asignada de manera global utilizamos el comando export. Si usais svn desde linea de comandos, necesita que tengais una variable EDITOR definida que será el editor que se utilizará para editar los comentarios de los commits.

También tengo definida una variable con la ruta de mi Dropbox. Su uso lo vereis más adelante. En realidad tengo un montón de rutas más como por ejemplo la carpeta donde tengo el código fuente del trabajo o de alguno de mis proyectos pero tampoco merece la pena y lo omito para mantener esto lo más simple posible.

Los aliases

Aqui pondremos los aliases que definamos. Esta es una de las partes más interesantes y la que más trabajo nos va a ahorrar a la hora de trabajar con la consola. Como normalmente acabarás con 50.000 aliases definidos es mejor que tengan su propio fichero de configuración.

Vamos a empezar con lo básico. Hay comandos que lanzamos muchas veces así que nos interesa tener un shortcut que nos permita tener que teclear menos. Por ejemplo, si somos unos fanáticos de rails y estamos todo el día utilizando el comando rails porque hemos migrado a rails3 podemos añadir a nuestro aliases la línea.


alias r='rails'

Entonces cada vez que tecleemos “r” será como si pusiésemos rails.

Eso nos puede ahorrar tecleos. Hay mucha gente a la que le gusta poner “l” para ejecutar “ls”. Eso ya es cuestión de gustos.

Alias también está muy bien para forzar parámetros a ciertos comandos. Por ejemplo:


alias ls='ls -F'

Hará que siempre que se ejecute ls lo haga con el parámetro -F. Esto a mi no me suele convencer mucho porque luego si quieres quitarlo solamente una vez es un jaleo pero ahí está. Úsalo con cuidado.

Otra utilidad muy interesante y por la que empezó la idea de este post es la de poder cambiar de carpeta más rápidamente. Por ejemplo, y utilizando las variables que definimos en el fichero env, podemos hacer


alias cddropbox="cd $DROPBOXFOLDER"

Y puedo cambiar de carpeta a la carpeta de dropbox muy rápidamente desde la linea de comandos. Esto es muy útil cuando estamos trabajando en alguna ruta particular que tiene una ruta demasiado larga.

Los alias están bien pero las funciones ya son algo de otro mundo. Una función recibe parámetros y ejecuta una serie de comandos que pueden recibir los parámetros que le hemos pasado.


function lsView() {
ls -la $1 > $TMP/lsView.txt
$EDITOR $TMP/lsView.txt &
}
Con esto creamos un comando lsView que nos muestra el contenido del directorio actual en nuestro editor de texto preferido. Los parámetros, como podeis deducir del ejemplo, se denotan por $1, $2, $3 y así sucesivamente.También podemos usar $* para poner todos los parámetros que se nos hayan pasado.

La configuración

Aqui añadiremos cosas como el prompt. Ya que nos ponemos vamos a dejarlo todo bonito.

El prompt de BASH se cambia con la variable de entorno PS1 asi que si queremos cambiar el prompt tan solo hay que cambiar esa variable. Por ejemplo:


export PS1="mi prompt es mío y hago con él lo que quiero: "

Nos dejaría con un estúpido e inútil a la vez que divertido prompt. Si queremos hacer algo más serio mejor que os paseis por el manual de bash ya que tienen una sección con los caracteres especiales que podemos utilizar. Por ejemplo:


export PS1="\w $ "

También se puede ejecutar un comando para rellenar el prompt. He visto gente que lo hace con su control de versiones para saber en la revision en la que está. Por ejemplo podríamos mostrar la carpeta actual con pwd haciendo:


export PS1="\$(pwd) $ "
Yo pongo tan solo la ruta en la que estamos en el prompt. Personalmente me parece lo más útil a no ser que vayas a acceder con una shell remota a tu máquina en cuyo caso merece la pena agregar el hostname para evitar líos. De todos modos podemos aún juguetear un poco con esto porque si nuestra consola soporta color podemos hacer que el prompt salga en otro color.

Los códigos de colores los podemos encontrar en el BASH howto y son

       Negro       0;30     Gris oscuro    1;30
       Azul        0;34     Azul claro     1;34
       Verde       0;32     Verde claro    1;32
       Cyan        0;36     Cyan claro     1;36
       Rojo        0;31     Rojo claro     1;31
       Púrpura     0;35     Púrpura claro  1;35
       Marrón      0;33     Amarillo       1;33
       Gris claro  0;37     blanco         1;37

Para cambiar el color de la terminal hay que utlilzar la cadena \[\033[<codigocolor>m\] y una vez que terminemos de utilizar ese color devolverla a el código vacío: \[\033[0m\]

Para poner la terminar en verde, por ejemplo, utilizaremos


GREEN="\[\033[1;32m\]"

RESET="\[\033[0m\]"

PS1="$GREEN[\W]$RESET "

y tendremos un bello prompt

En lo simple está lo bello aunque se pueden hacer cosas bastante funky como por ejemplo:


GREEN="\[\033[1;32m\]"

RESET="\[\033[0m\]"

PS1="$GREEN[\W]$RESET - \h - \t \n->"

La version en dos líneas está bien si la combinas con Vcprompt. Eso ya es la repanocha. Vamos a poner que si estamos en un control de versiones (creo que solo soporta svn, mercurial y git) nos muestre la rama en la que estamos:


GREEN="\[\033[1;32m\]"

RESET="\[\033[0m\]"

CYAN="\[\033[1;36m\]"

PS1="\t - $GREEN[\W]$RESET - $CYAN[\$(vcprompt)]$RESET - \h \n->"

Vemos que nos hemos pasado a una carpeta que es un repositorio de subversion de la rama trunk. Vereis que algunos screenshots de este post están con este prompt y es que después de escribir esto me he quedado con esta version tan … cutre y a la vez bella. Con esta shell me siento como si le acabase de poner spoilers y neones a un Skoda Fabia. Me apetece ponerme gorra y escuchar el Maquina Total 8.

Pues aquí lo dejo que ya llevo bastante tiempo escribiendo esto. Esperemos que con esto se te haga un poco más agradable los días sobre esa ya no tan aburrida terminal. Si con esto no ligas en la próxima reunion de la hermandad de la línea de comandos es que no tienes remedio.

Por último, y si os ha parecido interesante el post os recomiendo comprar el screencast de peepcode sobre advanced command line. Trabaja de una manera muy similar a la que he puesto aquí pero además añade un montón de consejos y sugerencias interesantísimas. Son unos 9 dólares que considero bien gastados.

Como no voy a ser menos he subido los dotfiles que he generado con esto a un repositorio de mercurial: https://bitbucket.org/rafadc/dotfiles

Supongo que iré actualizando ahí a medida que los vaya usando. ¡Me voy a buscar un cliente de twitter para línea de comandos!

Referencias:

[1] Manual de bash: http://www.gnu.org/software/bash/manual/bashref.html

[2] Peepcode: http://peepcode.com/

[3] Bash HOWTO: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html

[4] Vcprompt: http://github.com/xvzf/vcprompt

2 Responses leave one →
  1. 2010 agosto 30

    Mola :D

    Me ha servido para una cosica que tenía que hacer en el ubuntu :P

  2. 2010 septiembre 1
    Andres permalink

    Cojonudo gracias!

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS

Switch to our mobile site