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.
¿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.
¿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.
¿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...
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.
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;
- $SHELL , esta es la variable donde se almacenan los datos del
shell (este documento se centra en bash, tenga en cuenta que para otra
shell no podra aplicar esto) en nuestro caso deberiamos tener definida
bash
- $PS1 , En esta se almacena la informacion que mostrar el prompt,
el ambito de este documento se centra en esta variable.
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.
P.ejem:
$set -u SHELL=BASH
Borrariamos la variable SHELL (vea man set o set --help para poder
conocer todas opciones).
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
| \a |
caracter de campana ASCII(07) |
| \d |
Fecha en formato alfanumerico, dia mes hora |
| \e |
caracter de escape ASCII(033) |
| \h |
Nombre del dominio sin dominio |
| \H |
Nombre completo del host |
| \n |
caracter de nueva línea |
| \r |
Retorno de carro |
| \s |
Caracter que sigue a la última barra |
| \t |
Hora actual en formato 24-horas HH:MM:S |
| \T |
Hora actual en formato 12-horas HH:MM:SS |
| \u |
Nombre del usuario del shell |
| \v |
La versión del Bash |
| \V |
La versión del paquete del Bash |
| \w |
El directorio actual de trabajo |
| \W |
El nombre completo del directorio actual de trabajo, si
esta en /usr/local |
| \@ |
La hora actual en formato 12-horas am/pm |
| \# |
El numero de comando del comando actual |
| \! |
El numero del comando actual en el historico, esto puede
ser util para ciertos scripts |
| \$ |
Si el UID efectivo es 0, una #, sino, un $, es decir si es
root o pertence: 0, si no: $ |
| \[ |
Inicio de una secuencia de caracteres no imprimibles |
| \] |
Fin de una secuencia de caracteres no imprimibles |
| \nnn |
Un caracter correspondiente al numero octal nn |
| \\ |
Una contra barra |
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.
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:
PS1="\[\033[0;32m\][\$(date +%H%M)]$\[\033[0m\]"
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 |
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:
function funcion_ejemplo {
echo "mi primera funcion"
}
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]$
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.
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.
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
2003 - 2005 (c) Xento Figal. Todos los contenidos bajo sus respectivas licencias: FDL/GPL -
www.gnu.org
Pagina generada en 0.3120 segundos