Re: Expect in a shell pipe




howardbryden@xxxxxxxxxxxxxx wrote:
I'm attempting to pipe commands to ssh(1) while also using Expect to
handle the optional dialog that ssh can generate. I'm using version
5.43.0 under HP-UX 11.11.

My Expect script is as follows:

##########
if [catch "spawn -noecho /usr/bin/ssh -i ~/.ssh/id_rsa_SVC -l admin
dessvc" reason] {
send_error -- "x: Failed to spawn SSH: $reason\n"
exit 1
}

set timeout -1
log_user 0

expect {
-exact "Are you sure you want to continue connecting (yes/no)? " {
send -- "yes\r"; exp_continue }
-exact "yes\r\n" exp_continue
-re "Warning: Permanently added '.*' (.*) to the list of known
hosts.\r\r\n" exp_continue
-exact "Enter passphrase for key '/root/.ssh/id_rsa_SVC': " { send
-- "passphrase\r" }
-re "Enter passphrase for RSA key '.*': " { send -- "passphrase.\r"
}
-re "..*" { send_error -- "$expect_out(0,string)" }
}

expect -re "^\r\n"

close_on_eof 0
interact
expect
exit
##########

The command line invocation is

echo "{command1}
{command2}
exit" | expect -f {script}

where {command1} and {command2} are arbitrary commands and {script} is
of course the above Expect script.

Using the close_on_eof / interact / expect sequence as per the thread
http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/b75184d13782f114/f731162c65184d7a?lnk=gst&q=expect+pipe+input+interact&rnum=1#f731162c65184d7a
("using Expect as path in pipe"), above pipe hangs.

Using Expect's -d option to trigger debugging, the final part of the
trace was (I've explicitly inserted linefeeds after the \r\n sequences
to hopefully render it a bit clearer):

expect: does "\r\n" (spawn_id exp6) match regular expression "^\r\n"?
yes
expect: set expect_out(0,string) "\r\n"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\n"
spawn id exp0 sent <svcinfo lsnode\nsvcinfo lsnode\nexit\n>
interact: received eof from spawn_id exp0
expect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "{command1}\r\n
{command2}\r\n
exit\r\n
Last login: Wed Sep 27 17:20:34 2006 from 10.2.82.100\r\r\n
{command1}\r\n
{command2}\r\n
exit\r\n
IBM_2145:DES_SVC1:admin>{command1}\r\n
{output from command1}\r\n
IBM_2145:DES_SVC1:admin>{command2}\r\n
{output from command2}\r\n
IBM_2145:DES_SVC1:admin>exit\r\n
exit\r\n
Connection to dessvc closed.\r\r\n"
write() failed to write anything - will sleep(1) and retry...


Seeing that the output was apparently being received into
expect_out(buffer), I then thought that send_user could dump the
output, so I recast the final part of the Expect script thusly:

...
close_on_eof 0
interact
expect
send_user -- "$expect_out(buffer)"
exit


But, no dice, the final part of the debug trace was:

send: spawn id exp0 not open
while executing
"send_user -- "$expect_out(buffer)""
(file "z" line 24)
write() failed to write anything - will sleep(1) and retry...


send_tty worked though:

...
close_on_eof 0
interact
expect
send_tty -- "$expect_out(buffer)"
exit


The output now appeared as:

svcinfo lsnode
svcinfo lsnode
exit
Last login: Wed Sep 27 17:34:18 2006 from 10.2.82.100
svcinfo lsnode
svcinfo lsnode
exit
IBM_2145:DES_SVC1:admin>{command1}
{output from command1}
IBM_2145:DES_SVC1:admin>{command2}
{output from command2}
exit
Connection to dessvc closed.


However:

1. send_tty of course sends its output to the session terminal, not to
stdout as such. I'd like to know why send_user didn't do that.

2. Even the output as produced by send_tty included extraneous stuff
like the input commands and prompt strings. Ideally I would have like
just the outputs, in this case the {output from command1} and {output
from command2} sections. Is this possible?

3. The close_on_eof setting was not advertised in the Expect manpage.
Indeed it announces a date of 29 December 1994, perhaps it needs an
update.


Thanks for any help.

try piping your commands to a shell executed by ssh like so
put in your own values for user, host, password,
I changed the expect part to test but you can modify the actual ssh
options
and expect text string to your requirements.
#!/opt/usr/bin/tclsh8.4
package require Expect
# read in input
set buff [read stdin ]
if [catch {spawn /usr/bin/ssh -i ~/.ssh/id_dsa.pub $user@$host
"/bin/sh" } reason] {
send_user -- "x: Failed to spawn SSH: $reason\n"
exit 1
}
set timeout -1
log_user 0

expect {
-re ".*password:" {
exp_send "$password\r"
exp_continue;
}
-re ".* (yes/no)? " {
send -- "yes\r"; {
exp_continue
}
-re ".*Warning: Permanently .*known hosts.\r\r\n" exp_continue
}
-re "..*" { send_error -- "$expect_out(0,string)" }
}

exp_send "$buff\r"
expect {
eof {
puts "$expect_out(buffer)"
}
}
catch { exp_close -i $spawn_id }
# comment this out to just get output from your command
puts " [ exp_wait -i $spawn_id -nowait ]"

suppose above is in fiel expectpipe.tcl then
echo "ls -la /tmp; exit " | expectpipe.tcl
would give you :
drwxrwxrwt 34 root root 69632 Sep 27 12:23 .
drwxr-xr-x 30 root root 4096 Sep 13 10:42 ..
...
12989 exp4 0 0

.



Relevant Pages

  • Expect in a shell pipe
    ... My Expect script is as follows: ... where and {command2} are arbitrary commands and is ...
    (comp.lang.tcl)
  • Re: Changing a users password non-interactively?
    ... You need expect and a setpass.expect script which ill add ... exit with a nasty warning. ... # Be careful of the COMMAND and UNDOCMD - they are dependant on your ...
    (comp.unix.aix)
  • Re: script does not always work the same each time.
    ... I have written a simple script to test code build and test run on a ... $lineterminationChar {append output $expect_out; ... exit 1;} ...
    (comp.lang.tcl)
  • Re: need small PHP job done
    ... i need help tweaking a PHP mail script; ... // check for a recipient email address and check the validity of it ... // check for an attachment if there is a file upload it ...
    (alt.php)
  • Re: OSR505 Signal trapping in shell scripts
    ... >>My test script is at the end. ... > process only gets one SIGHUP per fd. ... > end up doing ioctls on fd 0, which is your stopio'd telnetd pty. ... > of the exit function. ...
    (comp.unix.sco.misc)