0

I'm trying to run an expect script that SSHs to another local device to install and run a python script. All variables are defined outside of the script:

set prompt "$SSHuser@$SSHname:~$"
spawn ssh -o \"StrictHostKeyChecking no\" $SSHuser@$SSHhost
expect
{
  "*assword"
  {
    send "$SSHpassword\r"
    exp_continue
  }
  "$prompt"
  {
    send "sudo su"
    expect
    {
      "*assword"
      {
        send "$SSHpassword\r"
        exp_continue
      }
      "$prompt"
      {
        send "apt update && apt upgrade -y && apt install net-tools -y && apt install python3-pip -y"
        expect "$prompt"
        {
        send "wget -O script.py https://SOMEURL"
        }
      }
    }
  }
}

However, I keep getting the following output/error:

missing close-brace
    while executing
"{"
couldn't read file "sur
    expect
    {
      *assword
      {
        send REDACTEDPASSWORD
        exp_continue
      }
      
      {
        send -- apt": no such file or directory
spawn ssh -o StrictHostKeyChecking no USERNAME@192.168.1.173
USERNAME@192.168.1.173's password: 

I have counted the brackets and used highlighting tools and I do not see any missing brackets. I also do not understand why it keeps reading "send "sudo su\r" as "sur". My exposure to expect is still pretty limited. I would really appreciate any help in understanding what has gone wrong here.

YLR
  • 1,503
  • 4
  • 21
  • 28
  • 1
    You need a backslash at the end of the `expect` lines so the next line is treated as part of the same command. See https://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm for details of how tcl is parsed. – Shawn Oct 25 '20 at 03:56
  • I'm not sure if you can nest `expect` calls like that either, but I'm way more familiar with tcl in general than expect. – Shawn Oct 25 '20 at 04:05
  • have you thought about using ansible? there are ansible modules like expect or apt. With ansible you are executing python scripts on remote machines by using ssh-coonnections. see https://docs.ansible.com/ansible/latest/collections/ansible/builtin/expect_module.html – Oliver Gaida Oct 25 '20 at 07:11
  • If you use SSH public key authentication and setup sudo properly, there is no more need to use `expect`. – Philippe Oct 25 '20 at 07:59
  • Take a look at my [sexpect (Expect for Shells)](https://github.com/clarkwang/sexpect) which you can use to write Expect scripts with **shell code only**. – sexpect - Expect for Shells Oct 26 '20 at 01:57

1 Answers1

0

Tcl forces you to use the "one true brace style" because newlines are command terminators.

As a comment, expect code does not have to be so deeply nested. This code can be written as

set prompt "$SSHuser@$SSHname:~$"

spawn ssh -o "StrictHostKeyChecking no" $SSHuser@$SSHhost
expect {
  "*assword" {
    send "$SSHpassword\r"
    exp_continue
  }
  "$prompt"
}

send "sudo su"
expect {
  "*assword" {
    send "$SSHpassword\r"
    exp_continue
  }
  "$prompt"
}

send "apt update && apt upgrade -y && apt install net-tools -y && apt install python3-pip -y"
expect "$prompt"

send "wget -O script.py https://SOMEURL\r"
expect "$prompt"

# assuming you want to exit here
send "exit\r"
expect eof

Essentially, each spawn or send should be followed by an expect.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352