spawn - comando não encontrado!

15

Estou usando o Mac OS X 10.9.4. A seguir, meu script para copiar arquivos da máquina local para outro 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

ao executar esse script, estou recebendo os seguintes

./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
fonte
No meu caso, eu precisava de marcadores EOD em torno do código esperado. stackoverflow.com/questions/26125036/…
AnneTheAgile 9/17

Respostas:

20

Seu script está tentando combinar dois intérpretes. Você tem ambos #!/bin/bashe #!/usr/bin/expect. Isso não vai funcionar. Você pode usar apenas um dos dois. Desde o bashprimeiro, seu script está sendo executado como um script bash.

No entanto, dentro do seu script, você possui expectcomandos como spawne send. Como o script está sendo lido bashe não por expect, isso falha. Você pode contornar isso escrevendo expectscripts diferentes e chamando-os do seu bashscript ou traduzindo tudo para expect.

A melhor maneira, porém, e que evita a prática horrível de ter suas senhas em texto sem formatação em um arquivo de texto simples, é configurar o ssh sem senha. Dessa forma, scpvocê não precisará de uma senha e não precisará expect:

  1. Primeiro, crie uma chave ssh pública em sua máquina:

    ssh-keygen -t rsa

    Você será solicitado a fornecer uma senha que será solicitada a digitar na primeira vez em que executar qualquer comando ssh após cada login. Isso significa que, para vários comandos ssh ou scp, você precisará inseri-lo apenas uma vez. Deixe a senha vazia para acesso completamente sem senha.

  2. Depois de gerar sua chave pública, copie-a para cada computador em sua rede:

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

    O IPlistfile.txtdeve ser um arquivo contendo nome ou IP de um servidor em cada linha. Por exemplo:

    host1
    host2
    host3

    Como esta é a primeira vez que você faz isso, será necessário inserir manualmente a senha para cada IP, mas depois disso, você poderá copiar arquivos para qualquer uma dessas máquinas com um simples:

    scp file user@host1:/path/to/file
  3. Remova a expectativa do seu script. Agora que você tem acesso sem senha, pode usar seu 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
fonte
1
Se você iniciar um ssh-agent, precisará digitar a senha uma vez. Caso contrário, você precisará inseri-lo sempre.
Glenn Jackman
5

Seu código pode ser muito mais 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

Se você configurar as teclas ssh conforme sugerido, é ainda melhor:

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