0

In Expect script, how do you prompt user without writing to stdout? Is it possible to prompt the user through stderr?

I have a script written in Perl to automate some testing using ssh. In order to automate login for ssh, I wrapped the ssh command using Expect, but sometimes the password for ssh expires mid-way in executing the code (e.g rsa token refreshes every 30seconds).

I found this: How can I make an expect script prompt for a password?

which works great, except it prompts the user through stdout. My Perl script reads and parses the stdout.

I would like to abstract this to my Expect script without modifying the Perl code, is it possible?

Edit: I just realized my use case is stupid since I'm not sure how Perl will be able to interact with the Expect script prompt since I'm calling the Expect script from Perl. :/ But it would still be good to know if it's possible to Expect to write to stderr. :D

Thanks!

Community
  • 1
  • 1
T.Ho
  • 1,190
  • 3
  • 11
  • 16
  • Once you are in, it doesn't matter if the password expires, unless you have a quite unusual SSH/shell configuration. Without knowing the details it is very hard to give you any helpful advice. Also, show us your code! – salva Feb 07 '14 at 08:12
  • The problem is I need to run a series of different commands to the box. Ideally, it would be best to spawn a persistent ssh session and pass the command through that, but it was easier to spawn a new session each time. I'm not too familiar with Perl to implement the former approach. – T.Ho Feb 11 '14 at 21:56
  • Then, try Net::OpenSSH. – salva Feb 11 '14 at 22:03
  • I haven't looked into Net::OpenSSH module directly, but I have tried Net::SSH:Perl which has a binary dependency which is platform specific. It was somewhat difficult to successfully compile the module. I'm assuming this would be a similar case with Net::OpenSSH, which seems to be relying on a binary ssh client. – T.Ho Feb 11 '14 at 22:12
  • Net::OpenSSH requires OpenSSH ssh client, but this is available for most Unix/Linux. And it doesn't work on Windows, but Expect doesn't either. Another option is Net::SSH::Any. – salva Feb 12 '14 at 10:48

1 Answers1

1

You can try accessing the “file” /dev/tty (it's really a virtual device). That will bypass the Perl script and contact the user's terminal directly. Once you've got that open, you use normal Expect commands to ask the user to give their password (remembering to turn off echo at the right time with stty).

Otherwise, your best bet might actually be to pop up a GUI; using a little Tcl/Tk script to do this is pretty trivial:

# This goes in its own script:
pack [label .l -text "Password for [lindex $argv 0]"]
pack [entry .e -textvariable pass -show "*"]
bind .e <Enter> {
    puts $pass
    exit
}
focus .e
# In your expect script:
set password [exec wish getPass.tcl "foo@bar.example.com"]

That's all. It's also a reasonably secure way of getting a password, as the password is always communicated by (non-interceptable) pipes. The only downside is that it requires a GUI to be present.

The GUI is probably in need of being made prettier. That's just the bare bones of what you need.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • The subprocess GUI script could be in any other language too, but Tcl/Tk is what I know best. – Donal Fellows Feb 07 '14 at 09:15
  • Thank you for the reply. I decided to go with modifying my Perl script since the Perl script should be aware of the new password so it can reuse it on a different call without having to re-authenticate each time. +1 for showing how to bypass the Perl script and give access to the user's terminal directly/ :). Thanks! – T.Ho Feb 11 '14 at 22:02