0

I'm having some trouble with an expect script I am writing. The goal of the script is to SSH to a partner and obtain network configuration information. That information is saved in a file and copied back to the local host for processing. The file is then removed from the remote host upon exit.

Under normal conditions, everything works great and as I would expect. However, should the user press ^C to interrupt the script during the SCP process, the file is not removed from the remote host. It is left there. I am not sure why this is or how to force its removal. When stepping through my signal handler and exit handler during such a case, it appears that for some reason the exit handler doesn't think that the file exists and skips the if statement. I have no idea why, though.

I have copied the exit handler and signal handler from my script below. Please let me know if you have any ideas or see any obvious errors. I'm not sure where to go from here.

# Configure exit handler
exit -onexit {
    # Remove configuration info file if it exists 
    if {[file exists ptinit.txt]} {
        send "rm -rf ptinit.txt\r"
        expect -exact "rm -rf ptinit.txt\r"
    }
}

# Configure signal trap to remove partner file before exiting
proc errsig_handler {pidlst} {
    send_user "\nStop command received from user. Exiting.\n"

    for {set i [expr [llength $pidlst]-1]} {$i >= 0} {incr i -1} {
        send_user "Current PID is: [lindex $pidlst $i]\n"

        # If pid is not null and process is currently running, kill it
        if {[lindex $pidlst $i] != "" && [exec kill -0 [lindex $pidlst $i] 2>/dev/null] == ""} {
            send_user "PID [lindex $pidlst $i] is not null and is currently running.\n"
            exec kill -9 [lindex $pidlst $i]
        }
    }
}

trap {errsig_handler $cur_pid} {INT TSTP}

UPDATE: I tried the method suggested by Dinesh, but am still having issues. I updated the exit handler code as follows: exit -onexit { exp_internal 1 unset expect_out(buffer)

# Remove configuration info file from remote server 
send_user "\nIN EXIT HANDLER\n"

send "rm -rf ptinit.txt\r"
expect {
    "rm -rf ptinit.txt\r" {
        sleep 5
        send "exit\r"
        expect eof {puts "EOF in rm match received."; sleep 2}
    }
    "cannot remove" { 
        puts "File deletion was not successful - ptinit.txt needs to be deleted manually."
    }
    -re $prompt {
        sleep 5
        send "exit\r"
        expect eof {puts "EOF received."; sleep 2}
    }
}

send_user "LEAVING EXIT HANDLER\n"

}

The only way I could get this to work was by commenting out my signal handler for loop that kills the spawned PIDs. When it is uncommented, the exit handler expect times out.

Either way, the file still is not removed from the remote system. This is what I see from exp_internal 1:

Stop command received from user. Exiting.

IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|\$) $' is ''. Not usable, disabling the performance booster.

expect: does " \r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? no
"cannot remove"? no
"(%|#|>|\$) $"? (No Gate, RE only) gate=yes re=no

expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? yes
expect: set expect_out(0,string) "rm -rf ptinit.txt\r"
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r"
send: sending "exit\r" to { exp9 }
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) "\n\rptinit.txt                                      0%    0     0.0KB/s   --:-- ETA\rptinit.txt
                               100%   35     0.0KB/s   00:00    \r\nexit\r\n"
EOF in rm match received.
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0

UPDATE 2:

I updated the exit handler to the following:

exit -onexit {
    exp_internal 1
    unset expect_out(buffer)

    # Remove configuration info file from remote server 
    set filename ptinit.txt
    send_user "\nIN EXIT HANDLER\n"

    send "rm -rf $filename\r"
    expect {
        "cannot remove" { puts "File deletion is not successful" }
        -re $prompt { puts "File deleted" }
    }
    send_user "LEAVING EXIT HANDLER\n"
}

This is the debugging information - still no file deleted.

Stop command received from user. Exiting.

IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|\$) $' is ''. Not usable, disabling the performance booster.

expect: does " \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|\$) $"? (No Gate, RE only) gate=yes re=no

expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|\$) $"? (No Gate, RE only) gate=yes re=no

expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt                                      0%    0     0.0KB/s   --:-- ETA" (spawn_id
 exp9) match glob pattern "cannot remove"? no
"(%|#|>|\$) $"? (No Gate, RE only) gate=yes re=no

expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt                                      0%    0     0.0KB/s   --:-- ETA\rptinit.tx
t                                    100%   35     0.0KB/s   00:00    \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|\$) $"? (No Gate, RE only) gate=yes re=no
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r\n\rptinit.txt                                      0%    0     0.0KB/s   --
:-- ETA\rptinit.txt                                    100%   35     0.0KB/s   00:00    \r\n"
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0
legendmac
  • 43
  • 2
  • 8

1 Answers1

0

The problem is because of file exists. It checks the file path present or not in the local machine wherever you are running the Expect script, not in the remote directory.

Removing that will solve the problem.

#This is a common approach for few known prompts
#If your device's prompt is missing here, then you can add the same.
set prompt "#|>|\\\$"; # We escaped the `$` symbol with backslash to match literal '$'

set filename ptinit.txt
send "rm -rf $filename\r"
expect {
    "cannot remove" { puts "File deletion is not successful"}
    -re $prompt { puts "File deleted" }
}

Update : In your code, you are expecting for rm -rf ptinit.txt\r which is wrong. Because expect will see the what is sent to the spawned process (that is also rm -rf ptinit.txt\r) and match that. Due to this, it is never actually sent to the spawned process.

So, Can you enable debug for the above code given by me and share here?

Dinesh
  • 16,014
  • 23
  • 80
  • 122
  • I can't seem to get your suggestion to work either. I have edited my post above with details on what I tried. – legendmac Jun 05 '15 at 15:53
  • @legendmac : Updated my answer. Waiting for your reply. – Dinesh Jun 05 '15 at 16:05
  • Updated my post with the debugging results. Still not getting the file deleted, as it's not matching either "cannot remove" or -re $prompt. It gets an EOF, instead. – legendmac Jun 05 '15 at 18:40
  • Was able to get this to work by expecting `-re $` instead of the `$prompt`, and adding in a `sleep 3` statement to prevent it from exiting too quickly. – legendmac Oct 13 '15 at 21:22