spawn - comando no encontrado!

15

Estoy usando Mac OS X 10.9.4, el siguiente es mi script para copiar archivos de la máquina local a un host diferente

#!/bin/bash
#!/usr/bin/expect

echo "I will fail if you give junk values!!"
echo " "
echo "Enter file name: "
read filePath
echo " "
echo "Where you want to copy?"
echo "Enter"
echo "1. if Host1"
echo "2. if Host2"
echo "3. if Host3"
read choice
echo " "
if [ $choice -eq "1" ]
then
  spawn scp filePath uname@host1:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
elif [ $choice -eq "2" ]
then
  spawn scp filePath uname@host2:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
elif [ $choice -eq "3" ]
then
  spawn scp filePath uname@host3:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
else
  echo "Wrong input"
fi

cuando ejecuto este script estoy recibiendo

./rcopy.sh: line 21: spawn: command not found
couldn't read file "password": no such file or directory
./rcopy.sh: line 23: send: command not found
./rcopy.sh: line 24: interact: command not found
dev2d
fuente
En mi caso, necesitaba marcadores EOD alrededor del código de espera. stackoverflow.com/questions/26125036/…
AnneTheAgile

Respuestas:

20

Su guión está intentando combinar dos intérpretes. Tienes ambos #!/bin/bashy #!/usr/bin/expect. Eso no funcionará. Solo puedes usar uno de los dos. Desde el bashprincipio, su script se ejecuta como un script bash.

Sin embargo, dentro de su script, tiene expectcomandos como spawny send. Dado que el script está siendo leído por bashy no por expect, esto falla. Puede solucionar esto escribiendo diferentes expectguiones y llamándolos desde su bashguión o traduciéndolo todo expect.

Sin embargo, la mejor manera, y una que evita la práctica horrible de tener sus contraseñas en texto plano en un archivo de texto simple, es configurar ssh sin contraseña. De esa manera, scpno necesitará una contraseña y no necesita expect:

  1. Primero, cree una clave ssh pública en su máquina:

    ssh-keygen -t rsa

    Se le pedirá una frase de contraseña que se le pedirá que ingrese la primera vez que ejecute cualquier comando ssh después de cada inicio de sesión. Esto significa que para múltiples comandos ssh o scp, solo tendrá que ingresarlo una vez. Deje la frase de contraseña vacía para un acceso completamente sin contraseña.

  2. Una vez que haya generado su clave pública, cópiela en cada computadora de su red:

    while read ip; do 
     ssh-copy-id -i ~/.ssh/id_rsa.pub user1@$ip 
    done < IPlistfile.txt

    El IPlistfile.txtdebe ser un archivo que contiene el nombre de un servidor o IP en cada línea. Por ejemplo:

    host1
    host2
    host3

    Como esta es la primera vez que hace esto, tendrá que ingresar manualmente la contraseña para cada IP, pero una vez que lo haya hecho, podrá copiar archivos a cualquiera de estas máquinas con un simple:

    scp file user@host1:/path/to/file
  3. Elimina la expectativa de tu script. Ahora que tiene acceso sin contraseña, puede usar su script como:

    #!/bin/bash
    echo "I will fail if you give junk values!!"
    echo " "
    echo "Enter file name: "
    read filePath
    echo " "
    echo "Where you want to copy?"
    echo "Enter"
    echo "1. if Host1"
    echo "2. if Host2"
    echo "3. if Host3"
    read choice
    echo " "
    if [ $choice -eq "1" ]
    then
      scp filePath uname@host1:/usr/tmp   
    elif [ $choice -eq "2" ]
    then
      scp filePath uname@host2:/usr/tmp   
    elif [ $choice -eq "3" ]
    then
      scp filePath uname@host3:/usr/tmp   
    else
      echo "Wrong input"
    fi
terdon
fuente
1
Si inicia un agente ssh, solo tendrá que ingresar la frase de contraseña una vez. De lo contrario, deberá ingresarlo cada vez.
Glenn Jackman
5

Su código puede ser mucho más conciso:

#!/bin/bash

read -p "Enter file name: " filePath
if ! [[ -r $filePath ]]; then
    echo "cannot read $filePath"
    exit 1
fi

PS3="Where you want to copy? "
select host in host1 host2 host3; do
    if [[ -n $host ]]; then
        expect <<END
            spawn scp "$filePath" uname@$host:/usr/tmp   
            expect "password"   
            send "MyPassword\r"
            expect eof
END
        break
    fi
done

Si configura las claves ssh como se sugiere, es aún mejor:

    if [[ -n $host ]]; then
        scp "$filePath" uname@$host:/usr/tmp   
        break
    fi
Glenn Jackman
fuente