Creación: 07-05-2009
índice de contenidos
1.Introducción
2. Entorno
3.El script
4.Conclusiones
5.Sobre el autor
1. Introducción
Cuando estamos trabajando con cualquier tipo de Unix/Linux, es muy típico usar el comando scp para copiar ficheros entre máquinas de un modo seguro (scp hace la transferencia de archivos usando ssh, por lo que la comunicación está cifrada).
Al utilizar este comando es habitual indicar el usuario de la máquina destino, y el comando scp nos preguntará la clave para acceder con este usuario a esa máquina.
Un ejemplo podría ser el siguiente:
$ scp scrumTnt.ods alex@servidorAutentia://ruta/tntConcept alex@servidorAutentia's password: scrumTnt.ods 100% 70KB 70.0KB/s 00:00
< >< >
Podemos ver como en la segunda línea el comando scp nos está pidiendo la clave. Esta petición la hace a través de manipular el terminal directamente, y no usa la entrada estándar. Esto hace que no sea trivial usar este comando dentro de scripts, ya que no podemos utilizar soluciones del estilo: echo ‘laclave’ | scp origen destino
En este tutorial vamos a ver como podemos hacer un script donde hagamos varios scp de distintos ficheros y directorios y no tengamos que meter la clave cada vez que se ejecuta un scp
.
Ojo, para este problema hay otra solución usando certificados para la autenticación entre las máquinas, que seguramente sea más «elegante». Esta otra solución mediante el uso de certificados para la autenticación no siempre es posible o deseable, por lo que en este tutorial presentaremos una alternativa.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM, 128GB Solid State Drive).
- NVIDIA GeForce 9400M + 9600M GT with 512MB
- Sistema Operativo: Mac OS X Leopard 10.5.6
3. El script
A continuación presentamos un script donde primero pediremos la clave al usuario y luego haremos varios scp donde ya no será necesario introducir la clave. De esta forma podemos automatizar un proceso donde hacemos varias copias entre máquinas, sin perder seguridad, y sin tener que meter la clave cada vez.
Este script se basa en el uso de expect, que es un comando de Unix/Linux para simular en un script las operaciones que pueda hacer un usuario con una aplicación a través del terminal.
#!/usr/bin/expect # Este es un script escrito en TCL, que se ejecutará con Expect !!! # # Este procedimiento ejecuta 'scp' sin pedirle la clave al usuario # proc securecopy {sourceFile user password server targetDirectory } { spawn scp $sourceFile $user@$server:/$targetDirectory expect { -re ".*password:" { send $passwordr exp_continue } -re "Permission denied.*" { exit 1 } timeout { puts "ERROR: Timeout waiting for scp to complete" exit 1 } } } # # Programa principal # set user [exec whoami] # Le pedimos la clave al usuario. La clave no será visible en el terminal send_user "scp $user's password: " stty -echo expect_user -re "(.*)n" {set password $expect_out(1,string)} send_user "n" stty echo securecopy scrumWuija.ods $user $password servidorAutentia /ruta/wuija securecopy scrumTnt.ods $user $password otroServidorAutentia /otraRuta/tntConcept
Vamos a comentar algunas líneas:
- Línea 1: el script es realmente un script de TCL, no de bash. Con esta primera linea conseguimos que se pueda ejecutar este script directamente desde la línea de comandos. Si no pusiéramos esta primera linea, para poder ejecutar el script
tendríamos que hacer: $expect nombreScript - Línea 10: con spawn lo que hacemos es lanzar un comando y que este se asocie a Expect, de forma que luego podamos simular las operaciones del terminal.
- Línea 12: con expect lo que hacemos es quedarnos a la espera de la salida del terminal.
- Línea 13: con -re estamos indicando una expresión regular. Es decir si en el terminal se encuentra una cadena del estilo alex@servidroAutentia’s passwprd: se ejecutarán los comandos que tenemos entre las llaves ( { } ) detrás de la expresión
- Línea 14: con send estamos mandando el texto que viene a continuación al terminal. En este caso estamos mandando al terminal el contenido de la variable $password, seguido de un retorno de carro (r). Así simulamos la entrada de la clave por parte del usuario.
- Línea 15: con exp_continue permitimos que continue la ejecución del comando, en nuestro caso el
scp
. - Líneas de la 35 a la 39: aquí le estamos pidiendo la clave al usuario. La clave no será visible en el terminal y será la que luego se utilice para llamar al procedimiento securecopy. Estas líneas podríamos cambiarlas para sacar la clave de un fichero o de cualquier otro sitio.
- Líneas 41 y 42: aquí es donde hacemos todas las copiar que ejemplo tenemos dos líneas, pero podríamos tener 200.
4. Conclusiones
A menudo hacemos muchas tareas repetitivas para administrar nuestros sistemas. Es fundamental que conozcamos las herramientas que tenemos a nuestro alcance para facilitarnos estar tareas rutinarias y que nos quede más tiempo para lo realmente interesante 😉
Por eso os animo a que utilicéis el principio DRY (Don’t Repeat Yourself, no hagas lo mismo dos veces) no solo en los desarrollos, sino en general en cualquier ámbito.
5. Sobre el autor
Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y ScrumMaster
Socio fundador de Autentia (Formación, Consultoría, Desarrollo de sistemas transaccionales)
mailto:alejandropg@autentia.com
Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»