0

I have a script below that works except for the expect portion:

#!/bin/bash
#
invdir=/home/john/inventory

for file in $invdir/$1
do
  if [ -z $1 ] || [ -z $2 ]
  then
     echo "You must enter a value: prod, dev, dr, or test AND the password of the env you entered"
     exit 0
  else
      for host in `cat $file`
      do
    ssh-copy-id -i ~/.ssh/id_rsa.pub $host <<-EOF
    expect "password:"
    send "$2\n" 
    EOF
      done
  fi
done

I found an expect script that does most of what I need:

#!/usr/bin/expect -f
spawn ssh-copy-id $argv
expect "password:"
send "your_password\n"
expect eof

to execute ./expect_script user@host1

My problem is that I don't know enough of either bash or expect to get these two to work under one bash script or expect script.

Thank you in advance....

JKC
  • 31
  • 2

1 Answers1

1
#!/bin/bash
#
invdir=/home/john/inventory

for file in "$invdir"/"$1"
do
  if [[ -z "$1" ]] || [[ -z "$2" ]]
  then
    echo "You must enter a value: prod, dev, dr, or test AND the password of the env you entered"
    exit 0
  else
    while IFS= read -r host
    do
      export host
      export pw="$2"
      expect <<'EOF'

        spawn ssh-copy-id -i $env(HOME)/.ssh/id_rsa.pub $env(host)
        expect "password:"
        send "$env(pw)\n" 
        expect eof

EOF
    done < "$file"
  fi
done

Some notes:

  • take care to quote your shell variables, especially positional params
  • you need to launch the expect interpreter to run expect code
  • pass shell variables to expect via the environment
  • don't read the lines of a file with for
  • I don't use <<-EOF because it's too easy to use non-tabs for the EOF word.
  • but do use <<'EOF' to protect the expect variables
glenn jackman
  • 4,630
  • 1
  • 17
  • 20
  • hi Glenn, Thank you for the answer and suggestions. When I ran the new script, it's giving me the following errors: `./new-ssh-login.sh prod mypasswd` `invalid command name "ssh-copy-id" while executing "ssh-copy-id -i ~/.ssh/id_rsa.pub $env(host)"` – JKC Jun 29 '23 at 13:01
  • D'oh! I forgot to use the crucial expect `spawn` command to launch the process we're going to control. Fixed. – glenn jackman Jun 29 '23 at 13:39
  • I'm not sure off the top of my head that expect understands `~` , so I used the HOME environment variable instead. – glenn jackman Jun 29 '23 at 13:41
  • Thanks Glenn. the scripts works now!!! I do have 2 questions. 1. how does the line `while IFS= read -r host` translate to $file (as this is what it looks like it's doing. 2. the line `done < "$file"` is this FEEDING the while loop Again, thank you so much. – JKC Jun 29 '23 at 16:00
  • Yes that's right. We're redirecting the contents of the file into the while loop, and the `read` command then consumes the input line-by-line. Explained in detail at https://mywiki.wooledge.org/BashFAQ/001 – glenn jackman Jun 29 '23 at 17:29
  • hi Glenn, One more favor. How can I ping the host and if it pings, go onto the spawn ssh-copy-id command else goto the next host. I'm just not sure how to put this in the script. Thanks again. – JKC Jul 03 '23 at 11:56
  • Ask a separate question. – glenn jackman Jul 04 '23 at 12:07