foo

Modificando el prompt de bash

El presente documento pretende servir de ayuda a quienes nunca han modificado o usado estas caracteristicas de bash. Con ejemplos utiles y explicaciones sencillas, no se pretende por tanto abarcar los aspectos mas complejos relacionados con bash, aqui tan solo se dara una idea global de como modificar el aspecto del interprete de bash, para documentacion mas extendida sobre bash consulte la seccion documentacion.
Si usted usa un shell distinto a bash, tal vez este documento no le sea de mucha utilidad.

                Comunes
                Colores
                Movimientos del cursor                 Prompt extenso con funciones especiales.
                Prompt con mucha informacion y lento.

Objeto del documento

El presente documento pretende servir de ayuda a quienes nunca han modificado o usado estas caracteristicas de bash.
Con ejemplos utiles y explicaciones sencillas, no se pretende por tanto abarcar los aspectos mas complejos relacionados con bash, aqui tan solo se dara una idea global de como modificar el aspecto del interprete de bash, para documentacion mas extendida sobre bash consulte la seccion documentacion.
Si usted usa un shell distinto a bash, tal vez este documento no le sea de mucha utilidad.


indice


¿Que es el prompt?

El prompt es el interprete de bash, el interprete posee una apariencia modificable , generalmente es esta:

 [usuario/dominio directorio]$

Esto realmente no es mas que una salida de comandos a una variable de nuestro shell, la variable es $PS1, existen mas variables pero nos vamos a centrar en la que nos interesa (PS1) que es donde se define el aspecto de nuestro prompt.


indice


¿Donde se encuentra el prompt?

El prompt de linux se puede definir en la variable de entorno $PS1 que a su vez se puede definir en el archivo .bashrc en el $HOME, o bien de manera general para toda la maquina en /etc/bashrc, si optamos por modificar el prompt de el usuario o usuarios, deberemos modificar la variable $PS1 de $HOME~.bashrc de lo contrario modificaremos el de toda la maquina, sea quien sea el usuario (/etc/bashrc).
Aunque esto tratandose de Linux tambien se puede modificar como veremos mas adelante, pero de momento dejemos este concepto como esta.


indice

¿Por que modificar el prompt?


Principalmente nos basamos en la utilidad, en la comodidad y en el control visual de la propia maquina.

En el prompt podemos visualizar lo que se nos ocurra, al contrario de otros sistemas, con bash podemos almacenar una cantidad importante de datos en memoria, esto en MsDos era casi inpensable, logicamente hay que tener en cuenta que; a cuanta mas memoria = uso mas lento de la interfaz de comandos, esto se hace particularmente importante cuando introducimos muchos  comandos, variables, o su salida si se prefiere asi, en el prompt, a este concepto se hace referencia en otra parte del documento.

En los sistemas multiusuario la modificacion del prompt puede ser muy util, puesto que nos permite mostrar el texto que nosotros deseemos, esto nos abre un abanico muy extenso de opciones, P.ejm: mostrar las cuotas de los usuarios, los servicios a los que tienen acceso, etc...


indice


Modificando el prompt


Nos vamos a basar en un archivo bashrc muy sencillo, e iremos comentando las lineas y/o instrucciones de este, por supuesto el ejemplo es extensible hasta donde queramos llegar.

# /etc/bashrc
if [ "`id -gn`" = "`id -un`" -a `id -u` -gt 99 ]; then
    umask 002
else
    umask 022
fi
<--Lo primero que hacemos es definir umask, umask nos permite tener una configuracion por         defecto en materia de ficheros, directorios y permisos.
    Buscamos el id del usuario, filtrando las cuentas que no son menores de 100, esto es por que esas cuentas que estan por debajo de 100 corresponden a "usuarios propios del sistema" (mail, news, apache, etc....) -->

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="\[\h@\u \w]"
   
<-- en esta linea definimos la variable PS1, esta es la linea del prompt en si, en este caso veriamos el nombre del host, el simbolo @ el usuario y el directorio actual de trabajo -->



Probablemente el aspecto de un archivo bashrc sera mas amplio, incorporando mas funciones.
Pero sin lugar a dudas lo que es evidente, es que es un script para el bash y como tal se puede modificar "al gusto", vamos a ver como podemos hacer un prompt mas personal.


indice


Variables de entorno


Nos tenemos que referir a ellas casi por obligacion, una variable de entorno es como cualquier otra, un nombre asociado a una cadena de caracteres, esta cadena de caracteres contienen ciertos parametros del propio sistema, como por ejemplo el editor de texto por defecto, los colores definidos al ejecutar un comando:P.ejm ls (tipo de archivo = color, etc...).
Nosotros nos vamos a centrar en las que nos interesan;

Para trabajar con las variables de entorno se usan los comandos set y env.
Si quiere ver las variables asignadas use env, para modificarlas use set, tambien puede ver el valor de una variable escribiendo echo  Nombre_de_la_variable.

Borrariamos la variable SHELL (vea man set o set --help para poder conocer todas opciones).


indice


Secuencias de escape

La secuencias de escape nos seran de muchisima utilidad, puesto que muestran informacion en el prompt si tener que escribir codigo nuevo.


Secuencias comunes




















En bash tambien podemos colorear los resultados, esto tambien se hace desde $PS1, asi como para poder ver los archivos en colores segun la extension, esta definido en una variable de entorno (P.ejm: LSCOLORS) para el prompt se define en la variable, pero no como una variable mas de entorno, si no dentro de la misma ($PS1).

Para incluir colores debemos encerrarlos entre \[\033[colorm\] donde color es cualquiera de los codigos que se encuentran en la tabla de abajo, la "m" es necesaria.
Para terminar con el codigo de color, \[\033[0m\], en caso contrario todo el texto que aparecera en el buffer sera del color que previamente hemos definido.


indice



Tablas de colores

Negro 0;30
Azul 0;34
Verde 0;32
Cyan 0;36
Rojo 0;31
Purpura 0;35
Marron 0;33
Gris claro 0;37
Gris oscuro 1;30
Azul claro 1;34
Verde claro 1;32
Cyan claro 1;36
Rojo claro 1;31
Purpura claro 1;35
Amarillo 1;33
blanco 1;37














Por lo tanto, si quisieramos mostrar la fecha en verde seria:


indice



Movimiento del cursor

 Por otro lado, en algunas ocasiones nos puede ser muy util cambiar otros aspectos, como el cursor, esto tiene mas usabilidad en scripts que en el propio prompt.


\033[;H Coloca el cursor en la linea L, columna C.
\033[A Mueve el cursor arriba N lineas
\033[B Mueve el cursor abajo N lineas
\033[C Mueve el cursor hacia delante N columnas
\033[D Mueve el cursor hacia atras N columnas
\033[s Guarda la posicion del cursor
\033[u Restaura la posicion del cursor






indice


Trabajando con funciones


Una funcion es un trozo de codigo dentro de un programa que se ejecuta como si fuese codigo independiente, puede ver mas sobre funciones aqui.
En nuestro caso usaremos funciones para definir aspectos de la variable $PS1, es decir usaremos funciones para declarar variables que posteriormente seran mostradas en PS1, la funcion mas basica es esta: Si usaramos esta funcion en la variable $PS1 ($PS1="$funcion_ejemplo") nos devolveria un prompt como este:

mi primera funcion$

Teniendo esto en cuenta, podemos crear funciones que nos devolveran aspectos interesantes, por ejemplo podemos hacer una funcion que nos muestre el consumo de memoria, el estado de samba, nuestra i.p publica, el espacio del disco, los archivos con una UID 0 dentro del mismo directorio de trabajo u otro, etc, etc, hay que tener en cuenta que para trabajar con funciones es necesario un conocimiento previo de como hacer scripts para bash, tambien hay que tener en cuenta que si mostramos algo demasiado largo, o que necesite mucho tiempo, repercutira en la rapidez y el aspecto del prompt.

En este  ejemplo se ha usado la funcion para definir una variable, de igual manera se pueden declarar variables como si de cualquier script se tratase.

Funciones como programas.


Otra manera de aprovechar el bash, es crear pequeñas aplicaciones, son pequeños scripts dentro de bashrc, se trata de pequeños trozos de codigo que trabajan de manera "autonoma" son otro tipo de trabajo con funciones, pero que en este caso al tratarse directamente sobre bashrc las podremos usar cuando estemos en nuestra shell, interesante ¿no?.

Sabiendo que podemos definir el bashrc de cada usuario, esto se presenta de una utilidad importante, pudiendo crear pequeños programas sin necesidad de que los usen otros usuarios, o facilitar tareas comunes.

P.ejm:

calcula()
{
echo "$*" | bc -l
}

Este ejemplo, si lo incluyeramos dentro de nuestro bashrc nos permitira usar calcula para ejecutar operaciones sobre bc.

[xento@k2 \home]$ calcula 2.3 ^3
12.167
[xento@k2 \home]$


indice


Ejemplos utiles o inutiles.

A continuacion nos dejamos de tanta teoria y hacemos un poco de practica, un par de prompts potentes, eso si hay una diferencia entre los dos, el primero resulta mas rapido, pero muestra menos informacion en la linea del prompt, el segundo en cambio muestra mas informacion en la linea del prompt, pero a cambio es mas lento.

Prompt extenso
# /etc/bashrc

if [ "`id -gn`" = "`id -un`" -a `id -u` -gt 99 ]; then
    umask 002
else
    umask 022
fi

if [ "`id -u`" -gt 99 ]; then
       .  /etc/bashrc-luser
fi

if [ "$PS1" ]; then
    case $TERM in
    xterm*)
        PROMPT_COMMAND='echo -ne "\033]0;${HOSTNAME}: ${PWD}\007"'
        ;;
    *)
        ;;
    esac

infored ()
   {

out=$(ifconfig eth0 | grep -i RX | awk '/bytes/ {print $3$4 }')
in=$(ifconfig eth0 | grep -i RX | awk '/bytes/ {print $7$8 }')
ip=$(ifconfig eth0 | awk '/addr/ {print $2 }'| cut -d: -f2 )
netuna=$(netstat -tuna | grep -v Active )
conactv=$(lsof | grep SYN_SENT)
conescucha=$(lsof -i | grep LISTEN)

echo -e "\033[0;35m[1]\033[0m" "Ver informacion en pantalla"
echo -e "\033[0;35m[2]\033[0m" "Ver informacion por puerto"
echo -e "\033[0;35m[3]\033[0m" "Ver informacion por proceso"

read opcion
case $opcion in
1)
echo -e "Salida:\033[0;34m$out\033[0m " " Entrada:\033[0;31m$in\033[0m " " IP:$ip "
echo "Conexiones de internet (servicios y establecidas)"
echo "$netuna"
echo "Procesos con conexion"
echo "$conactv"
echo "Procesos esperando conexion"
echo "$conescucha"
;;
2)
read puerto
var1=$(lsof -i :$puerto)
echo "$var1"
;;
3)
read proceso

echo "$var2"
;;
esac

    }

    function memf {
    exec free -m | grep Mem | awk '{print $4}'
}

    function memt {
    exec free -m | grep Mem | awk '{print $3}'
}

    function cuotas {
    quotastats | grep drops | awk '{print $5}'
}

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="\[[$(cuotas)] [\033[1;31m\]$(memt)\[\033[0m\]-\[\033[1;34m\] $(memf)\[\033[0m\] \W]"

if [ "x$SHLVL" != "x1" ]; then # We're not a login shell
        for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . $i
        fi
    done
    fi
fi



Como podreis ver dentro de bashrc he creado un par de scripts para poder usarlos desde mi shell, principalmente defino por un sitio que si no se es root o se tiene 0 como uid se ejecuta el archivo /etc/bashrc-lusers, de lo contrario se continua, ademas en la funcion infored, introducimos un pequeño programa para mostrar informacion util, despues tambien usamos algunas funciones para declarar variables y mostrarlas en el mismo prompt.



Prompt que muestra mucha informacion y es muy lento.

# /etc/bashrc
if [ "`id -gn`" = "`id -un`" -a `id -u` -gt 99 ]; then
    umask 002
else
    umask 022
fi

if [ "$PS1" ]; then
    if [ -x /usr/bin/tput ]; then
      if [ "x`tput kbs`" != "x" ]; then # We can't do this with "dumb" terminal
        stty erase `tput kbs`
      elif [ -x /usr/bin/wc ]; then
        if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" terminal
          stty erase `tput kbs`
        fi
      fi
    fi
    case $TERM in
    xterm*)
        if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
            PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
        else
            PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\007"'
        fi
        ;;
    screen)
        PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\033\\"'
        ;;
    *)
        [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default
        ;;
    esac
   
    function uptaim {
perl -le 'my $uptimeinfo = `uptime`;if ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up\s+(\d+)\s+day.?\W\s+(\d+):(\d+)\W\s+(\d+)\s+\ w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx) {print("$2d $3h $4m");}elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up+\s+(\d+):(\d+)\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W\s+( \d+).(\d+)/igx) {print("$2h $3m");}elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up\s+(\d+)\s+day.?\W\s+(\d+)\s+min\W\s+(\d+)\s+\ w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx) {print("$2d $3m");}elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up+\s+(\d+)\s+min\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W \s+(\d+).(\d+)/igx) {print("$2m");}print undef;'
}

    function discolibre {
perl -le 'my($disktotal,$diskusedi);for(`df`){chomp;next if !/^\/dev\/\S+/;next if /(cd|cdrom|fd|floppy)/;/^(\S+)\s+(\S+)\s+(\S+)/;$disktotal += $2;$diskused += $3;}$disktotal = sprintf("%.2f",$disktotal / 1024 / 1024);$diskused = sprintf("%.2f",$diskused / 1024 / 1024);print("$diskused-$disktotal");'
}

    function memf {
exec free -m | grep Mem | awk '{print $4}'
}

    function memt {
exec free -m | grep Mem | awk '{print $3}'
}

    function cpu {
exec top -n1 | grep "CPU" | awk '{print $3+$5"%"}'
}

function proc {
exec top -n1 | grep processes | awk '{print $1}'
}

function date2 {
exec date |  awk '{print $1"-"$3"-"$2" "$6 }'
}

function users {
exec top -n1 | grep users | awk '{print $5" Users"}'
}


    [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="\[[HD: $(discolibre) GB][Ram: \[\033[1;31m\]$(memt)\[\033[0m\]-\[\033[1;34m\]$(memf)\[\033[0m\] MB][$(cpu) Cpu][$(proc) Proc][$(users)] [$(date2)][$(date +%H:%M)]\[\033[0m\][Total: $(uptaim)][\w]
[\u\[\033[1;32m\]@\[\033[0m\]\h\[\033[0m\]:]\ \[\033[1;32m\]$\[\033[0m\]"

    if [ "x$SHLVL" != "x1" ]; then # We're not a login shell
        for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . $i
        fi
    done
    fi
fi
 

Este prompt mostraria mucha informacion, pero es realmente pesado y lento, aqui no hemos trabajado mucho en funciones que nos permitan ejecutar codigo a voluntad, si no que directamente les hemos asignado variables y las mostramos en el prompt.


Se espera que se ilustre bien como modificar un prompt y hacerlo practico a nuestras necesidades, estos ejemplos no son quizas la mejor manera de hacer las cosas, pero resultan utiles para explicar en que consiste una modificacion del prompt.


indice


Documentacion a tener en cuenta

-[http://xinfo.sourceforge.net/documentos/bash-scripting/]
    Una introduccion a la programacion en bash.

-[http://www.tldp.org/LDP/abs/html/]
    El imprescindible how-to sobre bash scripting.


indice


Sobre el documento

El presente documento se encuentra bajo terminos de la licencia FDL, se distribuye sin ninguna garantia, esta autorizada la libre distribucion, modificacion y copia, rogando que se notifique al autor cambios y aportaciones, e incluyendo al autor original cuando se haga copia total o parcial o cita del mismo, para ver mas detalles consulte la licencia GNU/FDL.
2004 (c) Xento Figal
Version 1.0

EOF

indice

Xento Figal 2004-01-11

2003 - 2005 (c) Xento Figal. Todos los contenidos bajo sus respectivas licencias: FDL/GPL - www.gnu.org

Pagina generada en 0.3120 segundos