Archive for the ‘programación’ Category
Command to check a Syslog server status from Nagios
I’ve been using Nagios for a long time and now I have to check a Syslog server. I was looking for a command to check directly a remote Syslog server.
I didn’t find anything that fit my needs so I did one by myself.
To use this command, the Syslog server has to bee listening on the UDP 514 port. It’s only made to check Syslog servers that are available on a network.
The process is simple:
- The script sends a message to the syslog server
- The script start a small UDP server on localhost
- The remote syslog server receives the message and sends it back to the server where the script was executed from
- The script UDP server receives the message and check if it is correct
The Syslog server needs to know how to match the specific message from the check script and send it back to the source script, so it needs a small previous configuration.
The code is hosted in github. There you cand find detailed information about how to run this script and how to configure a Syslog server in the README file.
http://github.com/lbosque/check_syslog
You can also clone directly the repository and see the README with your favourite editor:
git://github.com/lbosque/check_syslog.git
Vacation script for email server
Sometimes I have the need to install some kind of auto-respond feature on an email server. I already used a few times gnarwl.
Honestly, I don’t like it. I spent a lot of time debugging and some parts of it made me crazy. Of course, it’s only my opinion and admit that there are a lot of work put on that project.
Nevertheless I decided to make my own vacation script. The idea was to make something very easy to use and install, and also something easy to hack. I assume certain behaviours so I don’t relay on the configuration file for a lot of things. This way, it results in a very simple configuration file.
I still want to add some features, but only the necessary to have a quality script without turning it in a very complex script.
The code is hosted in github. There you can rea the README file to more information about how it works and how to install it.
http://github.com/lbosque/simple_vacation
You can also clone directly the repository and see the README with your favourite editor:
git clone git://github.com/lbosque/simple_vacation.git
It would be great to have any kind of feedback that helps me to improve the code. Of course you can contact me for any kind of doubt or comment.
Tagline en el tema journalist de wordpress
He hecho un pequeñito cambio en el tema journalist de Lucian Marin, que es el que uso en este blog.
El cambio lo he aplicado a la última versión en la que, en la cabecera del tema, aparece un diálogo de fondo negro con el tagline del blog. Lo que he hecho es simplemente meterle un if para que no muestre el diálogo si el blog no tiene definido el tagline.
Este cambio hay que aplicárselo al header.php de dicho tema. A continuación pongo el diff del fichero:
19c19,21
< <div id="bubble"><p><?php bloginfo('description'); ?></p></div> <!-- erase this line if you want to turn the bubble off -->
---
> <?php if (strlen(get_bloginfo('description')) > 0) { ?>
> <div id="bubble"><p><?php bloginfo('description'); ?></p></div>
> <?php } ?>
Exportar passwords de revelation a texto plano con ruby
Revelation tiene la opción de exportar el fichero de contraseñas a texto plano. El problema es que la organización de las entradas no es demasiado buena, porque las pone en una sola columna sin indentación, por lo que resulta dificil ver el anidación de las contraseñas en caso de que se usen carpetas.
Necesitaba tener las contraseñas en texto plano de forma que pudiese ver a simple vista esta información y fuese más facil de mantener. Esto se puede hacer fácilmente con ruby y xml-simple:
require 'rubygems'
require 'xmlsimple'
PASSWORD_FILE="./passwords.xml"
config = XmlSimple.xml_in(PASSWORD_FILE)
ce = config
indent = ""
INDENT_SPACES = " "
def stepin(ce, indent)
if !ce.nil?
indent = indent + INDENT_SPACES
end
ce['entry'].each { |item|
puts indent + item['name'].to_s
if !item['entry'].nil?
stepin(item, indent)
elsif item['entry'].nil? && item['type'] != 'folder'
if item['description'] && !item['description'].to_s.empty?
puts indent + INDENT_SPACES + "description: " + item['description'].to_s
end
item['field'].each { |field_type|
if !field_type['content'].nil?
puts indent +
INDENT_SPACES +
field_type.values[0].gsub("generic-", "") +
": " +
field_type.values[1]
end
}
end
}
end
stepin(ce, indent)
Para que esto funcione basta tener instalado rubygems y xml-simple.
Una historia de capistrano, crontabs y pipes
Al montar el deploy de una nueva máquina con capistrano he querido afinar un poco la carga de crontabs.
No me gusta poner las tareas de crontab en el /etc/crontab. Creo que es una muy mala práctica. En vez de eso prefiero que cada usuario tenga su propia tabla de crontabs y para ello hago uso del comando crontab.
En muchas ocasiones hace falta definir crontabs para más de un usuario. Para no andar añadiendo una linea en el script de deploy por cada fichero de crontab que se tenga doy por hecho que los nombres de todos los archivos con las tablas de crontab siguen el mismo formato, que es “crontab ..
El código pues para capistrano es:
task :app_deploy, :roles => [:app] do
Dir["./appserver/etc/crontab.*"].each { |crontab|
sudo "sh -c 'cat #{release_path}/#{crontab} | \
crontab -u #{File.extname(File.basename(crontab)).delete('.')} -"
}
end
En este código hay varias cosas que explicar.
Primero se presupone pues que si quiero, por ejemplo, añadir el crontab para el usuario www-data simplemente lo crearé y lo guardaré en appserver/etc/crontab.www-data
En cuanto al código, por un lado el bloque lo que hace es cargar en un array los ficheros con un nombre que coincida con el patrón comentado anteriormente. Hay que tener en cuenta que el código en ruby se ejecuta en la máquina desde la que se lanza el deploy y lo que se le pasa al comando run o sudo es un comando unix que se va a ejecutar en la máquina en la que se quiera hacer el deploy.
Por otro lado está el hecho de que cuando se ejecutan con sudo dos comandos unidos por una tubería, el sudo se va a aplicar únicamente al primero.
Si se hace:
$ sudo echo '* * * * * date > /tmp/date' | crontab -u root -
el sudo se va a aplicar únicamente al comando echo y no al comando crontab por lo que eso no funcionará ya que no tenemos privilegios suficientes.
Por lo tanto para no tener que repetir el comando sudo a los dos lados de la tubería y también para no complicar el comando en capistrano, lo que se puede hacer es englobar toda la sentencia en una subshell de la siguiente forma:
$ sudo sh -c 'echo "* * * * * date > /tmp/date" | crontab -u root -'
ActiveLDAP, validaciones y callbacks
Mientras intentaba implementar el soporte de vacaciones con gnarwl y postfix en una aplicación Rails de gestión de usuarios en LDAP me he encontrado con una situación que no me esperaba.
Primero he de comentar por encima en que consiste gnarwl. Se trata de un script al que se le pasa por la entrada standard un correo en texto plano, con su remitente y destinatario. Después el script busca el destinatario del correo en el árbol LDAP donde está guardada toda su información y comprueba si el atributo vacationActive está activado. Si lo está, le envía al remitente del correo un mail con el texto indicado en el atributo vacationInfo.
Al grano. En el modelo del usuario, gracias a ActiveLDAP, tenía indicado que uno de los objectClass que definen a todo usuario en esta aplicación en concreto es el objectClass Vacation.
ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=Usuarios',
:classes => ['top', 'person', 'qmailUser', 'inetOrgPerson', 'Vacation']
Como no quería sobrecargar el formulario de creación de usuario con un campo/checkbox “Vacaciones”, he metido un callback before_create en el modelo del usuario, de la siguiente forma:
before_create :set_vacation def set_vacation self.vacationActive = false end
De esta forma, la propia definición de objectClass Vacation del usuario se iba a encargar de asignarle ese objectClass y el before_create se iba a encargar de crear el atributo vacationActive y de ponerlo a false.
Cual ha sido mi sorpresa al ir a crear un usuario nuevo y recibir un mensaje típico de validación que no esperaba:
1 error prohibited this user from being saved
There were problems with the following fields:
* vacationActive is required attribute by objectClass 'Vacation'
Al principio me ha despistado un poco, pero al final he visto cual era el problema.
Obviamente sabía que cuando una entrada en LDAP tiene el objectClass Vacation, se exige que como mínimo tenga también el atributo vacationActive definido. Lo que no sabía era que ActiveLDAP genera las validaciones en tiempo real consultando primero los objectClass de esa entrada y generandose su lista con los atributos de los que dependen esos objectClass.
Por lo tanto el before_create añadido anteriormente no sirve, ya que es necesario crear ese atributo antes de la validación. Lo correcto sería:
before_validation_on_create :set_vacation
Además de este detalle se había juntado otro problema que hacía que me costase un poco con la solución. Este problema es que ActiveLDAP no acepta una definición de un booleano de la forma clásica:
vacationActive = false
ActiveLDAP acepta valores booleanos de la siguiente en forma de cadenas de la forma “TRUE” o “FALSE”.
Mirando un poco las tripas de ActiveLDAP he visto que tiene una función para normalizar los valores en el caso de que se le pase true o false. No obstante parece que no aplica esa función a nivel interno, por lo que resulta totalmente inutil en caso de desconocimiento del programador, como en este caso me ha pasado a mi.
Por lo tanto, el callback correcto en esta situación no sería el que he indicado anteriormente, sino que sería este:
before_validation_on_create :set_vacation def set_vacation self.vacationActive = "FALSE" end
Caracteres inválidos en el parametro page de will_paginate
Hoy me han llegado al correo varias notificaciones de excepciones del site del Centenario do Inter. Estos errores se han generado por no indicar el parámetro page del will_paginate, de la siguiente forma:
http://localhost:3000/fotos?page=
El código de will_paginate no contempla eso, por lo que tenía dos opciones. Una poner un filtro en mis controladores para asegurarme de que hubiese algún número de pagina. Esa opción es muy poco DRY, así que he hecho el siguiente cambio en el collection.rb del plugin de will_paginate:
Index: vendor/plugins/will_paginate/lib/will_paginate/collection.rb
===================================================================
--- vendor/plugins/will_paginate/lib/will_paginate/collection.rb (revisión: 65)
+++ vendor/plugins/will_paginate/lib/will_paginate/collection.rb (copia de trabajo)
@@ -16,7 +16,7 @@
# populating the collection using the +replace+ method.
#
def initialize(page, per_page, total = nil)
- @current_page = page.to_i
+ @current_page = !page.blank? && page != 0 && page.to_i != 0 ? page.to_i : 1
@per_page = per_page.to_i
self.total_entries = total if total
La verdad es que no se, ni si eso está contemplado en versiones posteriores a la que estoy usando, ni si es una buena solución, pero a mi me ha servido para resolver el problema rápidamente y sin tirar apenas código.
Con ese cambio, además de asegurarme de que la aplicación no de 500 al no poner ningún número en el parámetro page, también me aseguro de que no se rompa por poner un parámetro que no sea un número, como por ejemplo:
http://localhost:3000/fotos?page=foobar
Pos eso.
Flatee
El otro día vi en un twitter que alguien hablaba de Flatee. Así que como curioso que soy abrí el enlace y me encontré de narices con una web que ya de por sí llama la atención por su diseño realmente agradable.
Leyendo un poco más he visto que se trata de un proyecto, que todavía está en fase de desarrollo, que pretende llevar la tarea de buscar piso compartido a un nivel superior (cosa que alguien debería de haber hecho hace muchísimo tiempo).
Parece un proyecto tan ambicioso como necesario, por lo que estaré al tanto del avance del mismo. Desde luego, si el resultado final resulta en una agradable experiencia de buscar piso compartido (que hoy en día me parece algo realmente doloroso), se podrá considerar un éxito rotundo.
En cuanto a los desarrolladores, estoy gratamente sorprendido de ver que uno de ellos se trata de Daniel Latorre, antiguo compañero de Net2U, con el que, a pesar de tenerlo de contacto en la mayoría de aplicaciones 2.0 que uso hoy en día, por desgracia no matengo contacto.
Así que deseo a Daniel y a Jesús Navarrete que realicen un gran trabajo, que lo tienen todo de su parte.
Trabajar en The Cocktail
En The Cocktail estamos buscando nuevas mentes brillantes (con que sean un poco perturbadas es suficiente). Concretamente andamos detrás de maquetadores y programadores Ruby on Rails. No hace falta que seas un gurú, pero sí que le eches ganas.
No me voy a extender mucho. Solo puedo decir que hace poco más de 4 meses que estoy aquí y no me he arrepentido ni un poquico.
Hacemos un trabajo de calidad, para clientes de calidad. Trabajamos con las últimas tecnologías del entorno web y primamos la innovación y las ganas. Tenemos un gran equipo, agradable y también tenemos galletas de chocolate y de limón.
Así que si te mola el plan o sabes de alguien a quien le vaya a molar, ponte en contacto con nosotros.
PD.: Mejor si no tienes alergia a los perros.
Proyectos
Aprovecho el post para hablar rápidamente del proyecto en el que estoy trabajando. Un site para el Internacional de Porto Alegre. Llevaba un tiempo trabajando en él, y este viernes 4 por la noche fue presentado durante un evento que realizó el club en un restaurante que tienen en Porto Alegre. El motivo de este evento fue la entrada en el año 99 del club. Para los seguidores del Inter este es motivo de celebración y posiblemente celebraciones va a ser lo que haya durante este año, hasta cumplir el Centenario.
El trabajo continua ya que hay que mantener la infraestructura en forma y siempre hay pequeñas mejoras o arreglos de pequeños bugs que corregir.
Aprovecho para agradecer a los que han intervenido directa o indirectamente en este proyecto, como la gente de la e21 con los que colaboro, a Fabiana (que siempre confía en mi) y Eurico, con los que es un placer trabajar. A Ju que se ha pegado alguna que otra hora aburrida mientras curraba. Y también agradezco a algún compañero de The Cocktail que me ha dado consejos tanto de diseño como de programación.
Y aunque parece demasiado homenaje para un proyecto na más, aprovecho para dedicárselo a mi sobrina Alice, que es del Inter (por herencia paterna) y que se pegaba todo el rato haciéndome monerías en la cara mientras trabajaba en Porto Alegre. Ya puestos, y para que no haya envidia, se lo dedico a mi sobrina Mariana, aunque solo sea para fastidiar, ya que es del Gremio.