web-dev-qa-db-ja.com

spawn-コマンドが見つかりません!

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
15
dev2d

スクリプトが2つのインタープリターを結合しようとしています。両方あります#!/bin/bashおよび#!/usr/bin/expect。それはうまくいきません。 2つのうち1つしか使用できません。 bashが最初なので、スクリプトはbashスクリプトとして実行されています。

ただし、スクリプト内には、expectspawnなどの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
    
20
terdon

あなたのコードはもっと簡潔にすることができます:

#!/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
5
glenn jackman

spawnexpectコマンドです 。インタープリターが/bin/bashの場合は機能しません。

3
l0b0