SSH + Sudo + Expect en script Bash: ejecutar comando con sudo en máquina remota

SSH + Sudo + Expect en script Bash: ejecutar comando con sudo en máquina remota

Estoy intentando automatizar la implementación de algunos paquetes .deb con un script. Quiero ejecutar sudo dpkg -i $myDeb.deben una lista de máquinas remotas a las que puedo acceder con ssh.

Intenté automatizar el comando con 'esperar' dentro de un script bash, pero obviamente estoy haciendo algo mal porque recibo varios errores diferentes (dependiendo de dónde pongo las comillas, básicamente)

Esta es la función que tengo (se llamará con algo como: _remoteInstallation "myPackage115.deb" "192.168.1.55". Sé que en la máquina remota, el .deb estará ubicado en $HOME/Documentos/:

function _remoteInstallation(){
    local retval=1
    local debToInstall=$(basename "$1")
    local remoteMachine="$2"
    spawned=$(expect -d -c "
          set timeout 1800
          spawn "/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall"'
          expect {
                \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                \"password\" { send \"myPassword\r\";  exp_continue }
                \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                default { exit 1 }
          }
    " )
    retval=$?
    return $retval
}

Con las comillas en el área generada de esa manera, obtengo

expect: invalid option -- 't'

Si lo cambio a:

 spawn /usr/bin/ssh -t borrajax@$remoteMachine '/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall'

Parece que está intentando ejecutar el comando sudo dpkg localmente (primero ssh(s) a '$remoteMachine' y luego ejecuta sudo dpkg localmente, como dos comandos separados)

Con este:

spawn '/usr/bin/ssh -t borrajax@$remoteMachine \'/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\''

Entiendo eso couldn't execute "'/usr/bin/ssh": no such file or directory(lo cual no es cierto)

... y en este punto, me quedé sin ideas...:-)

Cualquier pista será apreciada. Gracias.

Respuesta1

Creo que te perdiste un nivel de citas que se escaparon. En este alto nivel de escape, lo mejor es simplemente hacer un pequeño guión para cada etapa donde de otro modo se necesitarían citas.

De lo contrario, puedes probar esta versión modificada (pero ten en cuenta que no recomiendo este estilo de codificación).

function _remoteInstallation(){
    local retval=1
    local debToInstall=$(basename "$1")
    local remoteMachine="$2"
    spawned=$(expect -d -c "
          set timeout 1800
          spawn \"/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\"
          expect {
                \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                \"password\" { send \"myPassword\r\";  exp_continue }
                \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                default { exit 1 }
          }
    " )
    retval=$?
    return $retval
}

Respuesta2

¿Por qué la gente siempre usa estas expectcosas feas ssh? Use claves ssh y listo (lea sobre criptografía de clave pública como teoría, solo úsela ssh-copy-id remotemachinede una vez por todas para practicar). Entonces el uso es tan simple como

ssh remote-machine "remote-shell-command" > local-redirection-of-command-output

Tan pronto como no tenga que hacer malabares entre 3 niveles de citas, naturalmente escribirá los comandos correctos.

información relacionada