# Chuletario de comandos para administrar Linux
### Ejecutar un script desde el propio directorio donde se localiza el script

Es frecuente tener que ejecutar scripts que hagan referencia a otros ficheros (csv, txt, conf,...) relativos al mismo. Conviene entonces cambiar el directorio activo (cwd) antes de ejecutar nada. Puesto que a veces el script debe ser ejecutado simultáneamente desde cron, ssh, línea de comandos, otros script,... al mover el mismo nos vemos obligados a cambiar todos los anteriores. Para solucionarlo ejecutamos al comienzo del script el siguiente comando:

### Desviar la salida estándar de un script

Utilizamos exec justo como segunda línea del script. Ej:

### Concatenar la salida de varios comandos en Bash

Supongamos que queremos enviar un email concatenando varias campos. Algunos de estos campos están generados a partir de un fichero plantilla, otros a partir del valor de una variable del propio script u otras fuentes. Queremos que enviar la salida conjunta de todos estos comandos a la entrada estándar del programa de envio de correo ssmtp.
Intuitivamente podríamos intentar algo similar a:
Sin embargo el ejemplo anterior falla ya que ssmtp recibiría únicamente la salida del último echo. Para evitar este problema empaquetamos todos los comandos anteriores entre paréntesis:
Como se vé sólo hace falta utilizar la tubería | una sóla vez indicando que la salida de ( comando1 ... comandoN) sea desviada a /usr/sbin7ssmtp.

### Rotando logs (forma simple)

Aviso: GNU rottlog y/o logrotate (man 8 logrotate) son herramientas mucho más convenientes para rotar logs. El script mostrado a continuación sirve sólo como referencia.

### Para buscar un fichero y ejecutar un comando sobre el fichero encontrado

La salida podría ser similar a:
find permite anidar condiciones OR (unión) mediante "-or". Por ejemplo para buscar nombres acabados en .c o .h:

### Mini código para tratar locks de forma "segura" mediante find

Consideramos que un lock es válido si tiene 20 minutos o menos de antigüedad. En cualquier otro caso se considera un error (bien porque hay otro script todavía en ejecución, en cuyo caso abortamos, o porque el último script murió sin borrar el fichero). Todo el truco consiste en utilizar find con la opción "-mmin -20". En el siguiente script CONTINUAR/while se utilizan para poder saltar al final del bloque principal mediante break al igual que si tubiesemos una etiqueta :END e hiciesemos GOTO END. La variable ERRORES se utiliza se va rellenando. Al final del scripts si no está vacia se considerá que hubo un error y se logea y envía por correo.

### Uso de socat para test de aplicaciones de red

P.ej, para simular el tráfico UDP hacia una aplicación escuchando en el puerto 30001:
En una segunda terminal lanzamos los datos simulados en un fichero de texto previamente creado:

### Captura de tráfico con tcpdump

P.ej, para capturar el tráfico udp que nos envían a un servidor ejecutamos como root en el propio servidor el comando:
También se puede capturar a un archivo en modo binario, y luego recuperarlo:
Y para verlo después:
con -r lo recuperamos del archivo donde se guardó en el comando anterior, y con -A se ve en ASCII. También puede utilizarse Wireshark para leer el fichero capturado.

### Configuración de acceso ssh sin contraseña

La idea es crear un conjunto de llave pública y privada, de forma que la llave pública la colocamos en el host remoto al que queremos acceder y la llave privada la guardamos localmente en el host local desde el que queremos conectar. Localmente creamos el par llave pública/privada mediante ssh-keygen:
A continuación (como root) copiamos el id_dsa a todos los usuarios que convenga (/home/miUsuario2/.ssh/id_dsa, /home/miUsuario3/.ssh/id_dsa,...) y en el servidor añadimos la clave pública (/home/"miUsuario/.ssh/id_dsa.pub) a la lista de llaves autorizadas de cada usuario que queramos (notar que el usuario1 en local puede querer acceder como un usuario diferente en la máquina remota). La forma más sencilla (suponiendo que ya hemos "subido" id_dsa.pub al servidor mediante un un correo, por samba, scp, memoryStick,...) es hacer algo similar a:

### Backups diarios en red con ayuda de ssh

Una vez configuradio ssh sin contraseña es muy sencillo utilizar ssh para hacer copias en red utilizando el sistema estandar de tuberías Unix. El siguiente crontab muestra como hacerlo en práctica para copiar la base de datos de Zope/Plone y el repositorio CVS:
Al tratarse de un comando de red el prefijo "ping -q -c 1 -w 1 servidor1 &&" evita continuar con el comando si el ping ha fallado. ver man ping para una explicación detallada de las opciones (-q = "quiet" evita mandar texto a la salida estandar, -c 1 = realizar un solo ping, -w 1=esperar máximo 1 segundo). Algunas opciones útiles que podríamos pasar a ssh para scripts automatizados son las siguientes:
'En general es una mala costumbre poner en el cron el comando ping ... && ssh. Es menos arriesgado y más práctico crear un script /opt/scriptsCRON/backup1.sh y añadir el mismo a la linea de cron, sin olvidar hacer backups del directorio /opt/scriptsCRON/'.

### Ejemplo de copia en paralelo de varias máquinas

El siguiente script surgió de la necesidad de copiar los ficheros que se iban generando continuamente en varias máquinas (windows con cygwin+ssh) a un servidor apache bajo Linux:

### Reencaminando puertos mediante SSH

Suponemos que tenemos una red local 192.168.1.X en la oficina 1 y una red local 192.168.2.X en la oficina 2. Suponemos que una máquina cliente Cliente1 de la oficina 1 dispone de acceso a ssh a un servidor (sshd) ServidorSSHOficina2 en la oficina 2 (basta con una sóla máquina en la oficina 1 y un sólo servidor en la oficina 2).
Para reencaminar el tráfico de un puerto/s en el cliente Cliente1 hacia un servidor/es y puerto en la red de la oficina 2 hacemos lo siguiente:
Con esto conseguimos que al conectar a Cliente1:MiPuertoLocalA dentro de la oficina 1 veamos el servicio ServidorRemotoA:PuertoRemotoA de la oficina 2. ServidorRemotoA puede ser o no ser el mismo ServidorSSHOficina2. La única condición es que ServidorSSHOficina2 tenga acceso al mismo.
Igualmente podemos a la inversa hacer lo siguiente:
Con esto conseguimos que al conectar a ServidorSSHOficina2:PuertoRemotoA dentro de la oficina 2 veamos el servicio ServidorLocalA:PuertoServidorLocalA de la oficina 1. ServidorLocalA puede ser o no ser el propio Cliente1. La única condición es que Cliente1 tenga acceso por red al mismo.

### Tuneles con SSH (conexión punto a punto o "puente" ethernet)

AVISO: ¡¡¡los tuneles ssh utilizan apliamiento tcp sobre tcp y en general es peor opción que otras soluciones más avanzadas como openvpn, sin embargo es mucho más rápido de configurar!!!. Se supone que tanto el cliente como el servidor tienen configurado correctamente el soporte para "TUN" (tun permite crear interfaces "virtuales" de red dinámicamente).
En el servidor necesitamos editar /etc/ssh/sshd_config y añadir/modificar una línea con la opción
reiniciando el servicio para que los cambios tengan efecto:
A continuación conectamos con las siguientes opciones:
En otra terminal local:
Comprobamos que los 2 extremos del punto a punto se ven mutuamente. En Cliente1 hacemos ping a 10.0.0.1 y en ServidorRemotoOficina2 hacemos ping a 10.0.0.2. A continuación bastará con crear las reglas de ruteo que consideremos necesarias. - Si en vez optar por una opción punto a punto utilizamos el modo "Bridge" (-o Tunnel=ethernet) el cliente y servidor ssh engañaran al protocolo ARP haciendo creen que los hosts de la oficina1 y 2 están unídos físicamente, pero puede generar conflictos de IP repetidas en ambos extremos. Básicamente en modo bridge (ethernet) cuando un host pregunta cual es la MAC física de una dirección, p.ej, 192.168.2.15, el cliente SSH "preguntará" al servidor en la oficina 2 si él conoce la IP y si el servidor le responde afirmativamente el cliente SSH responderá al host local "yo soy 192.168.2.15". A continuación cada vez que el host (que ha cacheado en su tabla ARP al Cliente SSH como la IP 192.168.2.15") haga una petición a dicha IP, el tráfico se reencaminará por el tunel SSH.
En general como usuario "no root", sin permisos especiales.
Muy importante: CIFS/SMB/Samba no es fiable (2009-11-27). Su uso generalizado se debe simplemente a que es la forma estándar de conectar PCs Windows. Una opción mucho más fiable y resistente es instalar cygwin en las máquinas con Windows y utilizar ssh (scp, sftp,...) en su lugar. SSH además posibilita opciones imposibles con CIFS/SMB/Samba como p.ej, cifrado, sincronizar de volúmenes enormes de datos en segundos con ayuda de rsync, aplicar filtros antes de copiar o distribuir la carga de cpu entre dos sistemas en red.
Una vez comprobado que funciona manualmente podemos añadir a /etc/fstab para que se monte automáticamente añadiendo una línea similar a:
Como referencia y para comparar. Si utilizamos NFS en lugar de Samba (NFS es mucho más rápido, estable y fiable pero sólo en redes Linux/UNIX, no windows):
En /etc/fstab:

### Generar un fichero core cuando se produzca un fallo de segmentación

En bash:
En tcsh:
Al ejecutar un programa que genere un "SEGMENTATION FAULT" el kernel creará un fichero de nombre "core". Entonces podremos utilizar este core como entrada al depurador gdb para saber exáctamente dónde se generó el fallo. Ej:
bt (back trace) muestra las últimas funciones invocadas antes de producirse el error. En este caso puede verse que la línea miBiblioteca.c llamó a la función estándar g_free de libglib en la línea 87, probablemente con un argumento no válido (puntero nulo, ...).

### Disminuir la velocidad del ratón en X

Muy útil para programas de dibujo/autocad/...