sábado, julio 03, 2010

rsync - Guía Rápida

Linux tiene muchas herramientas para copiar y respaldar información. rsync es la favorita para muchos administradores.

rsync utiliza un algoritmo que permite transmitir eficientemente una estructura (como un archivo) a través de un canal de comunicación cuando el receptor ya tiene una versión diferente de la misma estructura. (wikipedia)

Copiar localmente

En su forma más simple lo podemos utilizar para copiar directorios enteros de forma local.
$ rsync -av /home/user/Docs /media/usb/backup/
-av lo ejecuta en modo verbose y archivo, práctica común para copia recursiva, conservar permisos y symlinks.

Copiar remotamente

Tanto el origen como el destino pueden ser otra computadora en la red.
$ rsync -avz /home/user/Docs user@online.backups.com:/backups/
agregamos -z para comprimir los datos sobre la red.

rsync puede tambier borrar archivos que ya no se encuentran en el origen pero si en el destino causa de alguna copia anterior. Es decir, que pasa si ya borramos algunos archivos de nuestro directorio de trabajo y queremos que también sean borrados de nuestro respaldo.
$ rsync -avz --del /home/user/Docs user@online.backups.com:/backups/
--del indica a rsync que borre los archivos que ya no están en el origen.

Directorio o archivos

Importante el último slash '/'. en:
$ rsync -avz --del /home/user/Docs user@online.backups.com:/backups/
estoy copiando el directorio 'Docs' dentro del directorio 'backups' pero si
$ rsync -avz --del /home/user/Docs/ user@online.backups.com:/backups/
estaré copiando los archivos dentro del directorio 'Docs' al directorio 'backups'

Copia incremental

$ rsync --backup --backup-dir=`date +%Y.%m.%d` -av /home/user/Docs/ /media/usb/backup/Docs/
--backup crea un respaldo --backup-dir crea el respaldo dentro de la jerarquía del directorio de destino. También se puede usar --suffix=SUFFIX para agregar un sufijo.

Apenas rascando la superficie de esta poderosa utilería. Para más información manpage.

lunes, marzo 22, 2010

MVC en Python

Últimamente he utilizado herramientas como SQLAlchemy y Turbogears en Python. La verdad me ha gustado mucho la flexibilidad y facilidad con la que puedo escribir scripts para procesar información con SQLAlchemy y me ha gustado mucho el modelo MVC de Turbogears 2, parecido al de Spring en Java, por lo que voy a comenzar a implementar más cosas en python.
Comenzaré con un blog/cms en Turbogears, yo sé que existen muchísimas opciones ya desarrolladas que seguramente son mejores a cualquiera que yo pueda hacer, sin embargo, me sirve para familiarizarme en ambiente de trabajo con TG2.

Instalando Turbogears.
La mejor opción es con Virtualenv, que crea un "ambiente virtual" de python para cargar dependencias, librerías y versiones, etc. Sin embargo en producción a mi me ha funcionado instalarlo junto con el resto de python del servidor. Las instrucciones para instalarlo son sencillas y están aquí.
Creando un proyecto
Es muy simple iniciar un proyecto en Turbogears.

$ paster quickstart
Enter project name: Altadefinicion
Enter package name [altadefinicion]:
Do you need authentication and authorization in this project? [yes]
Selected and implied templates:
tg.devtools#turbogears2 TurboGears 2.0 Standard Quickstart Template

Variables:
auth: sqlalchemy
egg: Altadefinicion
geo: None
package: altadefinicion
project: Altadefinicion
sqlalchemy: True
sqlobject: False
tgversion: 2.0.3
Creating template turbogears2
Creating directory ./Altadefinicion
...
...
...
reading manifest template 'MANIFEST.in'
writing manifest file 'Altadefinicion.egg-info/SOURCES.txt'

Si no recibimos ningún mensaje de error, podemos iniciar la aplicación con:

$ paster serve --reload development.ini

Y apuntando nuestro explorador a http://localhost:8080 podremos ver una página de bienvenida.



Entrando al directorio del proyecto podemos observar una simple estructura:

$ tree -d
.
|-- Altadefinicion.egg-info
|-- altadefinicion
| |-- config
| |-- controllers
| |-- i18n
| | `-- ru
| | `-- LC_MESSAGES
| |-- lib
| |-- model
| |-- public
| | |-- css
| | `-- images
| |-- templates
| `-- tests
| |-- functional
| `-- models
|-- data
| `-- sessions
`-- ez_setup

25 directories

Por default TG2 usa SQLite como motor de base de datos y almacena todo en un archivo llamado devdata.db para crear la base de datos por default con datos de prueba hay que correr otro comando de paster:

$ paster setup-app development.ini

Con esto ya tenemos lista la cimentación para construir una aplicación con python, usando Turbogears 2 y SQLalchemy

martes, febrero 02, 2010

Neither BindingResult nor plain target object for bean name "command"...

Este error me sale frecuentemente y sobre todo después de muchas correcciones o adecuaciones a nuevos controllers en spring-mvc.

Siempre pierdo mucho tiempo tratando de encontrar el error, por que cuando veo el código tanto del jsp como del controllores todo parace perfecto, sin embargo el error persiste.

Cuando encuentro la solución siempre recuerdo que ya lo había hecho así antes y ahora quiero ponerlo aquí para que no se me olvide.

El error sale cuando inserto un nuevo objeto para persistir, no cuando edito uno ya existente y la respuesta está en la salida con succesView
return new ModelAndView(success);

Si successView no está definido me arroja el error, cuando se modifica el objeto successView es editado para mostrar nuevamente la forma de edición, sin embargo cuando el objeto es nuevo, pasa el parámetro de successView que está definido en el dispatcher. Entonces, si no hay successView definido en el dispatcher, me encuentro con ese error.

    <bean id="catalogoEstrategiasFormController" class="com.deuxbits.ssaspps.webapp.controller.CatalogoEstrategiasFormController">
        <!-- property name="validator" ref="beanValidator"/ -->
        <property name="successView" value="redirect:catalogoestrategias.html"/>
        <property name="catalogoEstrategiasManager" ref="catalogoEstrategiasManager"/>
        <property name="userManager" ref="userManager" />
        <property name="catalogoProgramasManager" ref="catalogoProgramasManager" />    
    </bean>