0

I am using expect for a streamlined login script to a whitelisted-only (thus low vulnerability) postgres instance. Here is the redacted script

#!/usr/bin/expect
set RDSI [lindex $argv 0]
spawn /usr/local/bin/psql -U postgres -h $RDSI -d clips
expect "Password" 
send "myPassword\r" 
interact 
expect eof  # I have tried with and without this line

Let's run it:

19:00:38/ciderapp $./exp.sh
spawn /usr/local/bin/psql -U postgres -h  -d clips
SET
psql (12.4)
Type "help" for help.

clips=#       # We get into the db v quickly          
              # Delays here for about 20+ seconds
myPassword    # we don't necessarily want this printed!
clips-# 

Three questions:

  • Given the initial entry to the clips is very fast (essentially immediate) what is going on for the subsequent 20+ second delay?
  • Is there any way to suppress the display of the myPassword ?
  • Given we were already connected before myPassword were printed then the behavior of ( a ) wait ~20seconds then ( b ) print the myPassword is confusing. Can that be explained?
WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560

2 Answers2

1

What you are seeing is the expected behavior of expect. You wait for it to receive the password prompt or to timeout (default 10 seconds), and then once it does one of those things you send the password unconditionally. You need to make the sending of the password conditional on receiving the password prompt, if you want to use it in situations where the prompt might not come.

But really there is no point in using expect with psql anyway, as PostgreSQL offers many better ways than that to get tasks done.

jjanes
  • 37,812
  • 5
  • 27
  • 34
  • Thx - can you address the specific bullet points to clarify how these are the anticipated behaviors - and if a different approach might be used? – WestCoastProjects Nov 03 '20 at 15:02
1

You can make the expect command do things conditionally. Here, you expect the password prompt, but it does not appear.

Assuming the interactive prompt is "clips-#", you can do this:

#!/usr/bin/expect
set RDSI [lindex $argv 0]
spawn /usr/local/bin/psql -U postgres -h $RDSI -d clips
set prompt "clips-#"
expect {
    "Password" 
        send "myPassword\r" 
        exp_continue
    }
    $prompt
}
interact 

There are 2 patterns in that expect statement. If "password" is seen, it will send the password and then continue in that same expect statement. When the prompt is seen, since there is no action for it, the expect command returns.

For the last line of an expect script, use

  • interact if you, the human, needs to interact with the spawned process, or
  • expect eof if no interaction is required, you just need to wait until the process ends.
glenn jackman
  • 238,783
  • 38
  • 220
  • 352