jueves, 19 de noviembre de 2009

Inventariando

Ante la tarea de inventariar los equipos que tenemos así como sus características principales (fabricante, modelo, ram, cpu,...), se hace imprescindible contar con un script que capture todos estos valores y nos los presente de manera resumida.

Aquí van algunos comandos para capturar información valiosa:

1. Memoria RAM instalada:

# echo "Memoria RAM (MB): "`free -m | grep Mem | tr -s "  " " " | cut -d " " -f 2`

2. Unidades de almacenamiento (discos duros, memorias USB, etc):

# echo "Discos duros:" && fdisk -l | grep "Disco /dev/" | cut -d " " -f 3,4 | tr -d ","

3. Fabricante, modelo y número de serie:

# lshw | grep -e product -e vendor -e serial | head -n 3

4. Procesador/es:

# cat /proc/cpuinfo | grep "model name" | sed "s/model name\t/Procesador/"

5. Número total de cores:

# grep 'model name' /proc/cpuinfo | wc -l

6. Para los sistemas Ubuntu, la versión:

# cat /etc/lsb-release | grep "DESCRIPTION" | cut -d "=" -f 2 | tr -d "\""

En Linux existen como véis multitud de comandos para conocer cualquier información. Es cuestión de investigar un poco por nuestro sistema (y googlear) para saber cómo hacer algo.

viernes, 13 de noviembre de 2009

Problema con cron

Cuando se tienen máquinas viejas actuando como servidores, es probable que no mantengan adecuadamente la hora del sistema. Y aunque cambiar la pila de botón de la placa base suele solucionar el problema, en ocasiones no es así (evidencia deterioro de hardware).

Lo normal es configurar cron para que ejecute el comando ntpdate -u servidor_hora cada cierto tiempo (por ejemplo una vez el día) para mantener la hora del sistema:

# crontab -e

[...]
0 0 * * * ntpdate -u ip_o_nombre_servidor_hora
[...]

Pero... transcurridos unos días accedemos al servidor y vemos que la hora va mal. Para asegurarnos que el comando se ha ejecutado, chequeamos el fichero syslog:

$ grep ntpdate /var/log/syslog
[...]
Nov 11 00:00:01 mipc /USR/SBIN/CRON[360]: (root) CMD (ntpdate -u 192.168.1.1)
Nov 12 00:00:01 mipc /USR/SBIN/CRON[1066]: (root) CMD (ntpdate -u 192.168.1.1)
Nov 13 00:00:01 mipc /USR/SBIN/CRON[1697]: (root) CMD (ntpdate -u 192.168.1.1)
[...]

Entonces, ¿qué ocurre?

Ocurre que cron no ejecuta los comandos programados (en nuestro caso ntpdate) dentro de un bash, por lo que los directorios en los que busca cron el comando ntpdate para ejecutarlo puede que no lo contengan. Cron intentó ejecutar el comando a las 00:00 todos los días (syslog da fe) pero el comando no se encontró. Claro, nosotros hacemos pruebas y lo ejecutamos en nuestro shell bash, con un valor apropiado en nuestra variable $PATH, vemos que funciona y asumimos que tiene que funcionar con cron.

Una solución sencilla es indicar la ruta completa del comando ntpdate en el crontab:

# crontab -e

[...]
0 0 * * * /usr/sbin/ntpdate -u ip_o_nombre_servidor_hora
[...]

Así funcionará sin problemas.

miércoles, 11 de noviembre de 2009

Ejecución de sentencias SQL desde scripts

En alguna ocasión nos puede interesar que algún script realice una consulta o inserción contra una base de datos. Os voy a indicar una sencilla forma de hacerlo, siempre y cuando uséis PostgreSQL como SGBD.

Lo primero de todo, será tener instalado el cliente de Postgresql, que para la versión 9.10 de Ubuntu es el siguiente paquete:

# aptitude install postgresql-client-8.3 (ó 8.4)

Tras instalarlo, deberemos tener disponible el comando psql.

Desde un script, basta con ejecutar:

$ echo "INSERT INTO inventario_macs VALUES ('192.168.1.1', '00:60:08:63:f5:4f');" | psql -h 192.1681.100 -d bd_pruebas -U upruebas

Indicar varias cosas:
  • La opción -h especifica la IP o nombre del servidor que aloja la base de datos.
  • La opción -d especifica la base de datos a la que queremos conectarnos (el servidor puede alojar varias bases de datos).
  • La opción -U especifica el usuario con que nos vamos a conectar.
Hay que tener en cuenta que la base de datos puede estar configurada para que solicite contraseña ante un acceso (autenticación activada) o no. Si no está activa esta opción, el comando anterior funcionará sin problemas. Si estuviese activa, al ejecutar el comando psql se nos preguntará por la contraseña, por lo que no es viable para usarlo en scripts de ejecución automatizada.

Para establecer entre una máquina cliente y otra servidor un vínculo de confianza con el objetivo de que no nos pidan la contraseña por cada acceso que queramos hacer (como ocurre con ssh), realizar los siguientes pasos en la máquina cliente:

1. Crear un fichero con nombre .pgpass en el directorio home del usuario que accederá a la base de datos. Este fichero contendrá lineas con el siguiente formato: hostname:puerto:base_datos:nombre_usuario:password. En nuestro caso:

192.168.1.100:5432:bd_pruebas:upruebas:micarromelorobaron

2. Asignar los permisos adecuados al fichero:

$ chmod 0600 .pgpass

Tras ello, podremos lanzar el comando anterior pues no se volverá a preguntar el password de acceso a la base de datos.

Como añadido, indicar que es muy cómodo a la hora de crear tablas redactar en nuestro propio equipo un archivo de texto con las sentencias SQL correspondientes, y luego ejecutarlas en el servidor de la forma:

$ cat fichero.sql | psql -h 192.1681.100 -d bd_pruebas -U upruebas

martes, 10 de noviembre de 2009

Seguimiento de IPs para obtener su MAC

Hasta ahora hemos visto la forma de obtener la MAC de una IP, pero claro, la IP tiene que estar en uso para poder conocer su MAC. ¿Cómo podríamos hacer para conocer la MAC de varias IPs que aunque no están en uso actualmente sí lo pueden estar en las próximas horas o días?

Se hará lo siguiente: tendremos una lista de IPs a chequear (de las cuales no conocemos sus direcciones MAC). Cada cierto tiempo (pongamos cada hora) se chequearán todas las IPs y las que respondan a ping (y por tanto obtengamos su MAC) las iremos anotando en otra lista.

La lista de IPs a chequear la tendremos en el fichero ips:

192.168.1.2
192.168.1.5
192.168.1.100
192.168.1.200
192.168.1.240

Realizaremos el script que chequeará cada vez que sea llamado:

#!/bin/sh

IFS="
"

for IP in $(cat ips)
do
  MAC=`ping -c 1 $IP >/dev/null 2>&1 && arp -n | grep "$IP " | awk '{print $3}'`
  if [ $? -eq "0" ]; then
    echo $IP $MAC >> macs
  else
    echo $IP >> tmp
  fi
done

mv tmp ips

Y por último, configuraremos cron para que llame al script cada hora:

$ crontab -e
0 * * * * sh /home/juan/chequear.sh

Indicar que, según muestra el script, en el fichero ips nos irán quedando las IPs que no han respondido a ping y en el fichero macs las IPs junto a sus MAC.

lunes, 9 de noviembre de 2009

Ejecución de comandos tras el arranque del S.O.

Si deseamos ejecutar algún comando o script tras el arranque del sistema operativo, deberemos especificarlo en el fichero /etc/rc.local:

ntpdate -u 192.168.1.1

Añadiendo esta linea bastaría para que tras el arranque de Linux, un equipo sincronice su hora con un servidor de hora (supuesto que el equipo 192.168.1.1 tenga corriendo el servicio ntpd). Esto es muy interesante para equipos con bastantes años que no llevan correctamente la hora del sistema.

Ahora bien, prefiero hacerlo bonito y que quede totalmente integrado con la "estética" del arranque en modo consola de Ubuntu (como en Ubuntu server):

echo -n " * Actualizando la hora del sistema... "
ntpdate -u 192.168.1.1
echo "OK"

viernes, 6 de noviembre de 2009

Simular comando watch

El comando watch es bastante útil si queremos monitorizar algún valor. Ejecuta el comando que le indiquemos por parámetro cada x segundos indicados también por parámetro, mostrando la salida del comando:

$ watch -n 1 date

En el ejemplo anterior, se ejecutará el comando date cada segundo (si no se indica periodicidad, por defecto son 2 segundos).

Ahora bien, ¿como podemos simular este comando en equipos que no disponen de él? Ejemplos de ello son instalaciones estándar de algunos sistemas Unix-like. Lo haremos de la siguiente forma:

#!/bin/sh

funcion(){
clear
date
}

while [ 1 ];
do
  funcion
  sleep 1
done

Este script tiene dos puntos clave: el comando a ejecutar (date en nuestro caso) y la cantidad de segundos a esperar por cada ejecución (1 en nuestro caso). Adaptando estas lineas simularéis el comando watch para la ejecución de lo que queráis.

miércoles, 4 de noviembre de 2009

Averiguando versión de Ubuntu

Basta con leer el contenido del siguiente fichero:

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=9.10
DISTRIB_CODENAME=karmic
DISTRIB_DESCRIPTION="Ubuntu 9.10"

martes, 3 de noviembre de 2009

Transferir ficheros con netcat

Imaginemos que necesitamos transferir un fichero por red entre dos máquinas y que, por el motivo que sea, no lo podemos hacer por ftp, scp,... bien por desconocimiento de passwords o por falta de esos servicios. En este caso, netcat es nuestra aplicación.

En la máquina receptora del fichero estableceremos netcat como servidor en un determinado puerto:

$ nc -l -p 5000 > fichero.odt

Lo que hará será escuchar por ese puerto y todo lo que reciba escribirlo al fichero fichero.odt (si no hubiésemos redirigido la salida estándar aparecería por pantalla).

En la máquina origen (la que tiene el fichero deseado), ejecutar el comando:

$ cat fichero.odt | nc 192.168.1.1 5000 -q 0

Supuesto que el servidor destino tiene dicha IP. Lo que hacemos en este caso es pasarle como entrada a netcat el contenido del fichero, y este lo enviará a la IP y puerto indicados. La opción -q 0 cerrará la conexión con el otro extremo cuando finalice la transmisión del fichero.

Si desconfiáis de que el contenido del fichero transmitido sea correcto, ejecutad en ambos servidor el comando:

$ md5sum fichero.odt
22cd94e9c8db682d2f3cb432649eb6b8  fichero.odt

para comparar el hash del fichero.

Se permiten muchas variaciones, como por ejemplo comprimir el fichero antes de mandarlo para generar menos tráfico de red y/o tardar menos en transmitirlo:

$ gzip -c fichero.odt | nc 192.168.1.1 5000 -q 0

lunes, 2 de noviembre de 2009

Averiguando MAC desde IP

En ocasiones nos puede interesar conocer la MAC de una determinada IP de nuestra red, bien para temas de inventario o para saber si alguien se ha cambiado indebidamente su IP.

Este sencillo script nos ayudará a obtener la MAC de la IP indicada como parámetro:

#!/bin/sh
ping -c 1 $1 >/dev/null 2>&1 && arp -n | grep $1 | awk '{print $3}'

Su llamada sería:

$ ./obtener_mac 192.168.1.1
00:13:f7:e9:96:cf

Si quisiéramos realizar un listado completo de IPS-MACS de nuestra red, podríamos adaptar el script de esta forma:

#!/bin/sh

for IP in $(seq 254)
do
  MAC=$(ping -c 1 $1$IP >/dev/null 2>&1 && arp -n | grep "$1$IP " | awk '{print $3}')
  echo $1$IP - $MAC
done

Suponiendo una red de clase C y pasando como parámetro la parte fija de la dirección IP:

$ ./listado_macs 192.168.2.
192.168.2.1 - 00:13:f7:e9:96:cf
192.168.2.2 -
192.168.2.3 -
[.......]