spawn - команда не найдена!

15

Я использую Mac OS X 10.9.4, следующий скрипт для копирования файлов с локального компьютера на другой хост

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

при запуске этого скрипта я получаю следующее

./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
источник
В моем случае мне нужны были маркеры EOD вокруг ожидаемого кода. stackoverflow.com/questions/26125036/…
AnneTheAgile

Ответы:

20

Ваш сценарий пытается объединить двух переводчиков. У вас есть и то #!/bin/bashи другое #!/usr/bin/expect. Это не сработает. Вы можете использовать только один из двух. Так как он bashбыл первым, ваш скрипт запускается как скрипт bash.

Однако в вашем скрипте есть expectтакие команды, как spawnи send. Поскольку скрипт читается, bashа не читается expect, это не удается. Вы можете обойти это, написав различные expectсценарии и вызывая их из своего bashсценария или переведя все это в expect.

Однако лучший способ, позволяющий избежать ужасной практики хранения ваших паролей в виде простого текста в простом текстовом файле, - это установить ssh без пароля. Таким образом, вам scpне понадобится пароль и вам не нужно expect:

  1. Сначала создайте открытый ключ ssh на вашем компьютере:

    ssh-keygen -t rsa

    Вас попросят ввести ключевую фразу, которую вам нужно будет ввести при первом запуске любой команды ssh после каждого входа в систему. Это означает, что для нескольких команд ssh или scp вам нужно будет ввести его только один раз. Оставьте парольную фразу пустой для доступа без пароля.

  2. После того как вы сгенерировали свой открытый ключ, скопируйте его на каждый компьютер в вашей сети:

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

    IPlistfile.txtДолжен быть файл , содержащий имя сервера или IP - адрес в каждой строке. Например:

    host1
    host2
    host3

    Поскольку вы делаете это впервые, вам придется вручную вводить пароль для каждого IP-адреса, но как только вы это сделаете, вы сможете скопировать файлы на любой из этих компьютеров с помощью простого:

    scp file user@host1:/path/to/file
  3. Удалите ожидание из вашего скрипта. Теперь, когда у вас есть доступ без пароля, вы можете использовать свой скрипт как:

    #!/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
Тердон
источник
1
Если вы запустите ssh-agent, вам нужно будет ввести пароль только один раз. В противном случае вам нужно будет вводить его каждый раз.
Гленн Джекман
5

Ваш код может быть намного более кратким:

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

Если вы настроили ssh-ключи как предложено, это даже лучше:

    if [[ -n $host ]]; then
        scp "$filePath" uname@$host:/usr/tmp   
        break
    fi
Гленн Джекман
источник