sábado, marzo 19, 2011

Ejecutar comandos remotamente (y guardar el tiempo)

En este post les enseñaré como ejecutar un programa en un servidor remoto el de fismat o en alguna compu que sepas que siempre estará prendida, y tomarle el tiempo de ejecución. Todo empezó con la siguiente situación:

Tarea: Escribir un programa que durará horas ejecutándose, tomar el tiempo de ejecución. Guardar la salida del programa y el tiempo que tardó en ejecutarse.

Inconveniente: Están tontos si creen que dejaré mi compu prendida toda la noche! Ni que estuviera jugando Plantas vs Zombies o bajando cosas.

Pues comencemos. Secure Shell (SSH) es de los más grandes inventos de la humanidad (junto con el apt-get) [cita requerida], ¿a quién no le fascina estar haciendo cosas en su compu, desde otra compu que posiblemente esté a cientos de kilómetros? 

Pero la terminal es engañosa, y muchas veces olvidas que estás conectado por SSH y haces 'sudo halt' en la compu equivocada. Esto es frustrante, en espacial cuando sólo vas a ejecutar unos pocos comanditos. Para evitar este problema, puedes hacer:

$ ssh user@host 'programa'

Esto ejecuta 'programa' en la compu remota, sin abandonar la compu donde estás. Es muy útil cuando 'programa' durará mucho tiempo corriendo. Puedes hacer Control+C con la seguridad que en la compu remota seguirá ejecutándose. Si no me crees

$ ssh user@host 'ps -u user'

Y verás tu proceso corriendo. Bien, ya logramos dejar ejecutando el programa en otra compu. Ahora, ¿Cómo medir el tiempo?

La respuesta es el comando 'time'. La sintaxis es simple

$ time programa
<-- salida del programa -->
real XX m YY s
usr  XX m YY s
sys  XX m YY s

Para guardar la salida de 'time', uno pensaría que basta terminar el programa con '>>salida' . Pero desde bash2.- en adelante, time se comporta chistoso y esto ya no es posible. La manera de remediarlo es

$ { time programa;} 2>>salida

(el primer espacio es importante). Si queremos que el 'programa' guarde salida:

$ { time programa >> salida1;} 2>>salida

Las salidas pueden ser el mismo archivo. Con estos ingredientes, ya podemos hacer

$ ssh user@host '{ time programa>>output;} 2>>time'

Listo ! Hemos dejado al servidor de fismat remoto trabajando.