spawn - commande introuvable!

15

J'utilise Mac OS X 10.9.4, voici mon script pour copier des fichiers de la machine locale vers un hôte différent

#!/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

lors de l'exécution de ce script, je suis en train de suivre

./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
la source
Dans mon cas, j'avais besoin de marqueurs EOD autour du code attendu. stackoverflow.com/questions/26125036/…
AnneTheAgile

Réponses:

20

Votre script tente de combiner deux interprètes. Vous avez les deux #!/bin/bashet #!/usr/bin/expect. Ça ne marchera pas. Vous ne pouvez utiliser que l'un des deux. Depuis la bashpremière fois, votre script est exécuté en tant que script bash.

Cependant, dans votre script, vous avez des expectcommandes telles que spawnet send. Étant donné que le script est lu par bashet non par expect, cela échoue. Vous pouvez contourner cela en écrivant différents expectscripts et en les appelant à partir de votre bashscript ou en traduisant le tout en expect.

La meilleure façon cependant, et qui évite l'horrible pratique d'avoir vos mots de passe en texte brut dans un simple fichier texte, est de configurer à la place ssh sans mot de passe. De cette façon, vous scpn'aurez pas besoin d'un mot de passe et vous n'avez pas besoin de expect:

  1. Créez d'abord une clé ssh publique sur votre machine:

    ssh-keygen -t rsa

    Il vous sera demandé une phrase secrète que vous devrez saisir la première fois que vous exécuterez une commande ssh après chaque connexion. Cela signifie que pour plusieurs commandes ssh ou scp, vous ne devrez les saisir qu'une seule fois. Laissez la phrase secrète vide pour un accès totalement sans mot de passe.

  2. Une fois que vous avez généré votre clé publique, copiez-la sur chaque ordinateur de votre réseau:

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

    Le IPlistfile.txtdoit être un fichier contenant le nom ou l'adresse IP d'un serveur sur chaque ligne. Par exemple:

    host1
    host2
    host3

    Puisque c'est la première fois que vous faites cela, vous devrez entrer manuellement le mot de passe pour chaque IP mais une fois que vous aurez fait cela, vous pourrez copier des fichiers sur n'importe laquelle de ces machines avec un simple:

    scp file user@host1:/path/to/file
  3. Supprimez l'attente de votre script. Maintenant que vous disposez d'un accès sans mot de passe, vous pouvez utiliser votre script comme:

    #!/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
la source
1
Si vous lancez un agent ssh, vous n'aurez à saisir le mot de passe qu'une seule fois. Sinon, vous devrez le saisir à chaque fois.
glenn jackman
5

Votre code peut être beaucoup plus concis:

#!/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 vous configurez les clés ssh comme suggéré, c'est encore mieux:

    if [[ -n $host ]]; then
        scp "$filePath" uname@$host:/usr/tmp   
        break
    fi
glenn jackman
la source