Archivo

Archivo para la categoría ‘sysadmin’

Sincronizar carpetas a un Servidor Casero automáticamente

Viernes, 18 de junio de 2010 Marcelo Sin comentarios

Introducción

Supongamos que tengo un equipo donde usualmente estoy trabajando y otro equipo que está siempre encendido, ambos separados por Internet. En este último, el único puerto abierto sobre una IP Pública es el 22 para usar SSH, con lo cual me viene perfecta la capacidad de rsync de sincronizar carpetas y los últimos cambios mientras estoy trabajando, todo mediante un canal seguro.

El Script de sincronización

Lo único que necesito es este script en la carpeta personal de mi equipo “cliente”, o sea, donde hago mis quehaceres diarios:

#!/bin/bash
# Script para sincronización a Servidor vía Casero rsync/ssh.
#
# Copyleft 2010 - Licencia BSD
# Autor: Marcelo Fernández.
# Email: marcelo.fidel.fernandez@gmail.com
#
# Características:
#  - Guarda la salida en un archivo de log (~/sync.log).
#  - Sincronización de una vía; pisa las modificaciones (y elimina) en el destino.
#  - Envía notificaciones al escritorio del usuario.
#  - Se sugiere ser llamado desde cron (gnome-schedule para el usuario final).
#  - Sincroniza (una sola vía) el directorio Documentos de mi Carpeta Personal y el Escritorio,
#    se pueden agregar más carpetas a gusto al momento de ejecutar el comando rsync.
#    También debe personalizarse el destino del backup, ahora en /media/Disco1/Backup
#
# Requerimientos:
#  - Rsync
#  - Paquete libnotify-bin (Debian/Ubuntu), que brinda el comando notify-send.
#
# Parámetros:
#  - Host destino. El script se lo llama "./sync.sh mi_host".
#    El login debe ser vía public keys, y la passphrase la maneja Gnome.
 
HOST=$1
LOG_FILE="sync.log"
export DISPLAY=:0.0 # Para el notify
export SSH_AUTH_SOCK="$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name '*ssh' | head -n 1)"
 
notify-send -u normal --icon=gtk-refresh --category=transfer "Sincronizando a Casa..."
echo `date` >> $LOG_FILE
rsync -avz -e 'ssh' --delete ~/Documentos ~/Escritorio $HOST:/media/Disco1/Backup/ &>> $LOG_FILE
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
    notify-send -u critical --icon=gtk-dialog-error --category=transfer.error  "Error al Sincronizar";
else
    notify-send -u normal --icon=gtk-apply --category=transfer.complete "Sincronización Completa";
fi

Programando su ejecución automática

Este script está pensado y preparado para ser llamado desde la aplicación “Tareas Programadas” de Gnome (disponible en el Centro de Software de Ubuntu o se instala haciendo click aquí):

Este es el detalle de la configuración de la tarea:

Y además nos avisa de que está trabajando y si tuvo éxito o no al sincronizar:

Algunas cuestiones para destacar

Como se aclara en los comentarios, cada vez que rsync copia las modificaciones al servidor, “pisa” lo que había anteriormente, lo que comúnmente se denomina sincronización de archivos “de una vía“.

Lo más interesante es que a pesar de ser ejecutado desde Cron, aprovecha las llaves SSH desbloqueadas por Gnome en la sesión de escritorio del usuario, es decir que la primera sincronización, si previamente no me había conectado al equipo remoto, me pide la frase de paso para desbloquear la clave privada; a partir de ese momento ésta queda compartida, gracias al ssh-agent que utiliza Gnome en background. Luego, mientras siga la sesión de escritorio establecida, va a aprovechar la llave desbloqueada por el usuario y hacer la sincronización sin mayor problema. Esto es mucho mejor en cuanto a seguridad que usar una clave privada sin frase de paso contra el servidor, y me permite desbloquearla sólo la primera vez y no cada vez que se hace la sincronización, siendo un perfecto balance (al menos para mí) entre seguridad, automatización y comodidad. Lógicamente esto sirve para utilizar en cualquier conexión SSH que se quiera establecer, y la solución, después de dar muchas vueltas y probar muchas alternativas (¡el ssh del cron no “veía” al agente!), la encontré en este post.

Conclusión

Este script fue creciendo desde algo muy simple, totalmente manual y que ejecutaba “cada vez que me acordaba” a mejorarlo un poco en cuanto a la automatización y hacerlo más “lindo” como está hoy. Si bien hay muchísimos mecanismos más robustos o con más facilidades (usando los snapshots de rsync por ejemplo y/o sincronizando ida y vuelta), éste es el que funciona para mí. Es bien claro lo que hace y no hay ninguna “magia” en el medio; trabaja sin que me moleste en mi actividad diaria y me despreocupo totalmente de que tenía que hacer backup. :-)

Espero que les sirva como a mí. Acá hay mucha más información sobre rsync y una explicación más profunda de las diferentes opciones y alternativas, que por supuesto se pueden utilizar con esto como base.

¡Saludos!

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Reiniciando las conexiones de red automáticamente en Ubuntu

Miércoles, 16 de junio de 2010 Marcelo Sin comentarios

Hace un tiempo que tengo una interfaz Wifi USB Encore; siempre la usé ocasionalmente, en Ubuntu se conectaba y tenía red sin problemas, pero al momento de usarla en forma constante nunca supuse que el módulo rtl8187, responsable de su funcionamiento, iba a tener tantos bugs. :-(

En Ubuntu 10.04 funciona sin instalar nada adicional, pero los principales problemas son que funciona sólo a 11Mbps y que aleatoriamente se desconecta, sin causa aparente, y el Network Manager vuelve a reconectarse. El problema es más serio cuando Network Manager se cansa de revivir a la placa, y el equipo se queda desconectado definitivamente. Y más si no estoy cerca para reconectarla a mano. :-P

Luego de probar unas cuantas recetas (y de esquivar Ndiswrapper porque es un equipo de 64 bits), decidí que voy a dejarlo así, y me hice un scriptcito de cron para reiniciar Network Manager si la interfaz está caída:

#!/bin/bash
 
# /usr/bin/network_respawn
# Network respawn -- rtl8187b dies randomly and despite Network-Manager usually
# reconnects again, sometimes it gives up and dies without connection.
 
# If wlan0 is not connected, it restarts Network-Manager
# This script is meant to be called from a cron job. 
 
IFACE="wlan0"
 
CONNECTED=`grep $IFACE /var/run/network/ifstate`
if [ "$CONNECTED" == "" ]; then  # Disconnected. Respawning...
    /usr/bin/service network-manager restart
fi

Además, hay que crear el archivo en /etc/cron.d/network_respawn para que el sistema llame al script anterior, cada 3 minutos en mi caso:

# Network respawn -- rtl8187b dies randomly and despite Network-Manager usually
# reconnects again, sometimes it gives up and dies without connection.
# If wlan0 is not connected, it restarts Network-Manager
 
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
*/3 * * * * root /usr/bin/network_respawn

Es un script sencillo, y puede ser utilizado para cualquier propósito como el mío. Lo malo es que reinicia todas las conexiones del equipo, ya que reinicia el Network Manager .

¿A alguien se le ocurre cómo hacerlo mejor? :-)

Saludos

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Reemplazando texto con expresiones regulares en Python

Viernes, 2 de abril de 2010 Marcelo Sin comentarios

Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo “%s/cosa/otra/g” del vim nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en PyFpdf, y vi que había algunos archivos .py llenos de llamadas a la función chr().

Claro, PyFpdf es un port más o menos “haragán” (lazy) de Fpdf para PHP, y el autor original evidentemente encontró más sencillo definir algunas fuentes (en binario) haciendo sucesivas llamadas a la función chr(), como  esta:

fpdf_charwidths['times']={chr(0):250, chr(1):250, chr(2):250, chr(3):250,} # Sigue...

Enseguida pensé en mejorarlo, reemplazando esas sucesivas llamadas a chr() por la misma función pero ya evaluada y en forma de byte string; por ejemplo, la idea era convertir lo anterior en:

fpdf_charwidths['times']={'\x00':250,'\x01':250,'\x02':250,'\x03':250,} # Sigue...

De esa manera, los archivos .py se simplificarían (se harían más legibles), no sufrirían modificaciones en su comportamiento y hasta serían más veloces en su interpretación y ejecución.

Primero se me ocurrió primero hacer algo más “a mano”, pero en cuanto se me complicó un poquito enseguida pensé que la mejor herramienta era usar expresiones regulares para el matching del patrón “chr(x)” y, por consiguiente, el módulo re de la librería estándar de Python.

Leyendo esta excelente página y la documentación del módulo en cuestión, armé un script, y me quedó así:

#!/usr/bin/python
# coding:utf-8
 
# This script tries to identify all chr(XX) constant calls in python scripts
# and replace them with '\xXX' strings.
# Author: Marcelo Fernández - License: MIT
 
import sys
import re
 
def chrrepl(match):
    # See http://www.amk.ca/python/howto/regex/regex.html
    # Use the captured group to get the hex string value.
    char_number = match.group(1)
    return repr(chr(int(char_number)))
 
if __name__ == '__main__':
    if len(sys.argv) != 3:
        print 'Usage: python chr_cleaner.py infile.py outfile.py'
        sys.exit(1)
 
    infile = sys.argv[1]
    outfile = sys.argv[2]
    # Open file for reading
    try:
        fin = open(infile, 'r')
        fout = open(outfile, 'w')
    except IOError:
        print 'Error when reading %s or trying to write %s' % (infile, outfile)
        sys.exit(2)
 
    intext = fin.read()
    pattern = 'chr\\((\\d+)\\)' # Group the chr() function parameter to capture it
    p = re.compile(pattern)
    outtext = p.sub(chrrepl, intext)
    fout.write(outtext)
    fout.flush()
 
    fin.close()
    fout.close()

Si bien creo que el snippet es bastante legible, lo interesante es que con el módulo re se puede:

  • Identificar un patrón en un texto: En este caso el patrón sería “chr(\d)” (\d porque busco un número allí).
  • Marcar grupos en ese patrón utilizarlos luego; como sé que voy a utilizar el número en cuestión para convertirlo a su byte string, lo defino dentro de un grupo. El patrón queda entonces “chr((\d))”. También es posible usar named groups, identificables por nombre en vez de por posición, pero eso lo dejo de tarea al lector :-P
  • Reemplazar todo el texto que coincide con ese patrón, y en cada reemplazo, llamar a una función que especifique “lo que hay que poner” allí, devolviendo un string. Esta es la frutilla del postre… :-)
    Si bien puedo usar p.sub() para reemplazar lo que busco por un texto constante, también puedo hacer que en cada ocurrencia del patrón una función cualquiera sea llamada, y  se le pase la instancia de MatchObject para que decidamos qué hacer con lo encontrado y devolver un string. Esto hace la función chrrepl() del snippet. Allí tomo el primer grupo (el grupo 0 es el string completo, el 1 es el primer grupo definido posicionalmente, y así sucesivamente), lo convierto a entero, ejecuto la función chr() y devuelvo su representación en byte string.

En fin, después de experimentar un buen rato, esto funcionó y acá se puede ver el diff del commit correspondiente para que se aprecie un poco mejor…

Saludos

Categories: codear, programación, python, sysadmin, ubuntu-ar Tags:

Curso de Asterisk

Martes, 30 de marzo de 2010 Marcelo Sin comentarios

Este es un quick-post como favor a un amigazo que participa de un emprendimiento involucrado en estos cursos de Asterisk

Bitsense empresa dedicada a la implementación de soluciones telefónicas, dará comienzo a su 3er curso de capacitación de Telefonía IP denominado Biac (Bitsense Initial Asterisk Course), el mismo es el primer curso en la Argentina dictado por dos instructores certificados dCAP (Digium-certified Asterisk Professional) junto con el apoyo de certificados Cisco y Juniper.

Para solicitar mas informacion envienos un mail a capacitacion@bitsense.com.ar y un representante se comunicará con usted o llamenos al telefono al 5353.9858 (int 105).

Saludos

Categories: codear, linux, sysadmin Tags:

Cómo remover el módulo USB 2.0 en Ubuntu 9.10+

Viernes, 19 de marzo de 2010 Marcelo Sin comentarios

Este post va a intentar ser breve y me parece que es bastante técnico, pero puede serle útil a más de uno.

Resulta que yo tengo una Impresora Multifunción Samsung SCX-4200, que tiene unos drivers (cerrados) para Linux [1]. Estos drivers sirven para imprimir y escanear, y si bien hoy en día Ubuntu se las arregla bárbaro para imprimir con los drivers libres de SpliX (¡instalación y configuración automágica!), queda pendiente aún el tema del escaneo.

Por algún motivo al utilizar el scanner (vía USB) la transferencia se caía, y resultó ser que la comunicación Scanner <-> USB 2.0 no funciona, como ya documenté en este mismo blog hace unos años (con la impresión no hay problemas); y no importa la mother, chip o cosa que haya en el medio (lo probé con diferentes equipos). O es esta printer en particular (mucha mala suerte), o es algo del firmware que me tocó en gracia, o… shit happens. :-(

En fin, en versiones anteriores de Ubuntu anteriores a 9.10, para forzar una comunicación USB 1.1 se solucionaba con un “sudo rmmod ehci_hcd”, porque el módulo USB 2.0 (ehci_hcd) era justamente, un módulo que se cargaba dinámicamente. Pero a partir de Ubuntu 9.10 (¿o antes?) este módulo fue incluido en el kernel (estáticamente), con lo cual a priori no tenía manera sencilla de forzar una comunicación USB 1.1 con algún dispositivo (que no sea cambiar el parámetro correspondiente en el BIOS), ya que no es posible descargar un módulo estático del kernel (más info acá).


Me puse a buscar, y encontré una solución. Para simular la “descarga” el módulo es necesario posicionarse en el directorio /sys/bus/pci/drivers/ehci_hcd y pasarle al archivo “unbind” qué hub USB “unbindear” (¿”desrelacionar”?); los hubs USB se pueden ver con un lsusb -v, y los que van a aparecer en el directorio mencionado son los de “Full Speed”, o sea, los de USB 2.0 [2] .

Si tu PC soporta USB 2.0 (y por ende tenés este problema, je), al menos uno hay, que corresponde al Hub de la motherboard. En mi caso hay dos, pero para no andar especulando (y porque quiero que el scanner funcione sin averiguar a cuál de los dos hub está conectado en particular), “unbindeo”/”desrelaciono”/”desenlazo” (?) ambos hubs:

marcelo@marcelo-laptop:~$ sudo -i
[sudo] password for marcelo:
root@marcelo-laptop:~# cd /sys/bus/pci/drivers/ehci_hcd/
root@marcelo-laptop:/sys/bus/pci/drivers/ehci_hcd# ls -l
total 0
lrwxrwxrwx 1 root root    0 2010-03-19 14:12 0000:00:1a.7 -> ../../../../devices/pci0000:00/0000:00:1a.7
lrwxrwxrwx 1 root root    0 2010-03-19 14:12 0000:00:1d.7 -> ../../../../devices/pci0000:00/0000:00:1d.7
--w------- 1 root root 4096 2010-03-19 14:12 bind
lrwxrwxrwx 1 root root    0 2010-03-19 14:12 module -> ../../../../module/ehci_hcd
--w------- 1 root root 4096 2010-03-19 14:12 new_id
--w------- 1 root root 4096 2010-03-19 14:12 remove_id
--w------- 1 root root 4096 2010-03-19 14:12 uevent
--w------- 1 root root 4096 2010-03-19 14:12 unbind
root@marcelo-laptop:/sys/bus/pci/drivers/ehci_hcd# echo -n 0000\:00\:1a.7 > unbind
root@marcelo-laptop:/sys/bus/pci/drivers/ehci_hcd# echo -n 0000\:00\:1d.7 > unbind
root@marcelo-laptop:/sys/bus/pci/drivers/ehci_hcd# ls -l
total 0
--w------- 1 root root 4096 2010-03-19 14:12 bind
lrwxrwxrwx 1 root root    0 2010-03-19 14:12 module -> ../../../../module/ehci_hcd
--w------- 1 root root 4096 2010-03-19 14:12 new_id
--w------- 1 root root 4096 2010-03-19 14:12 remove_id
--w------- 1 root root 4096 2010-03-19 14:12 uevent
--w------- 1 root root 4096 2010-03-19 14:21 unbind
root@marcelo-laptop:/sys/bus/pci/drivers/ehci_hcd#
Listo el pollo. Todos los dispositivos USB que estén conectados por medio de estos Hubs van a ser reconocidos y utilizados por el “fallback”, USB 1.1; en definitiva, este es manejado por el módulo linux uhci_hcd, como podemos ver con el comando dmesg:
[...]
[64720.180444] ehci_hcd 0000:00:1a.7: remove, state 4
[64720.180464] usb usb1: USB disconnect, address 1
[64720.184731] ehci_hcd 0000:00:1a.7: USB bus 1 deregistered
[64720.184838] ehci_hcd 0000:00:1a.7: PCI INT C disabled
[64730.610396] ehci_hcd 0000:00:1d.7: remove, state 1
[64730.610417] usb usb2: USB disconnect, address 1
[64730.610422] usb 2-4: USB disconnect, address 3
[64730.684860] ehci_hcd 0000:00:1d.7: USB bus 2 deregistered
[64730.684980] ehci_hcd 0000:00:1d.7: PCI INT A disabled
[64731.070210] usb 6-2: new full speed USB device using uhci_hcd and address 5
[64731.254158] usb 6-2: configuration #1 chosen from 1 choice
[64731.259814] uvcvideo: Found UVC 1.00 device FO13FF-50 PC-CAM (05c8:0100)
[64731.273207] input: FO13FF-50 PC-CAM as /devices/pci0000:00/0000:00:1d.1/usb6/6-2/6-2:1.0/input/input11
[...]

En mi caso no tenía conectada la impresora, pero sirve el ejemplo de todas maneras ver cómo la webcam es reconocida por uhci_hcd (USB 1.1). Para volver atrás, supongo que hay que hacer lo mismo pero con bind (no lo probé, sólo me parece lógico…), aunque yo reinicio la máquina para no complicarme. :-P

Esto es fácil de meter en un script, y espero que le sirva a alguien (me llevó un buen rato encontrarlo).

Saludos

Marcelo

[1] Por algún motivo la gente de Samsung sacó los drivers Linux de la página de la printer al momento de escribir esto (?). Ya les envié un mail al respecto, espero que contestesten y/o vuelvan a aparecer (habían sido actualizados hace un par de meses, no parecían estar sin mantener…). Si alguien los necesita, me escribe y los pongo en algún lugar accesible.
Actualización: Me contestaron enseguida, a las 3 horas de haberles escrito que no hay drivers Linux en su página. Según ellos, se disculpan y afirman que puede que el equipo de desarrollo esté actualizando los drivers en este mismo momento… hay que ver en unos días si aparecen.
[2] Acá hay una porción de la salida de un “lsusb -v” donde aparece uno de los 2 Root Hub USB 2.0 que tengo en mi equipo; ver que el archivo relacionado que aparece en el directorio /sys/bus/pci/drivers/ehci_hcd corresponde al descriptor “iSerial” del mismo:
[...]
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 Unused
  bDeviceProtocol         0 Full speed (or root) hub
  bMaxPacketSize0        64
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0002 2.0 root hub
  bcdDevice            2.06
  iManufacturer           3 Linux 2.6.31-20-generic ehci_hcd
  iProduct                2 EHCI Host Controller
  iSerial                 1 0000:00:1d.7
  bNumConfigurations      1
[...]
Categories: codear, linux, sysadmin, ubuntu-ar Tags: