-1

Based on one of the topics posted here, i have designed my expect script to return the exit code but for some reason it keeps on running and doesnt exit at all

I am using the below script to -get a file from the remote server -delete the file after the transfer is complete

Below is the code written

set timeout 30

set user [lindex $argv 0]
set pass [lindex $argv 1]
set host [lindex $argv 2]
set remote_file [lindex $argv 3]
set local_file [lindex $argv 4]
set port [lindex $argv 5]

if {$port != "" } {
spawn sftp -oPort=$port $user@$host
} else {
spawn sftp $user@$host}
expect -nocase password:
send "$pass\r"
expect sftp>

send "get $local_file $remote_file\r"
expect sftp>

send "rm $local_file\r"
expect eof

set waitval [wait -i $spawn_id]
exit [lindex $waitval 3]

-> It should have exit with the return code.

I am using the below alternate script for now. It works. But I was hoping to make it more generic without mentioning the error messages. Please let me know if there is any improvements that can be done for the below script.

set timeout 30

set user [lindex $argv 0]
set pass [lindex $argv 1]
set host [lindex $argv 2]
set remote_file [lindex $argv 3]
set local_file [lindex $argv 4]
set port [lindex $argv 5]

if {$port != "" } {
spawn sftp -oPort=$port $user@$host
} else {
spawn sftp $user@$host}
expect -nocase password:
send "$pass\r"
expect {
-re "failed|invalid password|incorrect|denied" {exit 1}
"Connection closed" {exit 1}
timeout {exit 1}
"sftp>"
}

send "get $local_file $remote_file\r"
expect {
-re "not found|denied|error|failure" {exit 1}
"No such file or directory" {exit 1}
timeout {exit 1}
"sftp>"
}

send "rm $local_file\r"
expect {
-re "not found|denied|cannot remove|error|failure" {exit 1}
"No such file or directory" {exit 1}
"sftp>"
}

send "exit\r"
expect eof

Regards, Allen

Allen
  • 1
  • 1

2 Answers2

2

For your first script:

It should have exit with the return code.

You need to tell the spawned sftp to exit, else wait waits forever:

[...]
send "get $local_file $remote_file\r"
expect sftp>

send "rm $local_file\r"
expect sftp>

send "exit\r"

set waitval [wait -i $spawn_id]
exit [lindex $waitval 3]

As for the second script, I'd at minimum define a proc that gracefully exits on an error condition, instead of just exit 1 with no explanation. Something like this:

# Lets user know what went wrong, then gracefully stop sftp
proc err_exit {msg} {
  puts stderr "ERROR: $msg, aborting."
  send "exit\r"
  expect eof
  exit 1
}
[...]
expect {
  -re "failed|invalid password|incorrect|denied" {
    err_exit "Access denied"
  }
  "Connection closed" {
    err_exit "sftp connection closed unexpectedly"
  }
  timeout {
    err_exit "Timeout occurred"
  }
  "sftp>"
}

Oh, and your code is in serious need of proper indentation and alignment. Tcl doesn't care, but code comprehension is hampered without it. (Take the fact that you told sftp to exit in the second script but not the first as a warning sign.)

Adrian
  • 595
  • 4
  • 9
0

Adrian,

I modified the script as below

[...]

send "rm $local_file\r"
expect sftp>

send "exit\r"

set waitval [wait -i $spawn_id]
exit [lindex $waitval 3]

I tested a scenario of file not present in our target system and below is the output of it

sftp> get /pw/work/outbound/SendBills*.zip /pw/work/inbound/ar/
File "/pw/work/outbound/SendBills*.zip" not found.

sftp> rm /pw/work/outbound/SendBills*.zip
Removing /pw/work/outbound/SendBills*.zip
Couldn't delete file: No such file or directory

So i was expecting the spawn expect script to return an exit code other than 0 to my calling .sh script.

I may have forgot to mention that my main script is .sh. Within it, I am calling the expect script which has the above commands that i posted.

Command from my .sh script:

if [ "$PSWD" = "Y" ]
then

$PS_APP_HOME/az/scripts/sh/azstmtsftp.exp $USER $PASS $HOST $REMOTE $LOCAL $PORT --   Here is where I am calling the expect script

else 

--This was written in case the third pary goes for SSH keys in future
sftp  $USER@$HOST  <<EOF
get $LOCAL $REMOTE
rm $LOCAL

EOF
fi

RETCODE=$?

I was hoping that the $RETCODE will have the error exit code (from my expect script) rather than 0

Based on the return code, i was hoping to plan my further actions.

Regards, Allen

Allen
  • 1
  • 1