Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

expect script hangs when spawning SHELL

97 views
Skip to first unread message

guido.a...@gmail.com

unread,
Jun 8, 2015, 6:39:24 AM6/8/15
to
Dear all,

I am trying to set up an expect script to automate an scp copy on multiple servers. For some unknown reasons, I need to spawn a shell to get it to work, but this is OK by me. The problem is that I cannot seem to close/exit/kill this shell after I successfully do the scp. Here is the script

foreach host $servers {
# Check if $host is a valid name/IP
if {[string match {*.*.*.*} $host]} {
# Set timestamp for current host
set timestamp [clock format [clock seconds]]
send_user "*******************************\n"
send_user "$timestamp\n"
send_user "\tHOST: $host\n"
send_user "*******************************\n"

set pid [spawn $env(SHELL)]
send "scp -p $filetocopy $user@$host:$scp_dir\r"
expect {
"*yes/no*" {
send "yes\r"
exp_continue
}
"*?assword:*" {
send "$password\r"
}
timeout {
send_user "Connection timed out for SCP\n"
}
}
exec kill $pid
}
expect eof
}

If I execute the script with -d, I get "expect: timed out" after the scp is complete. Any thoughts?

Best,
Guido

Rich

unread,
Jun 8, 2015, 11:25:03 AM6/8/15
to
guido.a...@gmail.com wrote:
> Dear all,

> I am trying to set up an expect script to automate an scp copy on
> multiple servers. For some unknown reasons, I need to spawn a shell
> to get it to work, but this is OK by me. The problem is that I cannot
> seem to close/exit/kill this shell after I successfully do the scp.

You could try sending the shell an "exit" command after the scp is
done.

heinrichmartin

unread,
Jun 9, 2015, 2:11:35 AM6/9/15
to
On Monday, June 8, 2015 at 12:39:24 PM UTC+2, Guido Avvisati wrote:
> set pid [spawn $env(SHELL)]
> send "scp -p $filetocopy $user@$host:$scp_dir\r"
> expect {
> "*yes/no*" {
> send "yes\r"
> exp_continue
> }
> "*?assword:*" {
> send "$password\r"
> }
> timeout {
> send_user "Connection timed out for SCP\n"
> }
> }
> exec kill $pid
> }
> expect eof
> }

In this snippet, you are not waiting for the scp to complete. This expect command times out by design.

heinrichmartin

unread,
Jun 9, 2015, 2:19:45 AM6/9/15
to
On Monday, June 8, 2015 at 12:39:24 PM UTC+2, Guido Avvisati wrote:
> I am trying to set up an expect script to automate an scp copy on multiple servers. For some unknown reasons, I need to spawn a shell to get it to work, but this is OK by me. The problem is that I cannot seem to close/exit/kill this shell after I successfully do the scp. Here is the script

Maybe my version helps:

vvvvvvvvvvvvvvvvvvvvvvvvvv
# argument handling above
# do scp
global spawn_id
set ret true
if {0 == [::spawn -noecho scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o NumberOfPasswordPrompts=1 $src $dst]} {
::logger::tree::lib::error "{[::info level 0]} cannot spawn scp."
set ret false
} else {
set sid $spawn_id
expect {
-i $sid
-ex "assword: " {
exp_send -i $sid "$passwd\r"; exp_continue
}
-ex "ermission denied" {
::logger::tree::lib::error "{[::info level 0]} wrong password."
set ret false
}
-re {[\r\n]} {
exp_continue
}
timeout {
::logger::tree::lib::error "{[::info level 0]} timed out."
set ret false
}
eof {
::logger::tree::lib::info "{[::info level 0]} completed."
}
}
# close the spawned process
::lib::wait $sid sid
if {$sid} {
::logger::tree::lib::error "{[::info level 0]} scp returned a non-zero exit code {$sid}."
set ret false
}
}
return $ret
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

where ::lib::wait is

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
# waits for the current child process to terminate.
# This releases the spawn id and its resources.
# @param sid the spawn id like the parameter <code>-i</code>
# of <code>send</code>. <code>$::spawn_id</code> by default
# @param ec the name of the variable to receive the exit code on success
# @return <code>true</code> on success, <code>false</code> else
proc wait {{sid {}} {ec {}}} {
if {{} eq $sid} {
return ::lib::wait $::spawn_id
}
if {{} ne $ec} {
upvar 1 $ec myec
}
catch {close -i $sid}
set ret false
if {[catch {::wait -i $sid} ret]} {
::logger::tree::lib::warn "Error while waiting for $sid."
catch {::wait -nowait -i $sid}
return false
} elseif {[lindex $ret 2]} {
::logger::tree::lib::warn "System error [lindex $ret 3] while waiting for $sid."
return false
} else {
set myec [lindex $ret 3]
::logger::tree::lib::debug "{$sid} has terminated with status {$myec}."
return true
}
# UNREACHABLE
}
# Cannot export this proc. It conflicts with a built-in proc.
# namespace export wait
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0 new messages