Problem that you are having is that you do run the send command as a consequence of first getting the password. So after the default timeout you send the password when no password prompt is seen and if you get a password you send the timeout. This is some boiler plate code I use to login to ssh and execute a command you can convert it to run your command just change the spawn invocation.
#!/bin/sh
# the next line restarts using wish \
exec /opt/usr8.6.3/bin/tclsh8.6 "$0" ${1+"$@"}
foreach pkg { Expect } {
if { [ catch {package require $pkg } err ] != 0 } {
puts stderr "Unable to find package $pkg\n$err\n ... adjust your auto_path!";
}
}
proc runSSHCommand { command user host password } {
set pid [ spawn ssh ${user}@${host} $command ]
set spawn_id $spawn_id;
set timeout 10
set bad 0;
set done 0;
exp_internal 0; # set to one for extensive debug
log_user 0; # set to one to watch action
set output ""
expect {
-i $spawn_id
-re {^.*password:} {
exp_send "$password\r"
}
-re {.*\(yes/no\)\?[ ]*$} {
# if a new host may need to agree to pass the host keys
exp_send "yes\r"
exp_continue; # stay inside this expect like a while loop without this we exit this expect
}
-re {Temporary failure in name resolution} {
# handle dns failure ... should use ip address or FQDN
append output $expect_out(buffer)
append output "$host was not found use IPAddress or FQDN for host\n"
set bad 1
}
timeout {
send_user "No password was sent\n"
}
fullbuffer {
# expect fill up after 10000 bytes 'fullbuffer' event hits at this point you can save the expect_out(buffer) here
# or ignore it
exp_continue;
}
eof {
set done 1 ;
}
}
if { !$done && !$bad} {
expect {
-i $spawn_id
-re {.{30}} {
# get every 30 characters change this as appropirate
send_user "."
append output $expect_out(buffer);
exp_continue; # stay inside this expect like a while loop without this we exit this expect
}
timeout {
send_user "hmm process is taking too long killing "
exec kill -9 $pid
set bad 1
}
fullbuffer {
# expect fill up after 10000 bytes 'fullbuffer' event hits at this point you can save the expect_out(buffer) here
# or ignore it
append output $expect_out(buffer)
exp_continue;
}
eof {
append output $expect_out(buffer)
send_user "\nall done!"
set done 1 ;
}
}
}
set exitstatus [ exp_wait -i $spawn_id ];
catch { exp_close -i $spawn_id };
if { $bad } {
throw ERROR $output
}
return $output
}
try {
set output [runSSHCommand {cat backup.tcl} username host password ]
} trap ERROR {a } {
puts "Error : $a"
exit 1
} on error { a b } {
puts "Unexpected error: $a \n$b"
exit 1
}
puts $output
puts "SUCCESS!"
exit 0