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

У моєму випадку мені знадобилися маркери EOD навколо коду очікування. stackoverflow.com/questions/26125036 / ...
AnneTheAgile

Відповіді:


20

Ваш сценарій намагається поєднати двох перекладачів. У вас є і те, #!/bin/bashі #!/usr/bin/expect. Це не вийде. Можна використовувати лише одне з двох. З 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-агент, вам доведеться вводити парольну фразу лише один раз. Інакше вам потрібно буде вводити його щоразу.
glenn jackman

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.