spawn - befehl nicht gefunden!

15

Ich verwende Mac OS X 10.9.4. Das folgende Skript kopiert Dateien vom lokalen Computer auf einen anderen Host

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

Beim Ausführen dieses Skripts bekomme ich folgende

./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
quelle
In meinem Fall brauchte ich EOD-Marker um den Expect-Code. stackoverflow.com/questions/26125036/…
AnneTheAgile

Antworten:

20

Ihr Skript versucht, zwei Interpreter zu kombinieren. Sie haben beide #!/bin/bashund #!/usr/bin/expect. Das geht nicht Sie können nur einen der beiden verwenden. Seit dem bashersten Mal wird Ihr Skript als Bash-Skript ausgeführt.

In Ihrem Skript haben Sie jedoch expectBefehle wie spawnund send. Da das Skript von bashund nicht von gelesen wird expect, schlägt dies fehl. Sie können dies expectumgehen, indem Sie verschiedene Skripte schreiben und sie aus Ihrem bashSkript aufrufen oder indem Sie das Ganze in übersetzen expect.

Der beste Weg, und einer, der die schreckliche Praxis vermeidet, Ihre Passwörter im Klartext in einer einfachen Textdatei zu haben, ist, stattdessen passwortloses ssh einzurichten. Auf diese Weise scpwird kein Passwort benötigt und Sie müssen nicht expect:

  1. Erstellen Sie zunächst einen öffentlichen SSH-Schlüssel auf Ihrem Computer:

    ssh-keygen -t rsa

    Sie werden nach einer Passphrase gefragt, die Sie bei der ersten Ausführung eines ssh-Befehls nach jeder Anmeldung eingeben müssen. Dies bedeutet, dass Sie mehrere ssh- oder scp-Befehle nur einmal eingeben müssen. Lassen Sie die Passphrase leer, um einen vollständig passwortlosen Zugriff zu erhalten.

  2. Nachdem Sie Ihren öffentlichen Schlüssel generiert haben, kopieren Sie ihn auf jeden Computer in Ihrem Netzwerk:

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

    Das IPlistfile.txtsollte eine Datei sein, die den Namen oder die IP eines Servers in jeder Zeile enthält. Beispielsweise:

    host1
    host2
    host3

    Da dies das erste Mal ist, müssen Sie das Passwort für jede IP manuell eingeben. Sobald Sie dies getan haben, können Sie die Dateien mit einem einfachen Befehl auf jeden dieser Computer kopieren:

    scp file user@host1:/path/to/file
  3. Entfernen Sie die Erwartung aus Ihrem Skript. Jetzt, da Sie kennwortlosen Zugriff haben, können Sie Ihr Skript wie folgt verwenden:

    #!/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
quelle
1
Wenn Sie einen ssh-agent starten, müssen Sie die Passphrase nur einmal eingeben. Andernfalls müssen Sie es jedes Mal eingeben.
Glenn Jackman
5

Ihr Code kann viel prägnanter sein:

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

Wenn Sie ssh-Schlüssel wie vorgeschlagen einrichten, ist es noch besser:

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