spawn – command not found!

I am using Mac OS X 10.9.4, following is my script to copy files from local machine to different 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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="43362d222e26032b2c303772">[email protected]</a>:/usr/tmp   
  expect "password"   
  send "MyPasswordr"
  interact
elif [ $choice -eq "2" ]
then
  spawn scp filePath <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="473229262a22072f28343375">[email protected]</a>:/usr/tmp   
  expect "password"   
  send "MyPasswordr"
  interact
elif [ $choice -eq "3" ]
then
  spawn scp filePath <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1d68737c70785d75726e692e">[email protected]</a>:/usr/tmp   
  expect "password"   
  send "MyPasswordr"
  interact
else
  echo "Wrong input"
fi

when running this script i am getting following

./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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Your script is attempting to combine two interpreters. You have both #!/bin/bash and #!/usr/bin/expect. That won’t work. You can only use one of the two. Since bash was first, your script is being run as a bash script.

However, within your script, you have expect commands such as spawn and send. Since the script is being read by bash and not by expect, this fails. You could get around this by writing different expect scripts and calling them from your bash script or by translating the whole thing to expect.

The best way though, and one that avoids the horrible practice of having your passwords in plain text in a simple text file, is to set up passwordless ssh instead. That way, the scp won’t need a password and you have no need for expect:

  1. First, create a public ssh key on your machine:
    ssh-keygen -t rsa

    You will be asked for a passphrase which you will be asked to enter the first time you run any ssh command after each login. This means that for multiple ssh or scp commands, you will only have to enter it once. Leave the passphrase empty for completely passwordless access.

  2. Once you have generated your public key, copy it over to each computer in your network :
    while read ip; do 
     ssh-copy-id -i ~/.ssh/id_rsa.pub <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d6a3a5b3a4e796">[email protected]</a>$ip 
    done < IPlistfile.txt

    The IPlistfile.txt should be a file containing a server’s name or IP on each line. For example:

    host1
    host2
    host3

    Since this is the first time you do this, you will have to manually enter the password for each IP but once you’ve done that, you will be able to copy files to any of these machines with a simple:

    scp file <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="314442544371595e424500">[email protected]</a>:/path/to/file
  3. Remove the expect from your script. Now that you have passwordless access, you can use your script as:
    #!/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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="394c5758545c7951564a4d08">[email protected]</a>:/usr/tmp   
    elif [ $choice -eq "2" ]
    then
      scp filePath <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f2879c939f97b29a9d8186c0">[email protected]</a>:/usr/tmp   
    elif [ $choice -eq "3" ]
    then
      scp filePath <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="05706b646860456d6a767136">[email protected]</a>:/usr/tmp   
    else
      echo "Wrong input"
    fi

Method 2

Your code can be a lot more concise:

#!/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" <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="067368676b6346">[email protected]</a>$host:/usr/tmp   
            expect "password"   
            send "MyPasswordr"
            expect eof
END
        break
    fi
done

If you set up ssh keys as suggested, it’s even better:

    if [[ -n $host ]]; then
        scp "$filePath" <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="21544f404c4461">[email protected]</a>$host:/usr/tmp   
        break
    fi

Method 3

spawn is an expect command. It will not work if your interpreter is /bin/bash.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x