Archivo

Archive for the ‘Administracion’ Category

Pantalla de bienvenida

Es posible crear un mensaje para que todos los usuarios que se logeen al sistema lo vean. Es, en cierta forma, similar al mensaje que aparece cuando se conectan a un servidor de IRC. El archivo en cuestión se encuentra en /etc/motd (por Message Of The Day); edítenlo a gusto y necesidad con cualquier editor de texto.

Todo en Español

Hay una forma de hacer que todos los mensajes de GNU/Linux aparezcan en español.
Para esto, hay que editar el archivo /etc/profile (el del directorio personal) y agregar las siguientes líneas:

export LANG=es
export LC_CTYPE=es_ES
export LC_ALL=es_ES

Después de hacer ésto, el sistema estará configurado totalmente en español.

Categorías: Administracion, Informacion

Migracion Linux Base

May 11, 2010 1 comentario

mkdir /root/migracion

export UGIDLIMIT=500

##migrar /etc/passwd

awk -v LIMIT=$UGIDLIMIT -F: ‘($3>=LIMIT) && ($3!=65534)’ /etc/passwd > /root/migracion/passwd.mig

##migrar /etc/group

awk -v LIMIT=$UGIDLIMIT -F: ‘($3>=LIMIT) && ($3!=65534)’ /etc/group > /root/migracion/group.mig

##migrar /etc/shadow

awk -v LIMIT=$UGIDLIMIT -F: ‘($3>=LIMIT) && ($3!=65534) {print $1}’ /etc/passwd | tee – |egrep -f – /etc/shadow > /root/migracion/shadow.mig

##migrar /etc/gshadow

cp /etc/gshadow /root/migracion/gshadow.mig

##backup home

tar -zcvpf /root/migracion/home.tar.gz /home

##Pasar

scp -r /root/migracion root@192.168.130.xxx:/root/

##IMPORTANDO

Bacapear usuario del sistema

mkdir /root/users.bk
cp /etc/passwd /etc/shadow /etc/group /etc/gshadow /root/users.bk

##Restaurar

cd /root/migracion
cat passwd.mig >> /etc/passwd
cat group.mig >> /etc/group
cat shadow.mig >> /etc/shadow
/bin/cp gshadow.mig /etc/gshadow

## Parado en el /

tar -zxvf /root/migracion/home.tar.gz

reboot

Categorías: Administracion

Quota de discos

* Instalar la característica de control de cuotas

apt-get install quota

* Indicar las particiones en las que aplicaremos las quotas editando/etc/fstab y añadiendo las opciones usrquota,grpquota

# <file system> <mount point>   <type>  <options>       <dump>  <pass>

/dev/hda5    /home    ext3    defaults,usrquota,grpquota    0    2

* Crearemos los archivos de control de quota y reiniciamos las particiones

touch /home/quota.user /home/quota.group
chmod 600 /home/quota.*
mount -o remount /home

* Para a continuación inicializar el mecanismo de cuotas

quotacheck -avugm

La primera vez obtendremos un aviso del tipo…

quotacheck: WARNING – Quotafile //quota.user was probably truncated. Can’t

save quota settings…
quotacheck: WARNING – Quotafile //quota.group was probably truncated. Can’t

save quota settings…

no hay que preocuparse.

Ahora el comando

quotaon /home

activará por fin la quota

* Editar la quota de los usuarios
Antes de nada deberíais saber que existen dos tipos de cuota:
– Cuotas rígidas: no será posible superar el límite y será negado el acceso.
– Cuotas flexibles: se pueden superar y el usuario sólo recibirá un aviso de

límite excedido. Tras un período de gracia – por defecto 7 días, configurable

por partición – la cuota se volverá rígida.

Manos a la obra, en teoría sólo root puede hacer esto y el comando es el

siguiente:

edquota -u usuario

entonces se nos mostrará una serie de registros con los siguientes campos:

Filesystem (el sistema de archivos en el que se aplica la cuota)
blocks (el número de bloques máximo a ocupar. 0 = ilimitado)
soft (el número de KB máximo a ocupar para cuota flexible. 0 = ilimitado)
hard (el número de KB máximo a ocupar para quota rígida. 0 = ilimitado)
inodes (el número de archivos máximo. 0 = ilimitado)

* Podemos copiar la configuración de un usuario con las cuotas establecidas a

otros con el comando:

edquota -p usuariomodelo usuario

Categorías: Administracion

Tutorial Iptables

IPTABLES
Manual práctico

En este manual se muestran las habituales arquitecturas de redes con firewall y la forma de montar iptables para cada caso, con distintas opciones para cada ejemplo.

1. Qué es un firewall
2. Qué es iptables
3. Al grano: creando un firewall con iptables
3.1 Proteger la propia máquina
3.2 Firewall de una LAN con salida a internet
3.3 Firewall de una LAN con salida a internet con DMZ
3.4 Firewall puro y duro entre redes
3.5 Firewall con política por defecto DROP
4. Cómo depurar el funcionamiento del firewall
Enlaces, notas, autor

1. Qué es un firewall

Un firewall es un dispositivo que filtra el tráfico entre redes, como mínimo dos. El firewall puede ser un dispositivo físico o un software sobre un sistema operativo. En general debemos verlo como una caja con DOS o mas interfaces de red en la que se establecen una reglas de filtrado con las que se decide si una conexión determinada puede establecerse o no. Incluso puede ir más allá y realizar modificaciones sobre las comunicaciones, como el NAT.

Esa sería la definición genérica, hoy en dia un firewall es un hardware especifico con un sistema operativo o una IOS que filtra el tráfico TCP/UDP/ICMP/../IP y decide si un paquete pasa, se modifica, se convierte o se descarta. Para que un firewall entre redes funcione como tal debe tener al menos dos tarjetas de red. Esta sería la tipología clásica de un firewall:

Figura 1: esquema de firewall típico entre red local e internet

Esquema típico de firewall para proteger una red local conectada a internet a través de un router. El firewall debe colocarse entre el router (con un único cable) y la red local (conectado al switch o al hub de la LAN)

Dependiendo de las necesidades de cada red, puede ponerse uno o más firewalls para establecer distintos perímetros de seguridad en torno a un sistema. Es frecuente también que se necesite exponer algún servidor a internet (como es el caso de un servidor web, un servidor de correo, etc..), y en esos casos obviamente en principio se debe aceptar cualquier conexión a ellos. Lo que se recomienda en esa situación es situar ese servidor en lugar aparte de la red, el que denominamos DMZ o zona desmilitarizada. El firewall tiene entonces tres entradas:

Figura 2: esquema de firewall entre red local e internet con zona DMZ para servidores expuestos

En la zona desmilitarizada se pueden poner tantos servidores como se necesiten. Con esta arquitectura, permitimos que el servidor sea accesible desde internet de tal forma que si es atacado y se gana acceso a él, la red local sigue protegida por el firewall. Esta estructura de DMZ puede hacerse también con un doble firewall (aunque como se ve se puede usar un único dispositivo con al menos tres interfaces de red). Sería un esquema como este:

Figura 3: esquema de firewall entre red local e internet con zona DMZ para servidores expuestos creado con doble firewall(perímetro)

Los firewalls se pueden usar en cualquier red. Es habitual tenerlos como protección de internet en las empresas, aunque ahí también suelen tener una doble función: controlar los accesos externos hacia dentro y también los internos hacia el exterior; esto último se hace con el firewall o frecuentemente con un proxy (que también utilizan reglas, aunque de más alto nivel).
También, en empresas de hosting con muchos servidores alojados lo normal es encontrarnos uno o más firewalls ya sea filtrando toda la instalación o parte de ella:

Figura 4: esquema de firewall entre redes, en la que solo se filtra y no se hace NAT

Sea el tipo de firewall que sea, generalmente no tendrá mas que un conjunto de reglas en las que se examina el origen y destino de los paquetes del protocolo tcp/ip. En cuanto a protocolos es probable que sean capaces de filtrar muchos tipos de ellos, no solo los tcp, también los udp, los icmp, los gre y otros protocolos vinculados a vpns. Este podría ser (en pseudo-lenguaje) un el conjunto de reglas de un firewall del primer gráfico:

Politica por defecto ACEPTAR.
Todo lo que venga de la red local al firewall ACEPTAR
Todo lo que venga de la ip de mi casa al puerto tcp 22 ACEPTAR
Todo lo que venga de la ip de casa del jefe al puerto tcp 1723 ACEPTAR
Todo lo que venga de hora.rediris.es al puerto udo 123 ACEPTAR
Todo lo que venga de la red local y vaya al exterior ENMASCARAR
Todo lo que venga del exterior al puerto tcp 1 al 1024 DENEGAR
Todo lo que venga del exterior al puerto tcp 3389 DENEGAR
Todo lo que venga del exterior al puerto udp 1 al 1024 DENEGAR

En definitiva lo que se hace es:
– Habilita el acceso a puertos de administración a determinadas IPs privilegiadas
– Enmascara el trafico de la red local hacia el exterior (NAT, una petición de un pc de la LAN sale al exterior con la ip pública), para poder salir a internet
– Deniega el acceso desde el exterior a puertos de administración y a todo lo que este entre 1 y 1024.

Hay dos maneras de implementar un firewall:
1) Política por defecto ACEPTAR: en principio todo lo que entra y sale por el firewall se acepta y solo se denegará lo que se diga explícitamente.
2) Política por defecto DENEGAR: todo esta denegado, y solo se permitirá pasar por el firewall aquellos que se permita explícitamente.

Como es obvio imaginar, la primera política facilita mucho la gestión del firewall, ya que simplemente nos tenemos que preocupar de proteger aquellos puertos o direcciones que sabemos que nos interesa; el resto no importa tanto y se deja pasar. Por ejemplo, si queremos proteger una máquina linux, podemos hacer un netstat -ln (o netstat -an, o netstat -puta | grep LISTEN), saber que puertos están abiertos, poner reglas para proteger esos puertos y ya está. ¿Para qué vamos a proteger un puerto que realmente nunca se va a abrir?
El único problema que podemos tener es que no controlemos que es lo que esta abierto, o que en un momento dado se instale un software nuevo que abra un puerto determinado, o que no sepamos que determinados paquetes ICMP son peligrosos. Si la política por defecto es ACEPTAR y no se protege explícitamente, nos la estamos jugando un poco.

En cambio, si la política por defecto es DENEGAR, a no ser que lo permitamos explícitamente, el firewall se convierte en un auténtico MURO infranqueable. El problema es que es mucho más difícil preparar un firewall así, y hay que tener muy claro como funciona el sistema (sea iptables o el que sea) y que es lo que se tiene que abrir sin caer en la tentación de empezar a meter reglas super-permisivas.
Esta configuración de firewall es la recomendada, aunque no es aconsejable usarla si no se domina mínimamente el sistema. Uno de los objetos principales de este documento es mostrar la forma de crear este tipo de firewalls.

IMPORTANTE
El orden en el que se ponen las reglas de firewall es determinante. Normalmente cuando hay que decidir que se hace con un paquete se va comparando con cada regla del firewall hasta que se encuentra una que le afecta (match), y se hace lo que dicte esta regla (aceptar o denegar); después de eso NO SE MIRARÁN MÁS REGLAS para ese paquete. ¿Cuál es el peligro? Si ponemos reglas muy permisivas entre las primeras del firewall, puede que las siguientes no se apliquen y no sirvan de nada.

2. Qué es iptables

IPtables es un sistema de firewall vinculado al kernel de linux que se ha extendido enormemente a partir del kernel 2.4 de este sistema operativo. Al igual que el anterior sistema ipchains, un firewall de iptables no es como un servidor que lo iniciamos o detenemos o que se pueda caer por un error de programación(esto es una pequeña mentira, ha tenido alguna vulnerabilidad que permite DoS, pero nunca tendrá tanto peligro como las aplicaciones que escuchan en determinado puerto TCP): iptables esta integrado con el kernel, es parte del sistema operativo. ¿Cómo se pone en marcha? Realmente lo que se hace es aplicar reglas. Para ellos se ejecuta el comando iptables, con el que añadimos, borramos, o creamos reglas. Por ello un firewall de iptables no es sino un simple script de shell en el que se van ejecutando las reglas de firewall.

Notas: bueno, para los más geeks y tocapelotas. Vale, se puede implementar un script de inicio en /etc/rc.d/INIT.d (o /etc/INIT.d ) con el que hagamos que iptables se «inicie o pare» como un servidor más. Lo podemos hacer nosotros o es probable que venga en la distribución (como en redhat por ejemplo). También se pueden salvar las reglas aplicadas con el comando iptables-save en un fichero y gestionar ese fichero con una aplicación o front-end desde la X o desde webmin.

Vale, tenemos una máquina linux con soporte para iptables, tiene reglas aplicadas y empiezan a llegar/salir/pasar paquetes. No nos liemos: olvidemos cuantas tarjetas de red hay, que direcciones ip tiene la máquina y olvidemos si el paquete entra o sale. Las reglas de firewall están a nivel de kernel, y al kernel lo que le llega es un paquete (digamos, un marrón 😉 ) y tiene que decidir que hacer con él. El kernel lo que hace es, dependiendo si el paquete es para la propia maquina o para otra maquina, consultar las reglas de firewall y decidir que hacer con el paquete según mande el firewall. Este es el camino que seguiría un paquete en el kernel:

Figura 5: cuando un paquete u otra comunicación llega al kernel con iptables se sigue este camino

Como se ve en el gráfico, básicamente se mira si el paquete esta destinado a la propia maquina o si va a otra. Para los paquetes (o datagramas, según el protocolo) que van a la propia maquina se aplican las reglas INPUT y OUTPUT, y para filtrar paquetes que van a otras redes o maquinas se aplican simplemente reglas FORWARD.
INPUT,OUTPUT y FORWARD son los tres tipos de reglas de filtrado. Pero antes de aplicar esas reglas es posible aplicar reglas de NAT: estas se usan para hacer redirecciones de puertos o cambios en las IPs de origen y destino. Veremos ejemplos.
E incluso antes de las reglas de NAT se pueden meter reglas de tipo MANGLE, destinadas a modificar los paquetes; son reglas poco conocidas y es probable que no las usen.
Por tanto tenemos tres tipos de reglas en iptables:
– MANGLE
– NAT: reglas PREROUTING, POSTROUTING
– FILTER: reglas INPUT, OUTPUT, FORWARD.

3. Al grano: creando un firewall con iptables

En este tutorial se ha intentado dar una breve introducción sobre lo que es un firewall, sus tipologías básicas y en concreto se presenta el sistema iptables. Pero vamos al grano y empezamos a ver configuraciones de firewall con iptables, empezando desde la más básica a las más complejas, en las que se establece la denegación como política por defecto.

Nota: se recomienda encarecidamente ir practicando estas reglas en alguna maquina linux disponible, y especialmente hacer uso de la herramienta iptraf para depurar y comprobar el funcionamiento de iptables. Con iptraf podemos comprobar si las conexiones TCP/IP se llegan a establecer o no. Una conexión tcp/ip empieza con el three-way-handshake:
– La maquina que desea conectarse a otra envia un paquete con flan SYN
– Si la otra maquina acepta, envia un SYN/ACK
– Entonces la máquina establece la conexión.

Si el firewall esta denegando la conexión, con iptraf veremos que la maquina origen solo manda paquetes con el flan S (de SYN), y que del otro lado no sale nada. Saber usar iptraf nos ayudará mucho.

3.1 Proteger la propia máquina
Muy bien, tenemos una máquina linux pinchada en internet y queremos protegerla con su propio firewall. Lo único que tenemos que hacer es crear un script de shell en el que se van aplicando las reglas.
Los scripts de iptables pueden tener este aspecto:

Saludo a la afición (echo)
Borrado de las reglas aplicadas actualmente (flush)
Aplicación de políticas por defecto para INPUT, OUPUT, FORWARD
Listado de reglas iptables.

Ojo con el orden de las reglas!

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para proteger la propia máquina
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar

# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# A nuestra IP le dejamos todo
iptables -A INPUT -s 195.65.34.234 -j ACCEPT

# A un colega le dejamos entrar al mysql para que mantenga la BBDD
iptables -A INPUT -s 231.45.134.23 -p tcp –dport 3306 -j ACCEPT

# A un diseñador le dejamos usar el FTP
iptables -A INPUT -s 80.37.45.194 -p tcp -dport 20:21 -j ACCEPT

# El puerto 80 de www debe estar abierto, es un servidor web.
iptables -A INPUT -p tcp –dport 80 -j ACCEPT

# Y el resto, lo cerramos
iptables -A INPUT -p tcp –dport 20:21 -j DROP
iptables -A INPUT -p tcp –dport 3306 -j DROP
iptables -A INPUT -p tcp –dport 22 -j DROP
iptables -A INPUT -p tcp –dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Nota para freaks y geeks: siiii, que ya lo se, se puede mejorar este script usando variables, se puede poner el comando con el path completo, pero limítense a hacer copy-paste. Para el resto de mortales, no olvidarse de ponerle flags de ejecución: chmod +x firewall1.sh o chmod 750 firewall1.sh

En fin, ya se ve, un script de los más simple, con unas pocas reglas con las que cerramos puertos al público a los que no tienen porque tener acceso, salvo el 80. Pero cualquiera con algo de ojo se habrá dado cuenta de que ni se filtra el UDP ni el ICMP. Apostaría cualquier cosa a que el sistema tiene algún puerto udp abierto, y además peligroso como el SNMP. Como he dicho anteriormente, en este tipo de firewall es recordable hacer un netstat para ver que puertos están en estado de escucha (abiertos), y salve que un rootkit nos haya modificado los binarios, netstat nos dará la información precisa que necesitamos. Hay gente que se decanta por hacerse un nmap así mismos. Cuidado: dependiendo de cómo lo ejecutemos quizá no nos muestre todos los puertos, ya que suele mirar los bien conocidos.
Imaginemos que hemos dado un repaso a nuestro sistema, y ahora si que tenemos mejor identificados los puertos tcp y udp abiertos. Pero por si acaso nos curamos en salud y al final del script cerraremos el rango de puertos del 1 al 1024, los reservados tanto para tcp como udp.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para proteger la propia máquina
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar

# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# A nuestra IP le dejamos todo
iptables -A INPUT -s 195.65.34.234 -j ACCEPT

# A un colega le dejamos entrar al mysql para que mantenga la BBDD
iptables -A INPUT -s 231.45.134.23 -p tcp –dport 3306 -j ACCEPT

# A un diseñador le dejamos usar el FTP
iptables -A INPUT -s 80.37.45.194 -p tcp -dport 20:21 -j ACCEPT

# El puerto 80 de www debe estar abierto, es un servidor web.
iptables -A INPUT -p tcp –dport 80 -j ACCEPT

# Cerramos rango de los puertos privilegiados. Cuidado con este tipo de
# barreras, antes hay que abrir a los que si tienen acceso.
iptables -A INPUT -p tcp –dport 1:1024
iptables -A INPUT -p udp –dport 1:1024

# Cerramos otros puertos que estan abiertos
iptables -A INPUT -p tcp –dport 3306 -j DROP
iptables -A INPUT -p tcp –dport 10000 -j DROP
iptables -A INPUT -p udp –dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

¿Sencillo, no? Ahora basta con hacer copy-paste de estas reglas y aplicarlas y ajustarlas en su sistema (quizás uses PostgreSQL). Si tiene miedo de perder el control de una máquina remota, pruebe el script en una máquina local y asegúrese de que aplica lo que usted quiere. Funcionar va a funcionar seguro.

3.2 Firewall de una LAN con salida a internet
Ahora vamos a ver una configuración de firewall iptables para el típico caso de red local que necesita salida a internet.

Figura 6: esquema de firewall típico entre red local e internet

¿Qué es lo que hace falta? Obviamente, una regla que haga NAT hacia fuera (enmascaramiento en iptables), con lo que se haría dos veces NAT en el firewall y en el router. Entre el router y el firewall lo normal es que haya una red privada (192.168.1.1 y 192.168.1.2 por ejemplo), aunque dependiendo de las necesidades puede que los dos tengan IP pública. El router se supone que hace un NAT completo hacia dentro (quizá salvo puerto 23), o sea que desde el exterior no se llega al router si no que de forma transparente se «choca» contra el firewall. Lo normal en este tipo de firewalls es poner la política por defecto de FORWARD en denegar (DROP), pero eso lo vemos más adelante.
Veamos como sería este firewall-gateway:

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet
##
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN
# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

# Ahora hacemos enmascaramiento de la red local
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Pero como somos muy malvados queremos que los empleados solamente puedan navegar por internet, denegando el acceso a Kazaa o edonkey. Esta sería una configuración simple pero efectiva.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet
## con filtro para que solo se pueda navegar.
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN
# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

## Ahora con regla FORWARD filtramos el acceso de la red local
## al exterior. Como se explica antes, a los paquetes que no van dirigidos al
## propio firewall se les aplican reglas de FORWARD

# Aceptamos que vayan a puertos 80
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 80 -j ACCEPT
# Aceptamos que vayan a puertos https
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 443 -j ACCEPT

# Aceptamos que consulten los DNS
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p udp –dport 53 -j ACCEPT

# Y denegamos el resto. Si se necesita alguno, ya avisaran
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -j DROP

# Ahora hacemos enmascaramiento de la red local
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Supongamos que este firewall tiene alguna función adicional: es un servidor proxy y además es un servidor de correo. Darle funcionalidades de este tipo a un firewall no es recomendable, porque si no se protegen bien esos puertos o si no está actualizado el software pueden entrar en el firewall a base de xploits comprometiendo TODA la red local. De todas formas muchas empresas no se pueden permitir o no quieren tener una máquina para cada cosa, bastante les cuesta a muchas poner un firewall. Por tanto: si se añaden servicios que deben estar abiertos al público en el propio firewall, nos la estamos jugando, y se recomienda pasar el servicio a otra máquina y ponerla en la DMZ.
Supongamos también que la empresa tiene comerciales en ruta y que se conectan a internet desde su portátil y con una ip dinámica. Supongamos también que el jefe de la empresa quiere acceder a la red local desde casa con una conexión ADSL. Ahora en el firewall debieramos tener instalado un servidor SMTP, pop3, y un PPTPD.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet
## con servicios abiertos de puerto 25, 110, y 1723
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN
# El localhost se deja (por ejemplo conexiones locales a mysql)
iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

## Abrimos el acceso a puertos de correo

# Abrimos el puerto 25, hay que configurar bien el relay del servidor SMTP
iptables -A INPUT -s 0.0.0.0/0 -p tcp –dport 25 -j ACCEPT
# Abrimos el pop3
iptables -A INPUT -s 0.0.0.0/0 -p tcp –dport 110 -j ACCEPT

# Y abrimos el puerto pptpd para la ip del adsl de casa del jefe
iptables -A INPUT -s 211.45.176.24 -p tcp –dport 1723 -j ACCEPT

## Ahora con regla FORWARD filtramos el acceso de la red local
## al exterior. Como se explica antes, a los paquetes que no van dirigidos al
## propio firewall se les aplican reglas de FORWARD

# Aceptamos que vayan a puertos 80
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 80 -j ACCEPT
# Aceptamos que vayan a puertos https
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 443 -j ACCEPT

# Aceptamos que consulten los DNS
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p udp –dport 53 -j ACCEPT

# Y denegamos el resto. Si se necesita alguno, ya avisaran
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -j DROP

# Ahora hacemos enmascaramiento de la red local
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp –dport 10000 -j DROP

# Y cerramos el puerto del servicio PPTPD, solo abierto para el jefe.
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp –dport 1723 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

¡Más difícil todavía!
Ahora queremos compartir algún servicio pero de un servidor que tenemos dentro de la red local, por ejemplo el IIS de un servidor windows2000, y además permitir la gestión remota por terminal server para esta máquina para una empresa externa. En este caso lo que hay que hacer es un redirección de puerto. Antes de iptables esto se podía hacer fácilmente con un servidor como rinet. Rinet lo que hace es simplemente abrir un puerto en el firewall y al conectarse a él te lleva hasta el puerto de otra máquina, como una tubería. Con Iptables podemos hacer redirecciones con una ventaja: no perdemos la información de IP origen, cosa que con rinet sí ocurría. En fin, veamos la configuración, con las nuevas reglas de DNAT:

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet
## con servicios abiertos de puerto 25, 110, y 1723
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar

## REDIRECCIONES

# Todo lo que venga por el exterior y vaya al puerto 80 lo redirigimos
# a una maquina interna
iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 80 -j DNAT –to 192.168.10.12:80

# Los accesos de un ip determinada a Terminal server se redirigen e esa
# maquina
iptables -t nat -A PREROUTING -s 221.23.124.181 -i eth0 -p tcp –dport 3389 -j DNAT –to 192.168.10.12:3389

## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN
# El localhost se deja (por ejemplo conexiones locales a mysql)
iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

## Abrimos el acceso a puertos de correo

# Abrimos el puerto 25, hay que configurar bien el relay del servidor SMTP
iptables -A INPUT -s 0.0.0.0/0 -p tcp –dport 25 -j ACCEPT
# Abrimos el pop3
iptables -A INPUT -s 0.0.0.0/0 -p tcp –dport 110 -j ACCEPT

# Y abrimos el puerto pptpd para la ip del adsl de casa del jefe
iptables -A INPUT -s 211.45.176.24 -p tcp –dport 1723 -j ACCEPT

## Ahora con regla FORWARD filtramos el acceso de la red local
## al exterior. Como se explica antes, a los paquetes que no van dirigidos al
## propio firewall se les aplican reglas de FORWARD

# Aceptamos que vayan a puertos 80
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 80 -j ACCEPT
# Aceptamos que vayan a puertos https
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 443 -j ACCEPT

# Aceptamos que consulten los DNS
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p tcp –dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -p udp –dport 53 -j ACCEPT

# Y denegamos el resto. Si se necesita alguno, ya avisaran
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -j DROP

# Ahora hacemos enmascaramiento de la red local
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp –dport 10000 -j DROP

# Y cerramos el puerto del servicio PPTPD, solo abierto para el jefe.
iptables -A INPUT -s 0.0.0.0/0 -i eth0 -p tcp –dport 1723 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Bueno ya tenemos montada la red, pero conviene insistir en que esta última configuración, con las redirecciones y los servicios de correo funcionando en el firewall es bastante insegura. ¿Qué ocurre si hackean el servidor IIS de la red local? Pues que el firewall no sirve de gran cosa, lo poco que podría hacer una vez se ha entrado en la red local es evitar escaneos hacia el exterior desde la máquina atacada, aunque para ello el firewall debiera tener una buena configuración con denegación por defecto. Si necesitamos ese servidor IIS, basta con comprar una tarjeta de red por 6€ o dolares y crear una DMZ.

3.3 Firewall de una LAN con salida a internet con DMZ

Bueno, esto se va complicando. Imaginemos que tenemos una red parecida a la anterior pero ahora hacemos las cosas bien y colocamos ese servidor IIS en una DMZ:

Figura 7: esquema de firewall entre red local e internet con zona DMZ para servidores expuestos

En este tipo de firewall hay que permitir:
– Acceso de la red local a internet.
– Acceso público al puerto tcp/80 y tcp/443 del servidor de la DMZ
– Acceso del servidor de la DMZ a una BBDD de la LAN
– Obviamente bloquear el resto de acceso de la DMZ hacia la LAN.
¿Qué tipo de reglas son las que hay que usar para filtrar el tráfico entre la DMZ y la LAN? Solo pueden ser las FORWARD, ya que estamos filtrando entre distintas redes, no son paquetes destinados al propio firewall.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet con DMZ
##
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN
# Todo lo que venga por el exterior y vaya al puerto 80 lo redirigimos
# a una maquina interna
iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 80 -j DNAT –to 192.168.3.2:80

# Los accesos de un ip determinada HTTPS se redirigen e esa
# maquina
iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 443 -j DNAT –to 192.168.3.2:443

# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

# Ahora hacemos enmascaramiento de la red local y de la DMZ
# para que puedan salir haca fuera
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Permitimos el paso de la DMZ a una BBDD de la LAN:
iptables -A FORWARD -s 192.168.3.2 -d 192.168.10.5 -p tcp –dport 5432 -j ACCEPT

iptables -A FORWARD -s 192.168.10.5 -d 192.168.3.2 -p tcp –sport 5432 -j ACCEPT

## permitimos abrir el Terminal server de la DMZ desde la LAN
iptables -A FORWARD -s 192.168.10.0/24 -d 192.168.3.2 -p tcp –sport 1024:65535 –dport 3389 -j ACCEPT

# … hay que hacerlo en uno y otro sentido …
iptables -A FORWARD -s 192.168.3.2 -d 192.168.10.0/24 -p tcp –sport 3389 –dport 1024:65535 -j ACCEPT

# … por que luego:
# Cerramos el acceso de la DMZ a la LAN
iptables -A FORWARD -s 192.168.3.0/24 -d 192.168.10.0/24 -j DROP

## Cerramos el acceso de la DMZ al propio firewall
iptables -A INPUT -s 192.168.3.0/24 -i eth2 -j DROP

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Vamos a ver: si las máquinas de la DMZ tienen una ip pública hay que tener muchísimo cuidado de no permitir el FORWARD por defecto. Si en la DMZ hay ip pública NO ES NECESARIO HACER REDIRECCIONES de puerto, sino que basta con rutar los paquetes para llegar hasta la DMZ. Este tipo de necesidades surgen cuando por ejemplo tenemos dos máquinas con servidor web (un apache y un IIS); ¿A cuál de las dos le redirigimos el puerto 80? No hay manera de saberlo (No, con servidores virtuales tampoco, piénsalo), por eso se deben asignar IPs públicas o en su defecto usar puertos distintos.
Por tanto hay que proteger convenientemente toda la DMZ. Tampoco haría falta enmascarar la salida hacia el exterior de la DMZ, si tiene una ip pública ya tiene una pata puesta en internet; obviamente hay que decirle al router como llegar hasta esa ip pública. Así podría ser esta red:

Figura 8: esquema de firewall entre red local e internet con zona DMZ para servidores expuestos usando IPs públicas

Y este podría ser un firewall adecuado:
#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre red-local e internet con DMZ
## pero con IPs públicas.
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN

# El localhost se deja (por ejemplo conexiones locales a mysql)
/sbin/iptables -A INPUT -i lo -j ACCEPT

# Al firewall tenemos acceso desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT

# Ahora hacemos enmascaramiento de la red local y de la DMZ
# para que puedan salir haca fuera
# y activamos el BIT DE FORWARDING (imprescindible!!!!!)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

# Con esto permitimos hacer forward de paquetes en el firewall, o sea
# que otras máquinas puedan salir a traves del firewall.
echo 1 > /proc/sys/net/ipv4/ip_forward

## Permitimos el acceso desde el exterior a los puertos 80 y 443 de DMZ
iptables -A FORWARD -d 212.194.89.152 -p tcp -dport 80 -j ACCEPT
iptables -A FORWARD -d 212.194.89.152 -p tcp -dport 443 -j ACCEPT
iptables -A FORWARD -d 212.194.89.150/30 -j DROP

## Permitimos el paso de la DMZ a una BBDD de la LAN:
iptables -A FORWARD -s 212.194.89.152 -d 192.168.10.5 -p tcp –dport 5432 -j ACCEPT

# en el otro sentido lo mismo
iptables -A FORWARD -s 192.168.10.5 -d 212.194.89.152 -p tcp –sport 5432 -j ACCEPT

## permitimos abrir el Terminal server de la DMZ desde la LAN
iptables -A FORWARD -s 192.168.10.0/24 -d 212.194.89.152 -p tcp –sport 1024:65535 –dport 3389 -j ACCEPT

# … hay que hacerlo en uno y otro sentido …
iptables -A FORWARD -s 212.194.89.152 -d 192.168.10.0/24 -p tcp –sport 3389 –dport 1024:65535 -j ACCEPT

# … por que luego:
# Cerramos el acceso de la DMZ a la LAN
iptables -A FORWARD -s 212.194.89.152 -d 192.168.10.0/24 -j DROP

## Cerramos el acceso de la DMZ al propio firewall
iptables -A INPUT -s 212.194.89.152 -i eth2 -j DROP

## Y ahora cerramos los accesos indeseados del exterior:
# Nota: 0.0.0.0/0 significa: cualquier red

# Cerramos el rango de puerto bien conocido
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp -dport 1:1024 -j DROP

# Cerramos un puerto de gestión: webmin
iptables -A INPUT -s 0.0.0.0/0 -p tcp -dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

ATENCIÓN
Merece la pena pararse a explicar esta parte del firewall:

## permitimos abrir el Terminal server de la DMZ desde la LAN
iptables -A FORWARD -s 192.168.10.0/24 -d 212.194.89.152 -p tcp -sport 1024:65535 –dport 3389 -j ACCEPT

# … hay que hacerlo en uno y otro sentido …
iptables -A FORWARD -s 212.194.89.152 -d 192.168.10.0/24 -p tcp –sport 3389 –dport 1024:65535 -j ACCEPT

# … por que luego:
# Cerramos el acceso de la DMZ a la LAN
iptables -A FORWARD -s 212.194.89.152 -d 192.168.10.0/24 -j DROP

Lo que nos lleva a dos cuestiones:
¿Por qué hay que explicitar la abertura en uno y otro sentido? Porque la tercera regla cierra todo lo que va de la DMZ a la red local. Para abrir el puerto 3389 de tcp es imprescindible que un paquete de ida sea capaz de llegar hasta la DMZ y que a su vez pueda volver a la LAN. Esto de tener que especificar la abertura en uno y otro sentido será el pan de cada día en un iptables con política DROP por defecto: mejor protección pero más trabajo.

¿Por qué se explicita el puerto de origen/destino 1024:65535 en la primera y segunda regla? Imaginemos que un hacker logra acceso a la máquina de la DMZ. Si no especificamos el puerto de destino en esas dos reglas, el hacker puede abrir CUALQUIER puerto de la LAN siempre que pueda establecer como puerto origen suyo el tcp/3389, cosa fácil para un hacker que sepa algo de C o que tenga el programa pertinente a mano. De todas formas el hacker tendría que saber que existe ese tipo de reglas, si es listo probara con puertos de gestión o con puertos netbios. El problema es que se deja un vínculo con la LAN bien para administrarlo remotamente o para establecer relaciones de confianza y ahí es donde reside el peligro.

En las conexiones «legales» no se usa como puerto origen nada por debajo del 1024; cuando alguien se conecta a otro puerto en su extremo abre un puerto por encima del 1024. Especificándolo en la regla de firewall protegeremos un poco mejor la LAN, aunque los puertos por encima de 1024 estarán en peligro.

3.4 Firewall puro y duro entre redes

En este caso olvidémonos de redes locales y de NAT. Aquí solo tendremos reglas de filtrado INPUT y FORWARD. Pongamos que tenemos el siguiente escenario:

Figura 9: esquema de firewall entre redes, en la que solo se filtra y no se hace NAT

En el firewall debemos indicar una serie de reglas para proteger los equipos que están al otro lado de este dispositivo, todos ellos de la red 211.34.149.0/24
Cada uno de ellos da un servicio determinado, y puede estar gestionado desde distintas IPs, lo que significa que habrá que dar acceso a determinados puertos de gestión (22, 3389, etc..).
Este podría ser el aspecto del script del firewall:

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre redes.
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN

# A nuestro firewall tenemos acceso total desde la nuestra IP
iptables -A INPUT -s 210.195.55.15 -j ACCEPT

# Para el resto no hay acceso al firewall
iptables -A INPUT -s 0.0.0.0/0 -j DROP

## Ahora podemos ir metiendo las reglas para cada servidor
## Como serán paquetes con destino a otras máquinas se aplica FORWARD

## Servidor WEB 211.34.149.2
# Acceso a puerto 80
iptables -A FORWARD -d 211.34.149.2 -p tcp –dport 80 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.2 -p tcp –dport 22 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.2 -j DROP

## Servidor MAIL 211.34.149.3
# Acceso a puerto 25, 110 y 143
iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 25 -j ACCEPT
iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 110 -j ACCEPT
iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 143 -j ACCEPT

# Acceso a gestion SNMP
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.3 -p udp –dport 169 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.3 -p tcp –dport 22 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.3 -j DROP

## Servidor IRC 211.34.149.4
# Acceso a puertos IRC
iptables -A FORWARD -d 211.34.149.4 -p tcp –dport 6666:6668 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.4 -p tcp –dport 22 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.4 -j DROP

## Servidor NEWS 211.34.149.5
# Acceso a puerto news
iptables -A FORWARD -d 211.34.149.5 -p tcp –dport news -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 213.194.68.115 -d 211.34.149.5 -p tcp –dport 22 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.5 -j DROP

## Servidor B2B 211.34.149.6
# Acceso a puerto 443
iptables -A FORWARD -d 211.34.149.6 -p tcp –dport 443 -j ACCEPT

# Acceso a una ip para gestionarlo
iptables -A FORWARD -s 81.34.129.56 -d 211.34.149.6 -p tcp –dport 3389 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.6 -j DROP

## Servidor CITRIX 211.34.149.7
# Acceso a puerto 1494
iptables -A FORWARD -d 211.34.149.7 -p tcp –dport 1494 -j ACCEPT

# Acceso a una ip para gestionarlo
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p tcp –dport 3389 -j ACCEPT

# acceso a otro puerto quiza de BBDD
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p tcp –dport 1434 -j ACCEPT

# acceso a otro puerto quiza de BBDD
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p udp –dport 1433 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.7 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Con esta firewall y sobretodo gracias a las reglas de DROP que metemos tras especificar lo que dejamos abiertos, protegeremos de manera eficaz todos lo puertos abiertos de las máquinas.

3.5 Firewall con política por defecto DROP

Aquí llega la sección para los auténticos administradores de pelo en pecho.
¿Qué supone el hecho de establecer como política por defecto la denegación?
» Se debe explicitar cada conexión permitida en los dos sentidos.
» Se debe conocer perfectamente qué debe estar abierto y qué no.
» Es muchos más difícil de mantener y si se hace conviene hacerlo desde el principio.
» No todo es más trabajo: también supone un firewall mucho más seguro.

En el ejemplo de la DMZ ya se presentaba esta situación en las reglas forward de una a otra red. Para ilustrar el DROP por defecto, vamos a mostrar la configuración del ejemplo anterior de firewall entre redes pero con política por defecto DROP.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para firewall entre redes con DROP por defecto
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto: DROP!!!
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

## Empezamos a filtrar
## Nota: eth0 es el interfaz conectado al router y eth1 a la LAN

# A nuestro firewall tenemos acceso total desde la nuestra IP
iptables -A INPUT -s 210.195.55.15 -j ACCEPT
iptables -A OUTPUT -d 210.195.55.15 -j ACCEPT

# Para el resto no hay acceso al firewall
# En principio esta de más, pero si rebajamos los permisos temporalmente
# nos cubre las espaldas
iptables -A INPUT -s 0.0.0.0/0 -j DROP

## Ahora podemos ir metiendo las reglas para cada servidor
## Como serán paquetes con destino a otras máquinas se aplica FORWARD

## Servidor WEB 211.34.149.2
# Acceso a puerto 80
iptables -A FORWARD -d 211.34.149.2 -p tcp –dport 80 -j ACCEPT
iptables -A FORWARD -s 211.34.149.2 -p tcp –sport 80 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.2 -p tcp –dport 22 -j ACCEPT

iptables -A FORWARD -s 211.34.149.2 -d 210.195.55.15 -p tcp –sport 22 -j ACCEPT

## Servidor MAIL 211.34.149.3
# Acceso a puerto 25, 110 y 143
iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 25 -j ACCEPT
iptables -A FORWARD -s 211.34.149.3 -p tcp –sport 25 -j ACCEPT

iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 110 -j ACCEPT
iptables -A FORWARD -s 211.34.149.3 -p tcp –sport 110 -j ACCEPT

iptables -A FORWARD -d 211.34.149.3 -p tcp –dport 143 -j ACCEPT
iptables -A FORWARD -s 211.34.149.3 -p tcp –sport 143 -j ACCEPT

# Acceso a gestion SNMP
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.3 -p udp –dport 169 -j ACCEPT

iptables -A FORWARD -s 211.34.149.3 -d 210.195.55.15 -p udp –sport 169 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.3 -p tcp –dport 22 -j ACCEPT

iptables -A FORWARD -s 211.34.149.3 -d 210.195.55.15 -p tcp –sport 22 -j ACCEPT

## Servidor IRC 211.34.149.4
# Acceso a puertos IRC
iptables -A FORWARD -d 211.34.149.4 -p tcp –dport 6666:6668 -j ACCEPT
iptables -A FORWARD -s 211.34.149.4 -p tcp –sport 6666:6668 -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 210.195.55.15 -d 211.34.149.4 -p tcp –dport 22 -j ACCEPT

iptables -A FORWARD -s 211.34.149.4 -d 210.195.55.15 -p tcp –sport 22 -j ACCEPT

## Servidor NEWS 211.34.149.5
# Acceso a puerto news
iptables -A FORWARD -d 211.34.149.5 -p tcp –dport news -j ACCEPT
iptables -A FORWARD -s 211.34.149.5 -p tcp –sport news -j ACCEPT

# Acceso a nuestra ip para gestionarlo
iptables -A FORWARD -s 213.194.68.115 -d 211.34.149.5 -p tcp –dport 22 -j ACCEPT

iptables -A FORWARD -s 211.34.149.5 -d 213.194.68.115 -p tcp –sport 22 -j ACCEPT

# El resto, cerrar
iptables -A FORWARD -d 211.34.149.5 -j DROP

## Servidor B2B 211.34.149.6
# Acceso a puerto 443
iptables -A FORWARD -d 211.34.149.6 -p tcp –dport 443 -j ACCEPT
iptables -A FORWARD -s 211.34.149.6 -p tcp –sport 443 -j ACCEPT

# Acceso a una ip para gestionarlo
iptables -A FORWARD -s 81.34.129.56 -d 211.34.149.6 -p tcp –dport 3389 -j ACCEPT

iptables -A FORWARD -s 211.34.149.6 -d 81.34.129.56 -p tcp –sport 3389 -j ACCEPT

## Servidor CITRIX 211.34.149.7
# Acceso a puerto 1494
iptables -A FORWARD -d 211.34.149.7 -p tcp –dport 1494 -j ACCEPT
iptables -A FORWARD -s 211.34.149.7 -p tcp –sport 1494 -j ACCEPT

# Acceso a una ip para gestionarlo
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p tcp –dport 3389 -j ACCEPT

iptables -A FORWARD -s 211.34.149.7 -d 195.55.234.2 -p tcp –sport 3389 -j ACCEPT

# acceso a otro puerto quiza de BBDD
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p tcp –dport 1434 -j ACCEPT

iptables -A FORWARD -s 211.34.149.7 -d 195.55.234.2 -p tcp –sport 1434 -j ACCEPT

# acceso a otro puerto quiza de BBDD
iptables -A FORWARD -s 195.55.234.2 -d 211.34.149.7 -p udp –dport 1433 -j ACCEPT

iptables -A FORWARD -s 211.34.149.7 -d 195.55.234.2 -p udp –sport 1433 -j ACCEPT

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

Ya esta, hemos levantado un verdadero muro entre internet y el conjunto de servidores que esta
Tras el firewall. No se puede ni hacer un ping a las máquinas, salvo que se haya dado acceso total a una ip. Si quisieramos dar acceso al ping, pondríamos algo así:

Es más llevadero aplicar el DROP por defecto cuando el firewall es para la propia máquina. El primer escenario de esta manual trataba sobre este caso, ahora lo revisamos con la política por defecto drop.

#!/bin/sh
## SCRIPT de IPTABLES – ejemplo del manual de iptables
## Ejemplo de script para proteger la propia máquina
## con política por defecto DROP
## Pello Xabier Altadill Izura
## http://www.pello.infopello@pello.info

echo -n Aplicando Reglas de Firewall…

## FLUSH de reglas
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

## Establecemos politica por defecto
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

## Empezamos a filtrar

# El localhost se deja (por ejemplo conexiones locales a mysql)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# A nuestra IP le dejamos todo
iptables -A INPUT -s 195.65.34.234 -j ACCEPT
iptables -A OUTPUT -d 195.65.34.234 -j ACCEPT

# A un colega le dejamos entrar al mysql para que mantenga la BBDD
iptables -A INPUT -s 231.45.134.23 -p tcp –dport 3306 -j ACCEPT
iptables -A OUTPUT -d 231.45.134.23 -p tcp –sport 3306 -j ACCEPT

# A un diseñador le dejamos usar el FTP
iptables -A INPUT -s 80.37.45.194 -p tcp –dport 20:21 -j ACCEPT
iptables -A OUTPUT -d 80.37.45.194 -p tcp –sport 20:21 -j ACCEPT

# El puerto 80 de www debe estar abierto, es un servidor web.
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp –sport 80 -j ACCEPT

# Aquí están las reglas de cerrar. Como hemos comentado en la configuración
# anterior conviene tener esto escrito por si en algún momento se relaja el
# firewall y s cambia a de DROP a ACCEPT por defecto
# Cerramos rango de los puertos privilegiados. Cuidado con este tipo de
# barreras, antes hay que abrir a los que si tienen acceso.
iptables -A INPUT -p tcp –dport 1:1024
iptables -A INPUT -p udp –dport 1:1024

# Cerramos otros puertos que estan abiertos
iptables -A INPUT -p tcp –dport 3306 -j DROP
iptables -A INPUT -p tcp –dport 10000 -j DROP
iptables -A INPUT -p udp –dport 10000 -j DROP

echo » OK . Verifique que lo que se aplica con: iptables -L -n»

# Fin del script

4. Cómo depurar el funcionamiento del firewall

Programas útiles
IPTRAF. Sin duda alguna uno de los programas más prácticos para depurar el firewall es iptables, ya que con el podemos observar si la conexiones se establecen o no; es un programa de consola que es aconsejable controlar ya que muestra en tiempo real el tráfico que atraviesa nuestra máquina con todo lujo de detalles: origen/destino de ips y puertos, tráfico total o tráfico total según el interfaz de red, etc… Si vemos muchas conexiones simultaneas y nos perdemos, existe la posibilidad de aplicar filtros para captar solo aquello que nos interesa.

NMAP. La herramienta para escanear puertos por excelencia, rechace imitaciones. Es una herramienta de consola rápida, efectiva y con multitud de opciones. Podemos usarla desde máquinas ajenas a nuestra red para comprobar si realmente el firewall esta filtrando correctamente y en cierta manera para hacernos una idea de que «visión» pueden tener los hackers de nuestro sistema.

SHELL. En el propio script del firewall podemos añadir algunas opciones para descubrir fallos de sintaxis en las reglas. Claro, imaginemos que tenemos un firewall de 40 lineas y una de ellas falla cuando ejecutamos el script. ¿Cuál es? Es probable que el mensaje de error no aclare lo suficiente, por eso se puede añadir algo así al final de cada regla:


iptables -A INPUT -s 195.55.234.2 -j ACCEPT && echo » regla-21 ok»
iptables -A INPUT -s 213.62.89.145 -j ACCEPT && echo » regla-22 ok»

Si la regla se ejecuta bien mostrará el mensajito de ok.
Otra opción algo mas cutre sería ir eliminando o comentando reglas hasta dar con la regla que tiene la sintaxis incorrecta. Cabe reseñar que puede fallar una regla, pero a partir de ella el resto se ejecutan con normalidad.

Enlaces:
-Página oficial: http://www.netfilter.org

-Bibliografía
Building internet firewalls: todo un clásico
-Otros tutoriales:
En la propia web de netfilter-iptables tenemos el enlace a otros tutoriales, aunque todos ellos están en perfecto inglés.
Ejem, iptables en 21 segundos, del mismo autor que este.

Categorías: Administracion

Grub2

GRUB

De Guía Ubuntu

GRUB
Desarrollador: Proyecto GNU
Versión estable: 1.97 / –
Versión inestable: – / –
Paquete repositorios: grub o grub2
Comando:
Género: Gestor de arranque
Licencia: GPL
En castellano: No
Sitio web: www.gnu.org/software/grub

GRUB (GRand Unifier Bootloader) es un gestor de arranque: es lo primero que se carga cuando se inicia la computadora. Permite tener diferentes sistemas operativos, y diferentes versiones de ellos, en el mismo disco duro. Por ejemplo podemos tener Windows y GNU/Linux en la misma computadora, GRUB se cargará antes que cualquiera de éstos permitiéndonos elegir cuál iniciar.

El gestor de arranque GRUB viene preinstalado en la mayoría de las distribuciones de GNU/Linux modernas, entre ellas Debian, Ubuntu y sus derivadas. Anteriormente, el gestor de arranque más usado era LILO.

Tabla de contenidos

[esconder]

// <![CDATA[// [editar]

Grub 2

Grub 2.0 es el gestor de arranque predeterminado de algunas de las últimas versiones de linux.

[editar]

Modificaciones en el menú de arranque

Para modificar el tiempo de espera, sistema operativo por defecto, el nombre de los sistemas operativos y toda la información del arranque de cada uno de ellos (igual que se hacía antes en /boot/grub/menu.lst) se puede hacer mediante el archivo /boot/grub/grub.cfg No es recomendable hacerlo de este modo, ya que este archivo es un archivo creado automáticamente por el sistema utilizando otros archivos que son los que se deben modificar para cambiar los ajustes de Grub2. El archivo grub.cfg tambien se genera escribiendo en terminal:

sudo update-grub2

Los principales archivos para modificar las opciones de grub2 son:

  • Los contenidos en la carpeta /etc/grub.d/
    • /etc/grub.d/10_linux
      • Este archivo contiene comandos y scripts que se encargan del kernel de linux en la particion principal.
    • /etc/grub.d/30_os-prober
      • Este archivo contiene comandos y scripts que se encargan de otros sistemas operativos.
      • El archivo tiene 4 secciones. Los cambios que realicemos en una sección no afectarán al resto de las secciones.
        • Las cuatros secciones son Windows, otras particiones Linux, OSX y Hurd.
  • El archivo /etc/default/grub:
Una breve explicación de las líneas de este archivo:
GRUB_DEFAULT= 0/saved, con la opción 0 hacemos que se seleccione por defecto la primera entrada, con la opción 1, la segunda, y así succesivamente. Con la opción saved, hacemos que siempre seleccione la última entrada que se ejecutó.
GRUB_TIMEOUT=10, le ponemos el tiempo de espera hasta ejecutar la entrada que tenemos puesta como default.
GRUB_HIDDEN_TIMEOUT=0, esconde el menú de entradas del grub, si le ponemos un tiempo mas alto lo que hace es esconder el menú, pero esperarse un tiempo hasta continuar. Para hacerlo visible tenemos que comentar (escribir # al principio) la linea y que queda de la siguiente manera
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_MENU_QUIET=true/false, si está a "true" oculta la cuenta atrás, mientras que si está a "false" muestra la cuenta atrás.
GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian , determina el nombre de la entrada del menú.
GRUB_CMDLINE_LINUX="opciones", similar al altoptions del antiguo grub.
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" quiet sirve para agrupar las entradas iguales, mientras que splash sirve para que nos muestre la imagen de carga en vez de los mensajes del kernel
#GRUB_GFXMODE=640x480 descomentar (escribir # al principio) la línea activa el grub gráfico. Mediante el comando vbeinfo escrito en la linea de comandos del grub vemos las posibilidades. Por ejemplo:
GRUB_GFXMODE=1024x768
#GRUB_DISABLE_LINUX_RECOVERY="true" Descomenta esta línea para que no aparezca la opción de recovery mode en el menú
  • Los de la carpeta /usr/sbin/ (solamente los que llevan grub*, son los comandos que se ejecutan en terminal)
Imagen:Nota idea.png Los errores en las modificaciones de GRUB pueden llevar a problemas con el arranque. Por esto es recomendable hacer una copia de seguridad de los archivos que modifiquemos antes de realizar algún cambio

[editar]

Cambiar el nombre de un sistema operativo en el menú

Con este comando podemos ver los nombres de todos los sitemas operativos (los nombres no cambian hasta que ejecutamos sudo update-grub2)

sudo cat /boot/grub/grub.cfg | grep "menuentry" | cut -d '"' -f 2

[editar]

Cambiar el nombre de Ubuntu

Para cambiar el nombre de Ubuntu, modificamos el archivo /etc/grub.d/10_linux:

sudo gedit /etc/grub.d/10_linux

Podemos, por ejemplo, hacer que el nombre de Ubuntu sea del tipo «Ubuntu, Karmic 2.6.31-15-generic», añadimos la línea:

codename="`lsb_release -cs`"

al final de:

while [ "x$list"!= "x" ]; do
 linux=`version_find_latest $list`
 echo "Found linux image: $linux" >&2
 basename=`basename $linux`
 dirname=`dirname $linux`
 rel_dirname=`make_system_path_relative_to_its_root $dirname`
 version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
 alt_version=`echo $version | sed -e "s,\.old$,,g"`
 linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

De esta forma añadimos una nueva variable con el nombre de la distro al archivo, que podremos usar despues en la siguiente Linea:

 linux_entry "${OS}, Linux ${version}" \
     "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_EXTRA} ${GRUB_CMDLINE_LINUX_DEFAULT}" \
     quiet

Aca Podemos modificar la primera línea a nuestro antojo:

linux_entry "${OS}, ${codename} ${version}" \         de esta forma mostrará "Ubuntu, Karmic 2.6.31-15-generic"
linux_entry "${OS} ${codename}" \                     de esta forma mostrará "Ubuntu Karmic"
linux_entry "${OS} Texto que quieras" \               de esta forma mostrará "Ubuntu Texto que quieras"

Guardamos el archivo y ejecutamos sudo update-grub2

[editar]

Cambiar el nombre otro sistema operativo

Para cambiar el nombre de otros SO, modificamos el archivo /etc/grub.d/30_os-prober:

sudo gedit /etc/grub.d/30_os-prober

Vamos a la sección del archivo que corresponda (si es para cambiar Windows es la primera sección sobre la línea 80)

for OS in ${OSPROBED}; do
  DEVICE="`echo ${OS} | cut -d ':' -f 1`"
  LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
  LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
  BOOT="`echo ${OS} | cut -d ':' -f 4`"

Y cambiamos:

  if [ -z "${LONGNAME}" ]; then
    LONGNAME="${LABEL}"
  fi

Por:

if [ "${LONGNAME}" = "Titulo literal que aparece en el menu grub" ]; then
   LONGNAME="Nuevo título que quieres"
elif [ -z "${LONGNAME}" ]; then
   LONGNAME="${LABEL}"
fi

Por ejemplo, si en el menú grub aparece «Windows 7 (loader) (on sda1)» y queremos q ponga «Seven (on sda1)», entonces escribiremos:

if [ "${LONGNAME}" = "Windows 7 (loader)" ]; then
   LONGNAME="Seven"
elif [ -z "${LONGNAME}" ]; then
   LONGNAME="${LABEL}"
fi

Guardamos el archivo y ejecutamos sudo update-grub2

[editar]

Cambiar o eliminar (on /dev/sdxy)

Modificamos la parte del archivo que pone (cada línea que pone menumentry es de una sección del archivo):

menuentry "${LONGNAME} (on ${DEVICE})" {
menuentry "${LONGNAME} " {                                    de esta forma, no muestra (on /dev/sdxy)
menuentry "${LONGNAME} (en la particion ${DEVICE})" {         de esta forma, muestra (en la particion /dev/sdxy)

Guardamos el archivo y ejecutamos sudo update-grub2.

[editar]

Agregar manualmente cualquier sistema operativo (Ejemplo: MacOS)

Esta es la solución si el grub no detecta la partición o si la detecta pero no la arranca correctamente. Es el equivalente a insertar una entrada manualmente en el antiguo menu.lst. En este ejemplo insertamos una particion de MacOS.

Abrimos el archivo /etc/grub.d/40_custom:

sudo gedit /etc/grub.d/40_custom

En la última línea del archivo pegamos las siguientes líneas (importante cambiar hd0,1 por la particion que corresponda):

menuentry "MacOS X (en hd0,1)" {
          insmod hfsplus
          set root=(hd0,1)
          multiboot /boot
}

Escribimos el comando:

sudo update-grub2

Si en el menú del grub aparecen 2 entradas para mac (la que creamos manualmente nosotros y otra que aparece automáticamente) debemos abrir el archivo 30_os-prober, ir a la sección de mac y comentar las líneas dedicadas a ese sistema operativo (si no has modificado el archivo, desde la 158 hasta la 207, incluidas). Las líneas son las siguientes:

#    macosx)
#     OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
#       cat << EOF
. . .
#              xnu_splash /Extra/splash.tga
#           fi
#        fi
#}
#EOF

[editar]

Eliminar un sistema operativo del menú Grub

La información de los sistemas operativos se agrupa en distintos archivos de la carpeta /etc/grub.d/ Para eliminar un sistema operativo, simplemente eliminamos el archivo o le cambiamos el nombre (por ejemplo introduciendo un asterisco antes del nombre).

[editar]

Eliminar memtest

Para que no aparezca memtest en el menú, le quitamos los permisos de ejecución con el siguiente comando:

sudo chmod -x /etc/grub.d/20_memtest86+

Si escribimos +x en lugar de -x volvemos a darle permisos de ejecución y nos volverá a aparecer.

Ejecutamos:

sudo update-grub2

[editar]

Eliminar el sistema de recuperación

Abrimos etc/default/grub

sudo gedit /etc/default/grub

y cambiamos

#GRUB_DISABLE_LINUX_RECOVERY="false"

por:

GRUB_DISABLE_LINUX_RECOVERY="true"

También podemos hacer esto en un solo comando con:

sudo sed s/'#GRUB_DISABLE_LINUX_RECOVERY="true"'/'GRUB_DISABLE_LINUX_RECOVERY="true"'/g -i /etc/default/grub

Despues actualizamos grub2:

sudo update-grub2

[editar]

Eliminar un kernel de Ubuntu

Para eliminar un kernel, podemos mover los archivos de ese kernel de la carpeta /boot a una carpeta creada por nosotros. Primero creamos la carpeta:

sudo mkdir /boot/kernels

A continuación movemos la imagen del kernel (debemos cambiar 2.6.31-14 por el kernel que queramos eliminar del menú):

sudo mv /boot/vmlinuz-2.6.31-14-generic-pae /boot/kernels/

Y tambien podemos mover la imagen de que se utiliza para entrar en el modo recuperación (debemos cambiar 2.6.31-14 por el kernel que queramos eliminar del menú):

sudo mv /boot/initrd.img-2.6.31-14-generic-pae /boot/kernels/

Despues actualizamos grub.cfg:

sudo update-grub2

Ahora podemos comprobar que podamos acceder al kernel que queramos viendo las entradas del grub con el siguiente comando: sudo cat /boot/grub/grub.cfg | grep «menuentry» | cut -d ‘»‘ -f 2

Nota: esto lo deberemos hacer cada vez que actualizamos a un nuevo kernel

[editar]

Cambiar el tiempo de espera y sistema operativo por defecto

Estos parámetros se modifican en el archivo /etc/default/grub:

$ sudo gedit /etc/default/grub

En la sección:

GRUB_DEFAULT=0

Sistema operativo por defecto, 0 es el primero, 1 el segundo, etc.

GRUB_TIMEOUT="10"

Tiempo de espera en segundos Despues de modificar el archivo, debemos actualizar grub.cfg con el comando:

sudo update-grub2

[editar]

Modificar el entorno

[editar]

Modificar la imagen de fondo

La imagen de fondo debe estar en formato .png, o .tga, preferiblemente tga. Por ejemplo para utilizar una imagen cualquiera en JPG, la abrimos la imagen con Gimp, vamos al menú Imagen>Escalar imagen y le ponemos la resolución 640×480. Es preferible guardarla en el escritorio y copiarla en /usr/share/images/grub/ , donde vienen las imagenes por defecto de grub2, con una resolución de 640×480. Copiarla con el comando:

 sudo cp/home/tu_nombre/Escritorio/tu_imagen.tga /usr/share/images/grub/tu_imagen.tga

Crearemos un link a la carpeta /boot/grub para no tener que editar el script theme.

sudo ln -s /usr/share/images/grub/tu_imagen.tga /boot/grub/moreblue-orbit-grub.tga

Despues de modificar el archivo, debemos actualizar grub.cfg con el comando:

sudo update-grub2

[editar]

Modificar el color del texto

Antes de modificar los colores del texto debemos tener una imagen de fondo. Para modificar los colores del texto abrimos el archivo /etc/grub.d/05_debian_theme

sudo gedit /etc/grub.d/05_debian_theme

En la sección:

# set the background if possible
if background_image `make_system_path_relative_to_its_root ${bg}`; then
 set color_normal=black/black
 set color_highlight=magenta/black

Donde en «set color_normal» el primer «black» es el color del texto sin seleccionar y en «set color_highlight», «magenta» es el color del texto seleccionado y «black» es el color del fondo en la línea de texto seleccionado. Los colores que se pueden utilizar son:

  • rojo: red
  • verde: green
  • azul: blue
  • amarillo: yellow
  • cian: cyan
  • magenta: magenta
  • blanco: white
  • negro: black

Despues de modificar el archivo, debemos actualizar grub.cfg con el comando:

sudo update-grub2

[editar]

Grub 1

[editar]

Modificaciones en el menú de arranque

Imagen:Nota idea.png Los errores en las modificaciones de GRUB pueden llevar a problemas con el arranque. Por esto es recomendable hacer una copia de seguridad del archivo menu.lst antes de realizar algún cambio. Se puede hacer con el siguiente comando:

$ sudo cp /boot/grub/menu.lst /boot/grub/menu.lst.backup

Luego, para restaurar la copia de seguridad, hacemos lo siguiente:

$ sudo cp /boot/grub/menu.lst.backup /boot/grub/menu.lst

Si ya es demasiado tarde mira Cómo recuperar GRUB.

[editar]

Cambiar el sistema operativo por defecto

Si tenemos Windows instalado y después hemos instalado Ubuntu, la configuración de GRUB por defecto hará que arranque Ubuntu. Si por algún motivo necesitamos que arranque Windows por defecto, veamos los pasos a seguir.

  • Editamos el archivo de configuración del menú de arranque de GRUB:
$ sudo gedit /boot/grub/menu.lst
  • Buscamos la siguiente línea:
default 0
  • Cambiamos el 0 por el número que ocupe el sistema operativo en la lista que queremos que se inicie por defecto, empezando por 0.
  • Guardamos los cambios y cerramos el editor.

[editar]

Cambiar el tiempo de espera

En Ubuntu, GRUB deja por defecto 10 segundos para permitir la selección del sistema operativo o versión del kernel. Este tiempo puede parecer excesivo o demasiado breve. Para modificarlo basta con seguir los siguientes pasos:

  • Editamos el archivo de configuración del menú de arranque de GRUB:
$ sudo gedit /boot/grub/menu.lst
  • Buscamos la siguiente línea:
timeout         10
  • Modificamos el valor 10 por el deseado, teniendo en cuenta que se trata de segundos.
  • Guardamos los cambios y cerramos el editor.

[editar]

Ocultar el menú

Si utilizamos normalmente sólo un sistema operativo o una versión del kernel, es molesto que nos aparezca el menú en cada arranque del sistema. GRUB permite configurar el menú de modo que no se muestre al arranque salvo que presionemos la tecla Escape (Esc) durante el mismo. Para hacer esto, seguimos los siguientes pasos:

  • Editamos el archivo de configuración del menú de arranque de GRUB:
$ sudo gedit /boot/grub/menu.lst

Buscamos la siguiente línea:

#hiddenmenu
  • Borramos la almohadilla o numeral (#) de la línea, haciendo esto la descomentaremos. Debe quedar así:
hiddenmenu
  • Guardamos los cambios y cerramos el editor.

[editar]

Proteger con contraseña

Para que ningún usuario no autorizado pueda modificar los valores de GRUB en tiempo de ejecución, podemos establecer una contraseña, de esta forma sólo pulsando la tecla ‘p’ e introduciendo la contraseña se podrán cambiar los parámetros del programa.

  • Editamos el archivo de configuración del menú de arranque de GRUB:
$ sudo gedit /boot/grub/menu.lst

Buscamos la siguiente línea:

#password topsecret
  • Borramos la almohadilla o numeral (#) de la línea, haciendo esto la descomentaremos. Debe quedar así:
password topsecret
  • Guardamos el archivo y cerramos el editor.

Ahora la contraseña es topsecret, se puede cambiar e introducir la que se desee.

[editar]

Codificar contraseña

Si queremos que nadie pueda leer la contraseña en el archivo de configuración de GRUB, el programa también ofrece la posibilidad de codificarla en formato md5:

$ sudo grub update
  • Aparece la consola de GRUB, entonces escribimos:
grub> md5crypt
  • Introducimos la palabra a codificar, en este caso topsecret, el programa devolvería el valor:
$1$ddTCc1$8v3fWFR4m5kDfuRG5LUHo/'
  • Lo copiamos y volvemos a la consola de Ubuntu:
grub> quit
  • En el archivo de configuración del menú de GRUB, borramos la siguiente línea:
# password topsecret'

En su lugar, escribimos:

password --md5 $1$ddTCc1$8v3fWFR4m5kDfuRG5LUHo/

Y ya tenemos nuestro GRUB protegido por contraseña cifrada.

  • Guardamos los cambios y cerramos el editor.

Si queremos restringir el acceso a algún elemento del menú de GRUB, basta con añadir después del título del menú una línea con la contraseña, por ejemplo:

title           Ubuntu, kernel 2.6.15-26-386 (recovery mode)
password        --md5 $1$ddTCc1$8v3fWFR4m5kDfuRG5LUHo/
root            (hd1,0)
kernel          /boot/vmlinuz-2.6.15-26-386 root=/dev/hdb1 ro single
initrd          /boot/initrd.img-2.6.15-26-386
boot
  • Guardamos los cambios y cerramos el editor.

[editar]

Cambiar colores

Por defecto, en Ubuntu el menú del GRUB tiene un fondo negro con letras blancas. Para cambiar los colores del menú de arranque por otros más atractivos, seguimos los siguientes pasos.

  • Editamos el archivo de configuración del menú de arranque de GRUB:
$ sudo gedit /boot/grub/menu.lst
  • Buscamos la siguiente línea:
# color cyan/blue white/blue
  • * Borramos la almohadilla o numeral (#) de la línea, haciendo esto la descomentaremos. Debe quedar así:
color cyan/blue white/blue
  • Guardamos los cambios y cerramos el editor.

Ahora nos aparecerá un menú con fondo azul, al estilo de varias aplicaciones con interfaz de línea de comandos. Si queremos, podemos cambiar los colores reemplazando las palabras cyan, blue y white por otras, que representen los nombres de distintos colores en inglés.

[editar]

Colocar una imagen de fondo

En vez de cambiar sólo los colores del menú, GRUB nos brinda la posibilidad de colocar una imagen de fondo para hacerlo aún más atractivo.

La imagen que se puede colocar en GRUB tiene que tener un máximo de 14 colores y un tamaño de 640 × 480 píxeles. Tiene que estar grabada en formato .xpm y conviene que esté comprimida con gzip (extensión .gz), aunque no es imprescindible.

  • Para saber desde GIMP cuántos colores tiene nuestra imagen ve a Colores -> Info -> Análisis del cubo de color…
  • Si tiene más de 14 colores, podemos reducir el número con Imagen -> Modo -> Indexado.
  • Una vez tenemos la imagen, para ponerla de fondo editamos el archivo de configuración del menú de GRUB:
$ sudo gedit /boot/grub/menu.lst
  • Añadimos al principio la línea:
splashimage=(hd0,2)/ruta_imagen/nombre_imagen.xpm.gz

Donde (hd0,2) identifica el disco y partición donde se encuentra la imagen. Esto varía según el equipo. Si tienes un solo disco duro, antes de la coma irá hd0; si tienes Ubuntu en una sola partición, pero compartiendo el disco con otro sistema operativo, posiblemente irá después de la coma un 1. Puede ayudarte ejecutar:

$ sudo fdisk -l

teniendo en cuenta que GRUB numera las particiones desde 0 (por ejemplo, (hd0,1) se corresponde con sda2; (hd1,2) con sdb3).

  • Reiniciamos y listo, ya tendremos una imagen de fondo en el menú de arranque.

[editar]

Configuración mediante aplicación externa

Otra de las formas para configurar GRUB fácilmente es por medio de la aplicación Start-Up Manager, para instalarlo tan solo hay que hacer clic a el Deb de su aplicación, no se encuentra en los repositorios por lo tanto tendréis que descargalo aquí.

Con esta aplicación podremos configurar el GRUB de manera muy fácil, nos da a elegir todas las opciones de manera sencilla.

Para poder ejecutarlo debemos poner en la consola lo siguiente:

$ sudo startupmanager

[editar]

Ver también

[editar]

Artículos relacionados

[editar]

Editores gráficos

Existen alternativas para realizar la configuración de manera gráfica, como las siguientes:

Estoy seguro de que muchos han instalado GRUB 2 porque quieren ver cómo es, o simplemente porque les venía por defecto en las nuevas versiones de sus distribuciones favoritas (por ejemplo, Ubuntu 9.10 viene con GRUB 2 por defecto). Pero en este último caso, si han actualizado desde una versión anterior, pueden observar que sigue siendo el mismo GRUB de toda la vida (llamado GRUB Legacy). Aquí voy a explicar cómo instalar GRUB 2 en Debian o una derivada de ésta (por ejemplo, Ubuntu) y también a personalizar tu nuevo GRUB

Instala GRUB 2

Antes de todo quiero decir que la versión de GRUB 2 que instalen depende de la distribución y de la versión de la distribución que estén usando, ya que Debian «Squeeze» y Ubuntu 9.10 «Karmic Koala» les instalará la versión 1.97 Beta 4 y Ubuntu 9.04 les instalará la versión 1.96, así que si estáis en este último caso, les recomiendo que actualicen a Ubuntu 9.10 para usar la versión más reciente de GRUB 2. Si ya tienen GRUB 2 en Ubuntu 9.04 y van a actualizar a Ubuntu 9.10, en la actualización del sistema a la versión 9.10 se les actualizará el GRUB a la versión más reciente. Ahora sí que comienza el tutorial:

Paso 1

Suponiendo que tenemos GNOME, nos vamos a Sistema > Administración > Gestor de paquetes Synaptic y buscan el paquete «grub2» (sin las comillas). Cuando hayan localizado el paquete grub2, hacen clic derecho sobre él y pulsa sobre «Marcar para instalar» (sin las comillas). Después dan a «Aplicar» (sin comillas) en el Gestor de paquetes Synaptic y esperen a que se instale el paquete. Si quieren instalarlo de una manera más simple, abran una Terminal y pongan esto: sudo apt-get install grub2 . Les saldrán unas pantallas en Terminal, en la primera aceptan, en la segunda responden que sí, y en la tercera pulsen Intro. Después de que se haya instalado el paquete grub2, reinicien el equipo.

Paso 2

Verán que en el GRUB de toda la vida les ha salido una opción llamada «Chainload into GRUB 2» (sin comillas). Sitúense sobre ésta y pulsen la tecla e. Entonces les saldrán dos líneas; se sitúan sobre la primera y pulsen la tecla e para modificar la línea. Con el teclado, desplácense a donde pone «root» (sin comillas) y lo sustituyen por «uuid» (sin las comillas). Cuando lo hayan escrito, pulsen la tecla Intro y, cuando les salgan dos líneas, pulsen b para arrancar GRUB 2. Suerte .

Paso 3

Les saldrá la pantalla de GRUB 2. Miren si les salen todos los sistemas operativos de su PC. Si les salen todos, arranquen Ubuntu o Debian, abran una Terminal y pongan esto: sudo upgrade-from-grub-legacy , y sigan sus instrucciones. Al reiniciar ya les saldrá por defecto GRUB 2. En caso de que no les salgan todos los sistemas operativos de vuestro PC, arranquen Ubuntu o Debian, abran una Terminal y tecleen esto: sudo aptitude purge grub2 , y al reiniciar seguirán con el GRUB de toda la vida.

Bien, ya tenemos instalado GRUB 2, pero si no les ha gustado la apariencia por defecto de GRUB, pueden cambiarla. Empezamos:

Cambiar el fondo de GRUB 2

Paso 1

Una vez en Ubuntu o Debian, vamos otra vez al Gestor de paquetes Synaptic y busquen el paquete «grub2-splashimages» (sin comillas). Seleccionen el paquete grub2-splashimages, hagan clic derecho con el ratón y pulsen sobre «Marcar para instalar» (sin las comillas), y pulsen en Aplicar en el Gestor de paquetes Synaptic. Cuando se haya instalado el paquete, cierren Synaptic.

Paso 2

Vámonos a Lugares > Equipo, seleccionen «Sistema de archivos» (sin comillas) y desplácense a /usr/share/images/grub . Una vez allí, elijan la imagen que quieran poner de fondo en su GRUB y NO cierren la ventana.

Paso 3

Como pueden ver en la imagen, abran una Terminal y tecleen esto: «sudo gedit /etc/grub.d/05_debian_theme» (sin comillas) y pulsen Intro. Se les abrirá una ventana de gedit y allí busquen estas líneas:

dijo:

for i in {/boot/grub,/usr/share/images/desktop-base}/moreblue-orbit-grub.{png,tga} ; do

Y déjenla como ésta:

dijo:

for i in {/boot/grub,/usr/share/images/grub}/laimagenquedeseen.{png,tga} ; do

PD: Donde pone «laimagenquedeseen» (sin comillas) deben poner el título de la imagen que quieren tener como fondo en GRUB 2. Al poner la imagen, no pongan la extensión del archivo (no pongan el tga final

Paso 4

Abran una Terminal y tecleen esto: sudo update-grub . Posteriormente, en la misma Terminal tecleen esto: sudo grub-mkconfig . De que hayan terminado, reinicien el equipo

Categorías: Administracion

Ejecución condicional

May 11, 2010 2 comentarios

Ejecución condicional

Otra situación algo más elaborada que la anterior es ejecutar una orden condicionada a la terminación correcta o no de una orden previa.

Esta funcionalidad nos la proporcionan los operadores «&&» y «||«.

Operador &&

El primer operador, «&& » separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina correctamente, es decir

orden1 && orden2

orden2 sólo se ejecutará si orden1 terminó sin ningún error.

Por ejemplo, queremos ejecutar la orden cat fichero sólo si existe fichero; entonces tendremos que buscar una orden que termine con un error si no existe fichero, por ejemplo ls fichero y condicionar la ejecución de cat fichero a esta:

$ ls fichero && cat fichero

Otro ejemplo, para compilar los controladores de dispositivos de linux e instalarlos, lo podemos hacer como:

make module && make modules_install

es decir instalará los controladores sólo si ha conseguido compilarlos correctamente.

Operador ||

El segundo operador, «|| » tiene un comportamiento similar al anterior, separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina incorrectamente, es decir

orden1 || orden2

orden2 sólo se ejecutará si orden1 terminó con algún error.

Por ejemplo si no existe fichero queremos crearlo vacía y si existe no hacemos nada. Igual que en el ejemplo anterior, buscamos una orden que termine con un error si no existe fichero y condicionamos la ejecución de la orden touch fichero al error de la orden previa:

$ ls fichero || touch fichero

También, al igual que en el ejemplo anterior podríamos hacer que si el proceso make modules falla, se borraran todos los ficheros temporales que se crean:

make modules || rm -r *.o

Ejecución simultánea

Otra posibilidad de ejecución también posible es lanzar varios procesos simutáneamente en segundo plano; basta escribir uno a continuación de otro en la línea de órdenes separados por «&». Este es el símbolo que se utiliza para indicar que el proceso se tiene que ejecutar en segundo plano, pero también actúa como separador para la ejecución de distintas órdenes.

por ejemplo :

[pfabrega@port pfabrega]$ sleep 10 & sleep 20 & sleep 15 &
[pfabrega@port pfabrega]$ ps axu
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.2  1408  540 ?        S    22:19   0:04 init [3]
...
pfabrega  1263  0.3  0.2  1624  516 pts/4    S    23:24   0:00 sleep 10
pfabrega  1264  0.0  0.2  1624  516 pts/4    S    23:24   0:00 sleep 20
pfabrega  1265  0.0  0.2  1624  516 pts/4    S    23:24   0:00 sleep 15
pfabrega  1266  0.0  0.3  2732  848 pts/4    R    23:24   0:00 ps axu

Agrupando con paréntesis

Podemos organizar la ejecución de varias órdenes agrupándolas convenientemente mediante paréntesis para modificar el orden predeterminado de ejecución. En primer lugar actúan los ; después los & y la ejecución es de izquierda a derecha. Para las ejecuciones condicionales se tiene en cuenta el valor de la variable $? que se fija por la última orden que se ejecuta.

Para alterar esta forma de ejecución podemos utilizar los paréntesis. En realidad los paréntesis fuerzan una nueva subshell para ejecutar las órdenes correspondientes.

Esta característica puede ser interesante en diferentes situaciones:

Quemos enviar una secuencia de órdene s a segundo pláno

(mkdir copiaseg; cp -r ./original/* ./copiaseg; rm -r ./original~; rm -r ./original.tmp) &

Resultado de la ejecución de una orden

Es habitual necesitar almacenar el resultado de la ejecución de una orden en una variable en lugar de que se dirija a la salida estándar o simplemente ejecutar como orden el resultado de otra orden.

Comillas invertidas `

Las comillas invertidas consideran una orden lo que tengan dentro y lo ejecutan devolviendo el resultado como líneas de texto a la shell. Por ejemplo:

$ A="ls /bin"
$ `echo $A`
arch        consolechars   ed          igawk     mount          rpm        tar
ash         cp             egrep       ipcalc    mt             rvi        tcsh
ash.static  cpio           ex          kill      mv             rview      touch
awk         csh            false       ln        netstat        sed        true
basename    date           fgrep       loadkeys  nice           setserial  umount
bash        dd             gawk        login     nisdomainname  sfxload    uname
bash2       df             gawk-3.0.6  ls        ping           sh         usleep
bsh         dmesg          grep        mail      ps             sleep      vi
cat         dnsdomainname  gtar        mkdir     pwd            sort       view
chgrp       doexec         gunzip      mknod     red            stty       ypdomainname
chmod       domainname     gzip        mktemp    rm             su         zcat
chown       echo           hostname    more      rmdir          sync
También podríamos haber puesto:
$ A="ls /bin"
$ B=`$A`
$ echo $B
arch ash ash.static awk basename bash bash2 bsh cat chgrp chmod chown consolechars cp cpio csh date dd df dmesg dnsdomainname doexec domainname echo ed egrep ex false fgrep gawk gawk-3.0.6 grep gtar gunzip gzip hostname igawk ipcalc kill ln loadkeys login ls mail mkdir mknod mktemp more mount mt mv netstat nice nisdomainname ping ps pwd red rm rmdir rpm rvi rview sed setserial sfxload sh sleep sort stty su sync tar tcsh touch true umount uname usleep vi view ypdomainname zcat

El operador $()

La shell bash proporciona el operador $() similar a las comillas invertidas. Ejecuta como orden los que haya entre paréntesis y devuelve su resultado. El mecanismo de funcionamiento es idéntico, con la ventaja de poder anidar operadores.

Agrupamiento de mandatos:

:

1.- Redirección de salida(>): Redirige la salida de un comando a un fichero.

Si hacemos: dir > fichero.txt

Se creará un archivo “fichero.txt”. Si miramos su contenido (cat fichero.txt) veremos que contiene exactamente lo que veríamos al ejecutar el comando dir.

2.- Redirección de entrada(<): Redirige la entrada estándard de un comando desde un fichero.

Si hacemos: grep “/root” < fichero.txt

De existir una línea que contenga esa cadena en el archivo antes creado, fichero.txt se imprimirá en pantalla la línea completa. Si no, no devolverá nada.

3.- Ejecución secuencial(;): Ejecuta secuencialmente una lista de comandos.

Ejemplo: mv archivo1 aux ; mv archivo2 archivo1; mv aux archivo1

4.- Redirección de salida estándard de error(>&).

Si utilizamos un comando y salen varias pantallas describiendo el error(Cosa poco usual), o si por ejemplo dejamos trabajando nuestro terminal ejecutando varias órdenes y queremos al volver mirar si todo ha sido correcto, hacemos:

comando >& fichero.txt

5.- Ejecución asíncrona(&): Ejecuta en paralelo el/los comandos introducidos.

Ejemplo: make programa_enorme.c & make programa_enorme2.c &

Compilará los dos programas “a la vez”, y además nos dejará el shell libre para poder seguir ejecutando mandatos.

6.- OR lógico( || ): Se ejecutan de forma secuencial los mandatos introducidos hasta que uno de ellos devuelva un valor 0(verdadero).

Ejemplo: test -d archivo || lpr archivo

Sólo imprime el archivo si no es un directorio.

7.- AND lógico (&&): Se ejecutan de forma secuencial los mandatos introducidos hasta que uno de ellos devuelva un valor distinto de 0(falso).

Ejemplo: test -f archivo && lpr archivo

Imprime el fichero sólo si se trata de un fichero ordinario.

8.- Tuberías(pipes)( | ): Se ejecutan los comandos de forma secuencial, pero redirigiéndose la salida de cada uno al siguiente comando.

Ejemplo1: dir | sort | less

Imprime la lista de los ficheros del directorio actual de trabajo ordenados alfabéticamente y línea a línea.

Ejemplo2: head -100 carta | grep “Juan” | sort | lpr

Imprime en orden alfabético las líneas que, estando entre las 100 primeras del archivo “carta” contengan la cadena de caracteres “Juan”.

Categorías: Administracion

Escritura de scripts de shell

May 11, 2010 1 comentario

Escritura de scripts de shell

Hemos llegado a un punto donde podemos realizar tareas más complejas a partir de los comandos aprendidos y es aquí donde radica el poder del intérprete de comandos bash. Como veremos a continuación, el intérprete de comandos es un poderoso lenguaje para realizar script que permitan unir varios comandos para realizar una tarea un poco más compleja (y es el este el poder principal de todo Un*x). El único requisito es tener nociones básicas de programación para poder sacar todo el provecho posible de esta característica del intérprete de comandos. En todo caso, con un poco de práctica y un buen sentido de la lógica se podrán hacer también script poderosos para desarrollar las tareas que requerimos.

Deberemos saber también que con la ayuda solamente de la conjunción de comandos no podremos hacer script verdaderamente interesantes. Por esto se incorporan las construcciones de shell. Estas son las construcciones while, for-in, if-then-fi y case-esac. Existen muchas más pero estas serán las más útiles para nosotros en estos momentos. Para mayor información sobre otro tipo de construcciones seria mejor revisar las páginas de manual del intérprete de comandos bash (man bash).

Empezaremos viendo un uso sencillo de la construcción for-in que tiene la siguiente sintaxis

 for var in word1 word2
 do
   commandos
 done

Para poder usar esto, podríamos realizar una lista de directorios que querramos nosotros de una sola vez

 for dir in /bin /etc /lib
 do
   ls -R $dir
 done

Esto hará un listado recursivo 3 veces. La primera vez que pase por el ciclo, la variable $dir tomará el valor /bin, la segunda será /etc y la tercera /lib.

Podríamos prescindir del par do-done con el uso de llaves ({})

 for dir in /bin /etc /lib
 {
   ls -R $dir
 }

Ya hemos visto anteriormente la idea de argumentos en la utilización de comandos y programas; pero deberemos ver como se realiza la codificación de un script para tomar estos argumentos. Como antes dijimos, los argumentos eran pasados a los programas para que estos lo utilizaran. En la construcción de script veremos lo que se llaman variables posicionales cuyo valor corresponde a la posición del argumento luego del nombre del script. Supongamos que tenemos un script que toma 3 argumentos. El primero será el nombre de un directorio, el segundo el nombre de un archivo y el tercero es una palabra a buscar. Este script buscará en todos los archivos del directorio, cuyo nombre incluya el nombre de archivo que le pasamos como argumento, la palabra que también le estamos pasando. El script se llamara miscript y estará compuesto del siguiente código

ls $1 | grep $2 | while read ARCHIVO
 do
   grep $3 ${1}/${ARCHIVO}
 done

La sintaxis será

miscript [directorio] [nombre_archivo] [palabra]

Aquí tenemos varias cosas para ver. Primero que nada, el uso de las variables posicionales. Como se podrá apreciar el número de la variable, que esta precedido por un signo $, indica la posición del argumento cuando el script es llamado. Solamente se podrán usar 9 variables de este tipo sin tener que emplear un pequeño truco de corrimiento que veremos luego, dado que el 0 representa al nombre del script mismo. Es decir que en este caso la variable posicional $0 valdrá «miscript». Como se puede ver se han utilizado canalizaciones para poner más de un comando junto. Al final de la construcción se esta usando una construcción while. Esta se usa para repetir un ciclo mientras una expresión sea cierta.

 while ($VARIABLE=valor)
 do
   commandos
 done

En este caso esta siendo usada al final de una canalización con la instrucción read ARCHIVO. Es decir, mientras pueda leer el contenido de la variable $ARCHIVO, continuar. Esta variable $ARCHIVO contiene el resultado de lo que arrojo la canalización del listado con la salvedad de que tenia que contener la palabra que le enviamos como argumento, es así que solo se imprimirán las líneas en las que coincida la palabra a buscar de los archivos que cumplan con los requisitos.

Otra cosa a tener en cuenta es una nueva construcción en este script, ${1}/${ARCHIVO}. Al encerrar un nombre de variable dentro de llaves podemos combinarlas. En este caso forman el nombre del directorio (${1}) y añadimos una / como separador del directorio, y seguido e nombre del archivo donde se aplicara el comando grep con la palabra a buscar $3.

Podríamos hacer que este script sea un poco más documentado. Para esto podríamos asignar las variables posicionales a otras variables para que se pueda entender mejor su uso.

 DIRECTORIO=$1
 ARCHIVO_BUS=$2
 PALABRA=$3

 ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO
 do
   grep $PALABRA ${DIRECTRIO}/${ARCHIVO}
 done

El número de las variables posicionales que pueden usarse en un script, como antes dijimos, se encuentra restringido a 10. ¿Qué pasaría si tenemos más de 9 argumentos? Es aquí donde tenemos que usar la instrucción shift. Esta instrucción mueve los argumentos hacia abajo en la lista de parámetros posicionales. De esta manera podríamos tener una construcción con esta distribución de variables

 DIRECTORIO=$1
 shift
 ARCHIVO_BUS=$1

De esta manera podríamos asignar el valor de la primer variable posicional a la variable DIRECTORIO y luego el siguiente argumento que habíamos dado se tomara otra vez con el nombre de $1. Esto solo tiene sentido si asignamos las variables posicionales a otra variable. Si tuviéramos 10 argumentos, el décimo no estaría disponible. Sin embargo, una vez que hacemos el que las variables se corran de posición este se convertirá en el noveno y se accederá por la variable posicional $9. Existe una forma también de pasar como argumento a la instrucción shift el número de posiciones que queremos correr. Por lo cual podemos usar

 shift 9

y así se lograra que el décimo argumento sea el parámetro posicional 1.

Lo que ocurre con los anteriores 9 argumentos es que desaparecen si no se los asigno a una variable anteriormente. Podremos cambiar usar un nuevo parámetro que podrá contener mas de un parámetro pasado al script. Este se denomina $* y contendrá el resto de los argumentos que se pasen al script luego de que se haya realizado un corrimiento determinado. Por ejemplo, si quisiera buscar una frase en lugar de una única palabra el script podría ser

 DIRECTORIO=$1
 ARCHIVO_BUS=$2
 shift 2
 PALABRAS=$*

 ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO
 do
   grep "$PALABRAS" ${DIRECTRIO}/${ARCHIVO}
 done

Lo que aquí cambio es que luego de haber asignado a variables los parámetros posicionales 1 y 2 las variables fueron desplazadas dos veces, eliminando los dos primeros argumentos. Luego asignamos los argumentos restantes a la variable PALABRAS. Para que sea tomado como una cadena, se lo encerró entre comillas para ser pasado al comando grep, si no lo hiciéramos el bash vería nuestra entrada como argumentos individuales para pasar al grep.

Otro parámetro que es de utilidad es el $# que lleva la cuenta de la cantidad de argumentos pasados al script. De esta forma podríamos realizar un script que identificara si se le están pasando la cantidad de parámetros que realmente necesita y anunciar el error si faltaran estos. Para ello utilizaremos la construcción if-then-fi que es muy parecida a la while-do-done, en donde el par if-fi marca el final de un bloque. La diferencia entre estas construcciones es que el if solo evaluara una vez la condición. La sintaxis es la siguiente

 if [ condición ]
 then
   hacer_algo
 fi

Las condiciones que puede usarse se encuentran en las man page test (man test). Nosotros usaremos una simple condición para contar argumentos, pero pueden ser usadas distintas condiciones como nombres de archivos, permisos, si son o no directorios, etc. Para saber si la cantidad de argumentos que se nos a pasado en el script es correcta, utilizaremos una opción aritmética que compare la cantidad de argumentos pasados ($#) con un número que nosotros estipularemos, en este caso 3. Pueden usarse diferentes opciones con el formato arg1 OP arg2, donde OP será alguno de los siguientes

-eq     es igual
-ne     no es igual
-lt     menor que
-le     menor que o igual
-gt     mayor que
-ge     mayor que o igual

Se usará en este caso el -ge (mayor o igual que) dado que si la cantidad de argumentos que siguen al segundo es mayor la tomaremos como una frase a buscar y si es igual como una palabra. Lo único que haremos en caso de que la cantidad de argumentos sea menor, será informar de esto y de la forma de usar el script.

 DIRECTORIO=$1
 ARCHIVO_BUS=$2
 shift 2
 PALABRAS=$*

 if [ $# -ge 3 ]
 then
   ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO
   do
     grep "$PALABRAS" ${DIRECTRIO}/${ARCHIVO}
   done
   else
     echo "Número de argumentos insuficientes"
     echo "Use: $0 <directorio> <archivo_a_buscar> <palabras>"
   fi

Otra utilidad para del if, es la posibilidad de realizar lo que se denomina if anidados. De esta forma podríamos tener varias capas de if-then-else-fi. Como ejemplo podría ser esta una construcción válida

 if [ $condicion1 = "true" ]
 then
   if [ $condicion2 = "true" ]
   then
     if [ $condicion3 = "true" ]
     then
       echo "las condiciones 1, 2 y 3 son ciertas"
     else
       echo "solo son ciertas las condiciones 1 y 2"
     fi
   else
     echo "condición 1 es cierta, pero no la 2"
   fi
 else
   echo "la condición 1 no es cierta"
 fi

Podríamos también hacer que una sola variable tome diferente valores e interactuar con ella para ver si se cumple la condición buscada. De esta forma podríamos por ejemplo hacer un menú de usuario con distintas alternativas. Pero esta forma es útil solo para pocas condiciones. ¿Que pasaría si tuviéramos muchas condiciones mas que agregar? Se nos haría por demás de complicado seguir el esquema armado y sería demasiado código para lo que se trata de realizar. Es aquí es donde se necesita la estructura case-esac. Como se podrá ver, al igual que en el if-fi aquí el inverso de case (esac) cierra la construcción. Veamos un ejemplo de una construcción con case

 read ELECCION
 case $ELECCION in
   a) programa1;;
   b) programa2;;
   c) programa3;;
   *) echo "No eligió ninguna opción valida";;
 esac

Hay que tener en cuenta algunas cosas respecto a este tipo de construcción. Por ejemplo el mandato que le damos al principio read indica al bash que tiene que leer lo que se ingrese a continuación y lo guarde en una variable que se llamara ELECCION. Esto también será útil para el uso de otras construcciones ya que el read no es propiedad exclusiva de la construcción esac, sino que pertenece al mismo bash. Como se ve, se le indica que si el valor que la variable contiene es igual a alguna de las mostradas debajo se ejecute determinado programa. (case $ELECCION in). La elección se debe terminar con un paréntesis «)» para que se cierre las posibilidades. Podríamos poner más posibilidades para cada elección; lo único que hay que recordar es cerrar con un paréntesis. El punto y coma nos marca el final de un bloque, por lo que podríamos agregar otro comando y se cerrara con punto y coma doble al último. El asterisco del final nos indica que se hará en caso de que no coincida lo ingresado con ninguna de las posibilidades. Un ejemplo, sería que nuestra construcción reconozca mayúsculas y minúsculas y además ejecute más de un comando por bloque.

 read ELECCION
 case $ELECCION in
   a|A)
        programa1
        programa2
        programa3;;
   b|B)
        programa4
        programa5;;
   c|C)
        programa3;;
   *)
        echo "No eligió ninguna opción valida";;
 esac

También se podría haber incluído un rango de posibilidades

 echo "Ingrese un caracter: "
 read ELECCION
 case $ELECCION in
   [1-9]) echo "Usted ingreso un número";;
   [a-z]) echo "Usted ingreso una letra minúscula";;
   [A-Z]) echo "Usted ingreso una letra mayúscula";;
 esac

Hay que recordar que todos estos script podrán estar en un archivo, pero para que se ejecuten se le deberá primero dar los permisos pertinentes. Un par de cosas a tener en cuenta para la construcción de script son la forma en que se quiere que ejecute éste y la captura de teclas. Al ejecutarse un script de shell, se estará creando un bash hijo que lo ejecutará. Dado que las variables y funciones pertenecen al intérprete de comandos que las creó, al finalizar el script el proceso hijo del bash morirá y con el todos los seteos de variables y funciones. Por esto, si se quisiera que los cambios de las variables y las funciones que se definieron permanezcan para ser utilizables una vez que el script haya terminado, se deberá comenzar a ejecutar el script con un punto «.» seguido por un espacio antes del nombre de éste. De esta forma el proceso del intérprete de comando actual sera quien ejecute el script con lo que se conservaran todas las variables y funciones.

[shrek@pantano:~]$ . miscript

Un script puede dejar cosas sueltas antes de terminar si éste es finalizado bruscamente enviándole una señal de finalización [1] ya sea con la combinación de teclas CtrlC o con un kill -15. Para esto se deberán capturar estas señales para poder hacer una limpieza, ya se de variables o archivos, antes de finalizar. La forma de hacerlo es con el uso del comando trap; de esta forma se capturará la señal que se le envíe al script y se podrá ya sea ignorar la misma o ejecutar otro comando de limpieza. Para demostrar esto haremos un pequeño script que servirá de menú. La llamada al script del menú podría estar en el archivo .profile del usuario o en el .bash_profile. Si lo que no queremos es que el usuario salga del script con usando la combinación de teclas CtrlC, lo que haremos es capturar la señal y hacer que se ejecute nuevamente el script que se llamará simplemente menu.

 trap './menu' 2
 while :
 do
   echo 'a) Listado de archivos'
   echo 'b) Día y hora actual'
   echo 'c) Mes actual'
   echo 'Seleccione: '
   read ELECCION
   case $ELECCION in
     a|A)      ls;;
     b|B)      date;;
     c|C)      cal;;
     *)      echo "No eligió ninguna opción valida";;
   esac
 done

Como se ve al principio del script se utiliza el comando trap que al captura la señal 2 (SIGINT) que produce el CtrlC relanza el script. Al final del script se ve que se llama nuevamente dado que al ejecutarse el comando de cada elección se quiere que el menú siga funcionando. Practicar con estas construcciones será de gran ayuda para entender el proceso de construcción de script y los preparara para script más complejos usando otros interpretes como el sed, awk y el lenguaje perl. Para mayor información respecto a la construcción de script, remitirse a las páginas de manual del intérprete de comandos, en este caso man bash.

Variables autodefinidas por shell-script

$# —- Esta variable contiene el numero de argumentos que hemos pasado al script.
$0 —- Esta variable contiene el nombre de el shell-script que se ejecuta.
$* —- Esta variable muestra una cadena con los parámetros que hemos pasado al script.
$? —- Esta variable contiene la salida del comando anterior donde se encuentre dentro de el script.

Esto lo veremos mas claro añadiendo estas variables a nuestro script anterior

#!/bin/bash
#Paso de argumentos de forma ‘estática’.
echo «primera opción $1»
echo «segunda opción $2»
echo «tercera opción $3»
#Variables autodefinidas
echo «se ejecuta $0»
echo «tengo $# argumentos»
echo «los cuales han sido $*»
cp #este comando necesita parámetros, por lo tanto lanzara un error que $? capturara
echo «salida de error: $?»

Al ejecutar nuestro script, obtendremos la siguiente salida:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script2a primera segunda tercera
primera opción primera
segunda opción segunda
tercera opción tercera
se ejecuta script2a
tengo 3 argumentos
los cuales han sido primera segunda tercera
cp: falta un fichero como argumento
Pruebe `cp –help’ para más información.
salida de error: 1
rh3nt0n@rh3nt0n-laptop:~/scripts$

Como se puede apreciar las variables autodefinidas del script toman el valor de los parámetros y las circunstancias en las que se ejecuta el script, variando si estas circunstancias varían.

Comando para operaciones aritméticas

comando ‘expr’. Este comando suele usarse con asiduidad dentro de condicionales tanto simples como múltiples que explicare mas adelante, o para simplemente hacer operaciones aritméticas. Necesita como mínimo tres argumentos, dos operandos y un operador.
Los operadores son los típicos de operaciones aritméticas :
suma ———- ‘+’
resta ——— ‘-‘
multiplicación- ‘*’Este símbolo hay que escaparlo ‘\*’ dada su condición de carácter especial.
división——- ‘/’
modulo——— ‘%’ el modulo no es mas que el resto de una división, el cual suele ser el divisor menos uno.
Ejemplo de modulo: 100 % 5 ——> el modulo 5 de 100 sería de 0 a 4.Esto nos puede servir a la hora de generar un numero aleatorio, reducirlo a la cantidad que deseemos, Se entenderá mas adelante con algunos ejemplos.

Sintaxis: expr [operando1] operador [operando2]

Ejemplo de expr:

#!/bin/bash
#Ejemplo de expr (el cuadrado de un numero)
echo «Dame un numero.»
read numero
resultado=`expr $numero \* $numero` # declaramos la variable resultado, como resultado de expr
echo «El resultado de el cuadrado de $numero es $resultado»

La salida del script seria la siguiente:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script5
Dame un numero.
6
El resultado de el cuadrado de 6 es 36
rh3nt0n@rh3nt0n-laptop:~/scripts$

Como se puede observar read pide la variable numero, y expr se encarga de dar como valor a la variable resultado, la operación que realiza con la variable numero, la cual en este caso no es mas que una multiplicación por si misma. Como se puede también observar ‘escapamos’ el carácter asterisco ‘\*’ para que la shell no lo tome como metacarácter.

TEST

Comando ‘test’. Este comando para que no cause confusión desde el principio se suele abreviar usando solo corchetes [cadena valor cadena ] y suprimiendo el propio comando ‘test’, dentro de un ‘if’, ‘case’, ‘until’, ‘for’ etc … (que veremos mas adelante) o simplemente para definir una variable, variable=`[ $1 != $2 ]`
Como veo que me enredo mucho, veamos un ejemplo con test, con y sin comando.
Un sencillo ejemplo de ‘test’para ver su sintaxis:

#!/bin/bash
# ejemplo de test
test $1 = $2 # necesitamos dos argumentos al lanzar el script
echo $? #si ‘echo’ devuelve un 0 es que el comando test es verdadero.

Si lo ejecutamos introduciendo dos valores iguales como argumentos, el resultado de la comparación será verdadero, ya que evaluamos si $1 es igual ‘=’ a $2, por lo tanto ‘echo’ imprimirá un 0 en la pantalla:

rh3nt0n@rh3nt0n-laptop:~$ bash script6 uno uno
0
rh3nt0n@rh3nt0n-laptop:~$

En caso de que introduzcamos dos argumentos distintos, la comparación no será verdadera, y por lo tanto nos devolverá un 1:

rh3nt0n@rh3nt0n-laptop:~$ bash script6 paquito paquita
1
rh3nt0n@rh3nt0n-laptop:~$

Ahora probemos a editar el anterior script de la siguiente manera, y lo ejecutamos del mismo modo que el anterior:

#!/bin/bash
# ejemplo de test con corchetes
[ $1 = $2 ] # necesitamos dos argumentos al lanzar el script
echo $? #si ‘echo’ devuelve un 0 es que el comando test es verdadero.

Una vez ejecutado el script, nos daremos cuenta que es lo mismo poner los corchetes que la palabra test.

Como dijimos anteriormente, el comando test sirve para evaluar ficheros, cadenas de texto, y números, pero estos no se evalúan de la misma forma ya que evidentemente no son argumentos del mismo tipo, y cada uno se trata de forma diferente:

Modos de evaluar con ‘test’.

1º Evaluando ficheros.
Los ficheros se pueden avaluar con estos parámetros:
-f———–indica si el fichero existe.0 si es verdadero y 1 si es falso.
-s———–indica si el fichero existe y no esta vacio.0 si verdad, 1 si falso.
-r———–indica si tiene permiso de lectura.0 verdad, 1 falso.
-w———–indica si tiene permiso de escrituta.0 verdad, 1 falso.
-x———–indica si tiene permiso de ejecución.0 verdad, 1 faslo.
-d———–indica si es directorio. 0 verdad, 1 falso.
Estos parámetros se pueden unir usando los enlazadores :
-a———–and, ‘y’.
-o———–or, ‘o’.
!————not, no.

Veamos un ejemplo de evaluación de ficheros:

#!/bin/bash
# evaluación de ficheros con test.
[ -f $1 ] # al lanzar el script damos ruta relativa o absoluta del fichero.
echo $? #mostrara 0 si exite y 1 si no existe

Probemos con uno de nuestros scripts:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script7 script1
0
rh3nt0n@rh3nt0n-laptop:~/scripts$

Podemos comprobar que existe ya que la evaluación nos retorna un 0.

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script7 script10
1
rh3nt0n@rh3nt0n-laptop:~/scripts$

Podemos comprobar que no existe ya que test nos retorna un uno.
También podemos usar ‘read’ para introducir dinámicamente el fichero a evaluar.

2º Evaluando cadenas de texto.

Para evaluar cadenas de texto tenemos los parámetros:

parámetros:
‘=’ ———- igual
‘!=’———- distinto

Ejemplo:

#!/bin/bash
# evaluación de ficheros con test.
[ $1 != $2 ] # al lanzar el script damos dos cadenas de texto como argumento
echo $? #mostrara 0 si distinto y 1 si si igual

Si ejecutamos el script, nos dará en función de los argumentos una salida u otra.

números aleatorios:

Antes de nada, explicare como se genera un numero aleatorio usando la variable $RANDOM.
La variable $RANDOM genera un numero aleatorio de entre 1 y 32000, podemos necesitar conseguir un numero aleatorio para multitud de funciones, a mi por ejemplo se me ocurre una, los números de la primitiva, pero hay un problema, nos sobran muchos números ya que la primitiva solo tiene 48, para solucionar el problema utilizaremos la expresión ‘%’ modulo, la cual nos limita el numero aleatorio a el modulo que elijamos de este, en este caso será 49.
Lo mejor es un ejemplo:

#!/bin/bash
# aleatorio con random ‘primitiva’
alea=`expr $RANDOM % 49` # generamos un numero
aleatorio1=`expr $alea + 1`# nos aseguramos que no sea 0 sumándole 1
alea=`expr $RANDOM % 49` # el segundo ..
aleatorio2=`expr $alea + 1`
alea=`expr $RANDOM % 49`
aleatorio3=`expr $alea + 1`
alea=`expr $RANDOM % 49`
aleatorio4=`expr $alea + 1`
alea=`expr $RANDOM % 49`
aleatorio5=`expr $alea + 1`
alea=`expr $RANDOM % 49`
aleatorio6=`expr $alea + 1`
echo «Copia estos numeros:»
echo » $aleatorio1 – $aleatorio2 – $aleatorio3 » # imprimimos los tres primeros
echo » $aleatorio4 – $aleatorio5 – $aleatorio6 » # imprimimos los otros tres

La salida seria algo parecido a esto:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash aleatorio
Copia estos numeros:
24 – 2 – 29
6 – 33 – 11
rh3nt0n@rh3nt0n-laptop:~/scripts$

Por supuesto hay mas métodos para generar números aleatorios, pero me pareció la forma mas rápida y sencilla de que vierais un ejemplo, espero que halláis captado la idea.
Sigamos con text.

3º Evaluando números

Pensareis que con las opciones anteriores de evaluación de cadenas de texto, también se pueden evaluar números, y en cierto modo si se puede, pero hay que tener algo en cuenta :
[ 04 = 4 ]
Si nos damos cuenta, esa evaluación nos devolvería ‘1’, ya que el ‘=’ evalúa si 04 es igual a 4, y como cadena de texto, no lo es.
Por lo tanto, si lo que queremos es evaluar números, tenemos las siguientes opciones o parámetros:
-lt ——— menor que …
-le ——— menor o igual
-gt ——— mayor que …
-ge ——— mayor o igual
-eq ——— igual
-ne ——— no igual

Visto lo cual haremos un script para adivinar un numero aleatorio, en el cual nos basaremos para ir mejorándolo y para así entender lo que viene a continuación: condicional simple.

#!/bin/bash
# adivinador con evaluación numérica
echo «Adivina mi numero»
read adiv
aleatorio=`date +%S` #creamos un numero aleatorio en segundos de 0 a 59
aleatorio=`expr $aleatorio % 5` # lo reducimos a su modulo 5 (de 0 a 4)
# si nos damos cuenta hemos sobrescrito la variable $aleatorio
# no hay problema en esto …
[ $aleatorio -eq $adiv ] # evaluamos si el numero que hemos introducido es igual a el aleatorio
echo $? # nos imprime si lo es o no: 0 si, 1 no .

Ejecutad el script:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash adivinador
Adivina mi numero:
3
0
rh3nt0n@rh3nt0n-laptop:~/scripts$ bash adivinador
Adivina mi numero:
2
1
rh3nt0n@rh3nt0n-laptop:~/scripts$

Como se puede apreciar, en la primera ejecución he tipeado el numero 3, y he acertado, por consiguiente la salida de el comando test es 0.
Por contra, en la segunda ejecución, he tipeado 2, y he fallado, por consiguiente la salida ha sido un 1.

Bueno después de todo esto, espero que halla quedado claro lo que significa un 0 y lo que significa un 1 en la salida de de un test…sigamos

Condicional simple.

Cuando hablamos de condicional simple, básicamente hablamos de el uso de el comando ‘if’, el cual nos permite usar el ‘test’ para que dependiendo de la salida de este, nuestro script haga una cosa u otra.. veamos un ejemplo con el anterior script:

#!/bin/bash
# adivinador mejorado con if
echo «Adivina mi numero:»
read adiv
aleatorio=`date +%S` #creamos un numero aleatorio en segundos de 0 a 59
aleatorio=`expr $aleatorio % 5` # lo reducimos a su modulo 5 (de 0 a 4)
# si nos damos cuenta hemos sobrescrito la variable $aleatorio
# no hay problema en esto …
if [ $aleatorio -eq $adiv ] ; # evaluamos si el numero que hemos introducido es igual a el aleatorio
then # si es igual pasamos a el echo de la siguiente línea
echo «has acertado!!»
else # si no es igual pasamos a el echo de mas abajo
echo «has errado!!»
fi

Si lo ejecutamos:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash adivinador2
Adivina mi numero:
3
has errado!!
rh3nt0n@rh3nt0n-laptop:~/scripts$

Podemos ver que la principal diferencia es que la salida de test nos redirige el camino a tomar por el script hacia un comando u otro, según sea la salida de este falsa o verdadera.

sintaxis de comando ‘if’:

if [ evaluación ] ;

—-then

———paso a tomar si verdadero

—-else

———paso a tomar si falso

fi

Como podréis comprobar, este comando es de los que hay que identar para una mayor comprensión de el a la hora de comprenderlo cuando lo miremos tiempo después de hacerlo.

Respecto a su funcionamiento solo añadir, que en caso de que no se cumpla la condición evaluada, no es estrictamente necesario usar ‘else’, con lo cual la opción ‘else’ es opcional, si lo que nos interesa es una salida verdadera de la evaluación..

Otro ejemplo de ‘if’ pero esta vez evaluando ficheros:

#!/bin/bash
####################################
# Este script evalua dos ficheros dados de forma estatica#
# diciendonos cual es mayor en tamaño .###########
####################################
uno=`ls -l $1 | tr -s » » | cut -f5 -d » «` #filtramos el primer fichero
dos=`ls -l $2 | tr -s » » | cut -f5 -d » «` #filtramos el segundo fichero
if [ $uno -gt $dos ] ;
then
echo » $1 es mayor »
else
echo » $2 es mayor »
fi

Si ejecutamos nuestro script, evaluando por ejemplo dos de los script que hemos creado hasta ahora:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash ficheromayor /home/rh3nt0n/scripts/script1 /home/rh3nt0n/scripts/script7
/home/rh3nt0n/scripts/script7 es mayor
rh3nt0n@rh3nt0n-laptop:~/scripts$

Condicional múltiple.

Para explicar el uso de esta forma de condicionar, haremos una calculadora simple la cual necesitara de tres argumentos a añadir de forma ‘estática’.
así entenderemos el como y por que de la opción de el comando ‘case’ para poder hacer múltiples condiciones, sin necesidad de alargar el código con ‘if’ recurrentes, como en el siguiente caso:

#!/bin/bash
# calculadora con if.
if [ $3 = «suma» ]
then
expr $1 + $2
else
if [ $3 = «resta» ]
then
expr $1 – $2
else
if [ $3 = «multi» ]
then
expr $1 \* $2
else
if [ $3 = «divi» ]
then
expr $1 / $2
else
echo «opción no valida»
fi
fi
fi
fi

Si ejecutamos la calculadora:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash calculadora 34 56 suma
90
rh3nt0n@rh3nt0n-laptop:~/scripts$ bash calculadora 34 56 multi
1904
rh3nt0n@rh3nt0n-laptop:~/scripts$

Bien, vemos que la calculadora funciona, pero el código es demasiado extenso y además tiene demasiados ‘if’, y no es necesario si usamos ‘case’.

Comando ‘case’.

Sintaxis:(cambiad ‘>’ por espacios)
case variable in
>>>>>>patron1)>>>>ordenes ;;
>>>>>>patron2)>>>>ordenes ;;
>>>>>>patron3)>>>>ordenes ;;
.
.
.
>>>>>>*)>>>>>>>>ordenes ;;
esac

Veamos como ejemplo la calculadora anterior a que se reduce con ‘case’:

#!/bin/bash
# Calculadora con case
case $3 in
«suma»)
expr $1 + $2 ;;
«resta»)
expr $1 – $2 ;;
«multi»)
expr $1 \* $2 ;;
«divi»)
expr $1 / $2 ;;
esac

Al ejecutar nuestra nueva calculadora con la mitad de líneas gracias a case, tenemos que case nos permite dar múltiples valores a una variable y actuar de la forma que sea, según el valor que introduzcamos.

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash calculadora2 50 50 multi
2500
rh3nt0n@rh3nt0n-laptop:~/scripts$ bash calculadora2 50 50 suma
100
rh3nt0n@rh3nt0n-laptop:~/scripts$

Ciclos o loops.

Los ciclos o loops, sirven para hacer que cuando se cumple una determinada circunstancia, una orden se repita, hasta que esa circunstancia deje de cumplirse.
Para esto tenemos varios comandos que comentaremos a continuación:

Comando ‘while’.’mientras’

Este comando ejecuta las ordenes que contenga, si la condición es cierta.(0).

Sintaxis:
while [ condición ]
do
#orden
#orden
.
.
.
done

Veamos un ejemplo:

#!/bin/bash
# El cuadrado de 1 a 100 con while
cont=1
while [ $cont -lt 100 ] #siempre se usa test, se evalua que $cont sea menor que 100
do
cuad=`expr $cont \* $cont` #hacemos que $cuad valga el cuadrado de $cont
echo «el cuadrado de $cont es: $cuad»
cont=`expr $cont + 1` #hacemos que $cont se vaya incrementando en uno.
done

Al ejecutarlo, veremos que while hace que se repitan de la línea 4 a la 8, hasta que la condición $cont -lt 100, se incierta, o sea que $cont valga 100 o mas.

rh3nt0n@rh3nt0n-laptop:~$ bash script8
el cuadrado de 1 es: 1
el cuadrado de 2 es: 4
el cuadrado de 3 es: 9
el cuadrado de 4 es: 16
el cuadrado de 5 es: 25
.
.
.
el cuadrado de 94 es: 8836
el cuadrado de 95 es: 9025
el cuadrado de 96 es: 9216
el cuadrado de 97 es: 9409
el cuadrado de 98 es: 9604
el cuadrado de 99 es: 9801
rh3nt0n@rh3nt0n-laptop:~$

También tenemos la opción de el comando ‘until’ que hace lo mismo que while pero al contrario, o sea su negación.

Comando ‘until’.’hasta’ Negación de while.

Sintaxis:
until [ condición ]
do
ordenes #misma estructura que while
done

Veamos otro ejemplo:

#!/bin/bash
# imprimimos hasta 10 con until
cont=1
until [ $cont -gt 10 ] #hasta que $cont sea mayor que 10
do
echo $cont
cont=`expr $cont + 1`
done

Al ejecutarlo veremos que el bucle funciona hasta que la variable $cont es mayor que 10.

rh3nt0n@rh3nt0n-laptop:~$ bash script9
1
2
3
4
5
6
7
8
9
10
rh3nt0n@rh3nt0n-laptop:~$

Comando de iteración ‘for’.

Este comando es muy útil para evaluar y actuar sobre elementos que estamos pasando por parámetros.

Sintaxis:
for variable in ‘lista de parámetros’
do
ordenes
done

Veamos un ejemplo basico:

#!/bin/bash
# ejemplo basico de for
for numero in $1
do
echo $numero
done

Al ejecutarlo veremos que coge los argumentos y ejecuta uno a uno el comando entre do y done:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script10 «uno dos tres»
uno
dos
tres
rh3nt0n@rh3nt0n-laptop:~/scripts$

Continuemos con for.
Ahora veremos una forma de estructurar for condicionando directamente la variable a introducir por parametros.
Sintaxis:
for (( 1º ; 2º ; 3º ))
do
done
1º Da un valor de inicio a la variable.
2º Condiciona la variable.
3º Incrementa la variable.
Veamos un ejemplo tonto en el que nuestro script nos dirá de un rango entre dos números dados por parámetros la cantidad de números que hay entre ellos y que son menores que el mayor de los introducidos, en caso de que el primer parámetro sea mayor que el segundo se parara el script avisando del error :

#!/bin/bash
# mas opciones de for
if [ $1 -lt $2 ]
then
numero=`expr $2 + 1`
for (( i=$1 ; i<$numero ; i++ ))
do
echo «$i es menor que $numero»
if [ $i = $2 ]
then
exit 0
fi
done
else
echo «opcion incorrecta !! la primera variable a de ser menor»
fi

Si ejecutamos el script veremos que for da el valor a la variable i, la compara con el segundo parámetro dado, si es menor ejecuta el comando echo, y después incrementa el valor de i en uno, haciendo esto hasta que i es igual o mayor que el segundo parámetro:

rh3nt0n@rh3nt0n-laptop:~$ bash prueba 44 45
44 es menor que 46
45 es menor que 46
rh3nt0n@rh3nt0n-laptop:~$

Si la primera variable es mayor que la segunda, nos lanza el error y sale:

rh3nt0n@rh3nt0n-laptop:~$ bash prueba 46 45
opcion incorrecta !! la primera variable a de ser menor
rh3nt0n@rh3nt0n-laptop:~$

Como operar con los ciclos.

Podemos interactuar con los ciclos o bucles según se comporten estos, es decir, si por ejemplo obtenemos una indeterminación dentro de un bucle, podemos hacer que este pare y salte a la siguiente línea del script dejando el bucle, que siga con el bucle, o que el script pare.
Para esto, podemos usar los siguientes comandos:
Comando ‘break’. Si después de una indeterminación en un bucle, la shell encuentra un break, esta lo interpreta saltando el bucle y siguiendo con la siguiente orden después del bucle.
Comando ‘continue’. continue, es un escape, con lo cual, si el bucle termina correcta o incorrectamente, y la shell encuentra un continue, en lugar de proseguir con el siguiente comando después del bucle, vuelve a ejecutar el bucle.
Comando ‘exit’. Aunque exit no es un comando exclusivo de los bucles, también se usa con estos, en el caso de que queramos parar la ejecución del script, si se produce una situación determinada.

Para comprender el uso de estas ordenes, crearemos un script con un bucle que de como resultado una indeterminación. Por ejemplo una indeterminación seria el resultado de dividir un numero entre cero :

#!/bin/bash
# ejemplo de indeterminación
for (( i=-10 ; i<=10 ; i++ ))
do
if [ $i -ne 0 ] ; then
expr 1 \ $i
else
break # continue # exit # aqui probad con cada una de las opciones
fi
done

Ahora probemos estas opciones con un script mas útil, el siguiente ejemplo te dice de un rango de números dados por parámetros, cuales son pares:

#!/bin/bash
# ejemplo con continue break y exit
if [ $# -ne 2 ] ; then
echo «necesito dos argumentos»
exit 1
fi
if [ $1 -gt $2 ] ; then
echo «$1 no puede ser mayor que $2″
exit 2
fi
for (( i=$1 ; i<$2 ; i++ ))
do
mod=`expr $i % 2`
if [ $mod -ne 0 ] ; then
continue # aqui probad primero segun esta y despues con break y exit
fi
echo » $i es par !!»
done

Al ejecutarlo según esta, la salida será:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script13 4 9
4 es par !!
6 es par !!
8 es par !!
rh3nt0n@rh3nt0n-laptop:~/scripts$

Si cambiamos la línea que contiene el continue, por break o exit, la salida será como esta, ya que el bucle con estas dos opciones quedara inutilizado:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script13 4 9
4 es par !!
rh3nt0n@rh3nt0n-laptop:~/scripts$

Menús selectivos en shell-script.

En shell-script, podemos confeccionar menús con los cuales elegir opciones a ejecutar con solo pulsar una tecla, para esto tenemos el comando ‘select’, el cual siempre debe de ir acompañado de el comando ‘case’.
Sintaxis:
select i in lista de opciones
do
case
esac
done

Veamos un ejemplo:

#!/bin/bash
# ejemplo de select
select i in managed monitor cualquiera_orden salida
do
case $i in
«managed») echo «aquí podríamos poner la configuración de nuestra interfaz de red en modo managed»;;
«monitor») echo «aquí podríamos poner la configuración de nuestra interfaz de red en modo monitor»;;
«cualquiera_orden») echo «aquí podríamos hacer lo que nos diera la gana..»;;
«salida») break;;
*) exit;; # esta opción hace que con cualquier opción que tecleemos invalida, el script pare.
esac
done

Al ejecutarlo tendremos:

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script11
1) managed 3) cualquiera_orden
2) monitor 4) salida
#? 1
aquí podríamos poner la configuración de nuestra interfaz de red en modo managed
#? 3
aquí podríamos hacer lo que nos diera la gana..
#? 4
rh3nt0n@rh3nt0n-laptop:~/scripts$

Uso de funciones

Una función es un trozo de código que se utilizara con frecuencia en un script, y que solo varia en una variable.
Sintaxis:
nombre_funcion() {
código a ejecutar en la función
}
Veamos un ejemplo:

#!/bin/bash
# determina par e impar de los números que introduzcamos dinámicamente
determinaPar() { # aquí empieza la función
num=`expr $a % 2`
if [ $num -eq 1 ];then
echo «impar ; $a»
else
echo «par: $a»
fi
} # aquí termina la función
echo «Dame tres números»
read a1
read a2
read a3
export a=$a1
determinaPar
export a=$a2
determinaPar
export a=$a3
determinaPar

Si lo ejecutamos veremos que a cada variable introducida se le aplica la función, lo cual ahorra muchas líneas de código ya que sin usar la función, tendríamos que repetir continuamente el código que contiene esta, para cada variable, con lo que esto conllevaría.

rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script12
Dame tres numeros
700
75
12346
par: 700
impar: 75
par: 12346
rh3nt0n@rh3nt0n-laptop:~/scripts$

Captura de señales.

Podemos hacer que nuestro script capture señales a la shell, lanzadas desde el teclado tipo ‘crtl+c’ y que la shell las ignore.
Para esto, se usa el comando ‘trap’.
Comando ‘trap’.Atrapa señales.

Sintaxis:
trap ordenes señal
ó:
trap señal <—- captura señal

Veamos un ejemplo:

#!/bin/bash
# Ejemplo de trap
trap mensaje 2
mensaje() {
echo «no puedes pararme ;)»
}
while [ 1 -eq 1 ] # buble infinito
do
date
sleep 1
done

Al ejecutarlo veremos que con ‘ctrl+c’ no podemos pararlo, podremos ‘pararlo’ usando ‘ctrl+z’, pero no podremos terminarlo hasta que no hagamos un ‘kill %PID’ :

rh3nt0n@rh3nt0n-laptop:~/scripts$ vi script15
rh3nt0n@rh3nt0n-laptop:~/scripts$ bash script15
sáb nov 18 23:46:52 CET 2006
sáb nov 18 23:46:53 CET 2006
no puedes pararme 😉
sáb nov 18 23:46:54 CET 2006
sáb nov 18 23:46:55 CET 2006
no puedes pararme 😉
sáb nov 18 23:46:56 CET 2006
sáb nov 18 23:46:57 CET 2006
no puedes pararme 😉
sáb nov 18 23:46:57 CET 2006
sáb nov 18 23:46:58 CET 2006
sáb nov 18 23:46:59 CET 2006
[2]+ Stopped bash script15
rh3nt0n@rh3nt0n-laptop:~/scripts$ jobs
[1]- Stopped bash script15
[2]+ Stopped bash script15
rh3nt0n@rh3nt0n-laptop:~/scripts$kill %1
rh3nt0n@rh3nt0n-laptop:~/scripts$ jobs
[1]- Terminado bash script15
[2]+ Stopped bash script15
rh3nt0n@rh3nt0n-laptop:~/scripts$ kill %2
rh3nt0n@rh3nt0n-laptop:~/scripts$ jobs
[2]+ Terminado bash script15
rh3nt0n@rh3nt0n-laptop:~/scripts$

Categorías: Administracion

Programacion Bash Practica

Pura teoría

Los condicionales tienen muchas formas. La más básica es: if expresión then sentencia donde ‘sentencia’ sólo se ejecuta si ‘expresión’ se evalúa como verdadera. ‘2<1’ es una expresión que se evalúa falsa, mientras que ‘2>1’ se evalúa verdadera.

Los condicionales tienen otras formas, como: if expresión then sentencia1 else sentencia2. Aquí ‘sentencia1’ se ejecuta si ‘expresión’ es verdadera. De otra manera se ejecuta ‘sentencia2’.

Otra forma más de condicional es: if expresión1 then sentencia1 else if expresión2 then sentencia2 else sentencia3. En esta forma sólo se añade «ELSE IF ‘expresión2’ THEN ‘sentencia2′», que hace que sentencia2 se ejecute si expresión2 se evalúa verdadera. El resto es como puede imaginarse (véanse las formas anteriores).

Unas palabras sobre la sintaxis:

La base de las construcciones ‘if’ es ésta:

if [expresión];

then

código si ‘expresión’ es verdadera.

fi

Ejemplo básico de condicional if .. then

#!/bin/bash

if [ «petete» = «petete» ]; then

echo expresión evaluada como verdadera

fi

El código que se ejecutará si la expresión entre corchetes es verdadera se encuentra entre la palabra ‘then’ y la palabra ‘fi’, que indica el final del código ejecutado condicionalmente.

Ejemplo básico de condicional if .. then … else

#!/bin/bash if [ «petete» = «petete» ]; then

echo expresión evaluada como verdadera

else

echo expresión evaluada como falsa

fi

Ejemplo: Condicionales con variables

#!/bin/bash

T1=»petete»

T2=»peteto»

if [ «$T1» = «$T2» ]; then

echo expresión evaluada como verdadera

else

echo expresión evaluada como falsa

fi

Ejemplo: comprobando si existe un fichero

#!/bin/bash

FILE=~/.basrc

if [ -f $FILE ]; then

echo el fichero $FILE existe

else

echo fichero no encontrado

Los bucles for, while y until

En esta sección se encontrará con los bucles for, while y until.

El bucle for es distinto a los de otros lenguajes de programación. Básicamente, le permite iterar sobre una serie de `palabras’ contenidas dentro de una cadena.

El bucle while ejecuta un trozo de códico si la expresión de control es verdadera, y sólo se para cuando es falsa (o se encuentra una interrupción explícita dentro del código en ejecución).

El bucle until es casi idéntico al bucle loop, excepto en que el código se ejecuta mientras la expresión de control se evalúe como falsa.

Si sospecha que while y until son demasiado parecidos, está en lo cierto.

Por ejemplo

#!/bin/bash

for i in $( ls ); do

echo item: $i

done

En la segunda línea declaramos i como la variable que recibirá los diferentes valores contenidos en $( ls ).

La tercera línea podría ser más larga o podría haber más líneas antes del done (4).

`done’ (4) indica que el código que ha utilizado el valor de $i ha acabado e $i puede tomar el nuevo valor.

Este script no tiene mucho sentido, pero una manera más útil de usar el bucle for sería hacer que concordasen sólo ciertos ficheros en el ejemplo anterior.

for tipo-C

Fiesh sugirió añadir esta forma de bucle. Es un bucle for más parecido al for de C/perl…

#!/bin/bash

for i in `seq 1 10`;

do

echo $i

done

Ejemplo de while

#!/bin/bash

CONTADOR=0

while [ $CONTADOR -lt 10 ]; do

echo El contador es $CONTADOR

let CONTADOR=CONTADOR+1

done

Este script ‘emula’ la conocida (C, Pascal, perl, etc) estructura `for’.

Ejemplo de until

#!/bin/bash

CONTADOR=20

until [ $CONTADOR -lt 10 ]; do

echo CONTADOR $CONTADOR

let CONTADOR-=1

done

Utilizando select para hacer menús sencillos —

#!/bin/bash

OPCIONES=»Hola Salir»

select opt in $OPCIONES; do

if [ «$opt» = «Salir» ]; then

echo done

exit

elif [ «$opt» = «Hola» ]; then

echo Hola Mundo

else

clear

echo opción errónea

fi

done

Si ejecuta este script verá que es el sueño de un programador para hacer menús basados en texto. Probablemente se dará cuenta de que es muy similar a la construcción ‘for’, sólo que en vez de iterar para cada ‘palabra’ en $OPCIONES, se lo pide al usuario.

Utilizando la línea de comandos

#!/bin/bash

if [ -z «$1″ ]; then

echo uso: $0 directorio

exit

fi

SRCD=$1

TGTD=»/var/backups/»

OF=home-$(date +%Y%m%d).tgz

tar -cZf $TGTD$OF $SRCD

Lo que hace este script debería estar claro para usted. La expresión del primer condicional comprueba si el programa ha recibido algún argumento ($1) y sale si no lo ha recibido, mostrándole al usuario un pequeño mensaje de uso. El resto del script debería estar claro.

Leyendo información del usuario

En muchas ocasiones, puede querer solicitar al usuario alguna información, y existen varias maneras para hacer esto. Ésta es una de ellas:

#!/bin/bash

echo Por favor, introduzca su nombre

read NOMBRE

echo «¡Hola $NOMBRE!»

Como variante, se pueden obtener múltiples valores con read. Este ejemplo debería clarificarlo.

#!/bin/bash

echo Por favor, introduzca su nombre y primer apellido

read NO AP

echo «¡Hola $AP, $NO!»

Evaluación aritmética

Pruebe esto en la línea de comandos (o en una shell):

echo 1 + 1

Si esperaba ver ‘2’, quedará desilusionado. ¿Qué hacer si quiere que BASH evalúe unos números? La solución es ésta:

echo $((1+1))

Esto producirá una salida más ‘lógica’. Esto se hace para evaluar una expresión aritmética. También puede hacerlo de esta manera:

echo $[1+1]

Si necesita usar fracciones, u otras matemáticas, puede utilizar bc para evaluar expresiones aritméticas.

Si ejecuta «echo $[3/4]» en la línea de comandos, devolverá 0, porque bash sólo utiliza enteros en sus respuestas. Si ejecuta «echo 3/4|bc -l», devolverá 0.75.

Capurando la salida de un comando–

Este pequeño script muestra todas las tablas de todas las bases de datos (suponiendo que tenga MySQL instalado). Considere también cambiar el comando ‘mysql’ para que use un nombre de usuario y clave válidos.

#!/bin/bash

DBS=`mysql -uroot -e»show databases»`

for b in $DBS ;

do

mysql -uroot -e»show tables from $b»

done

Operadores de comparación de cadenas

s1 = s2

s1 coincide con s2

s1 != s2

s1 no coincide con s2

s1 < s2

s1 es alfabéticamente anterior a s2, con el locale actual

s1 > s2

s1 es alfabéticamente posterior a s2, con el locale actual

-n s1

s1 no es nulo (contiene uno o más caracteres)

-z s1

s1 es nulo

Ejemplo de comparación de cadenas

Comparando dos cadenas

#!/bin/bash

S1=’cadena’

S2=’Cadena’

if [ $S1!=$S2 ];

then

echo «S1(‘$S1’) no es igual a S2(‘$S2’)»

fi

if [ $S1=$S1 ];

then

echo «S1(‘$S1’) es igual a S1(‘$S1’)»

fi

Operadores aritméticos

+ (adición)

– (sustracción)

* (producto)

/ (división)

% (módulo)

Operadores relacionales aritméticos

-lt (<)

-gt (>)

-le (<=)

-ge (>=)

-eq (==)

-ne (!=)

Los programadores de C tan sólo tienen que corresponder el operador con su paréntesis.

Comandos útiles

Esta sección ha sido reescrita por Kees (véanse agradecimientos)

Algunos de estos comandos contienen lenguajes de programación completos. Sólo se explicarán las bases de estos comandos. Para una descripción más detallada, eche un vistazo a las páginas man de cada uno.

sed (editor de flujo)

Sed es un editor no interactivo. En vez de alterar un fichero moviendo el cursor por la pantalla, se utiliza una serie de instrucciones de edición de sed, y el nombre del fichero a editar. También se puede describir a sed como un filtro. Miremos algunos ejemplos:

$sed ‘s/a_sustituir/sustituto/g’ /tmp/petete

Sed sustituye la cadena ‘a_sustituir’ por la cadena ‘sustituto’, leyendo del fichero /tmp/petete. El resultado se envía a stdout (normalmente la consola), pero se puede añadir ‘> captura’ al final de la línea de arriba para que sed envíe la salida al fichero ‘capture’.

$sed 12, 18d /tmp/petete

Sed muestra todas las líneas de /tmp/petete excepto la 12 y la 18. El fichero original no queda alterado por este comando.

awk (manipulación de bases de datos, extracción y proceso de texto)

Existen muchas implementaciones del lenguaje de programacin AWK (los intérpretes más conocidos son gawk de GNU, y el ‘nuevo awk’ mawk). El principio es sencillo: AWK busca un patrón, y por cada patrón de búsqueda que coincida, se realiza una acción.

Si tenemos un fichero /tmp/petete con las siguientes líneas:

«prueba123

prueba

pprruueebbaa»

y ejecutamos:

$awk ‘/prueba/ {print}’ /tmp/petete

El patrón que busca AWK es ‘prueba’ y la acción que realiza cuando encuentra una línea en /tmp/petete con la cadena ‘prueba’ es `print’.

$awk ‘/prueba/ {i=i+1} END {print i}’ /tmp/petete

Cuando se utilizan muchos patrones, se puede reemplazar el texto entre comillas por ‘-f fichero.awk’, y poner todos los patrones y acciones en ‘fichero.awk’.

grep (impresión de líneas que coinciden con un patrón de búsqueda)—

Ya hemos visto ejemplos del comando grep en los capítulos anteriores, que muestra las líneas que concuerdan con un patrón. Pero grep puede hacer más que eso.

$grep «busca esto» /var/log/messages -c

12

Se ha encontrado 12 veces la cadena «busca esto» en el fichero /var/log/messages.

[vale, este ejemplo es falso, el fichero /var/log/messages está alterado :-)]

wc (cuenta líneas, palabras y bytes)

En el siguiente ejemplo, vemos que la salida no es lo que esperábamos. El fichero petete utilizado en este ejemplo contiene el texto siguiente:

«programación en bash

como de introducción»

$wc –words –lines –bytes /tmp/petete

2 5 41 /tmp/petete

Wc no tiene en cuenta el orden de los parámetros. Wc siempre los imprime en un orden estándar, que es, como se puede ver: líneas, palabras, bytes y fichero.

sort (ordena líneas de ficheros de texto)

Esta vez, el fichero petete contiene el texto siguiente:

«b

c

$sort /tmp/petete

Esto es lo que muestra la salida:

a

b

c

Categorías: Administracion