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

How to catch erro from spawned command?

259 views
Skip to first unread message

eric...@gmail.com

unread,
Apr 14, 2008, 5:19:39 PM4/14/08
to
Hi,

I have a problem with this in expect:
spawn ssh f...@123.123.123.123 ls -l > /tmp/mylog 2>&1
while (1) {
expect timeout { puts "get timeout\n"; exit 99} \
"Are you sure*" { send "no\r"; break; } \
"*password: $" { send "$passwd\r"; continue; } \
eof { puts "get eof\n"; break;} \
default { puts "get default\n"; break;};
}

The problem is if "ssh" failed, like teh script get a dummy ip
address, the erro message, "ssh: connect to host xxx.xxx.xxx.xxx port
22: No route to host" didn't get to /tmp/mylog/. This is because
expect think my command is
'spawn ssh f...@123.123.123.123 "ls -l > /tmp/mylog 2>&1 ' but what I
really want is

eric...@gmail.com

unread,
Apr 14, 2008, 5:25:45 PM4/14/08
to
Sorry I hit the wrong key and the message just got sent. Here is a
rewrite:

I have a problem with this in expect:
spawn ssh f...@123.123.123.123 ls -l > /tmp/mylog 2>&1
while (1) {
expect timeout { puts "get timeout\n"; exit 99} \
"Are you sure*" { send "no\r"; break; } \
"*password: $" { send "$passwd\r"; continue; } \
eof { puts "get eof\n"; break;} \
default { puts "get default\n"; break;};
}

The problem is if "ssh" failed, like the script get a dummy ip
address, the erro message, "ssh: connect to host 123.123.123.123 port
22: No route to host" didn't get to /tmp/mylog. This is because


expect think my command is
'spawn ssh f...@123.123.123.123 "ls -l > /tmp/mylog 2>&1" '
but what I really want is

'spawn "ssh f...@123.123.123.123 ls -l" > /tmp/mylog 2>&1 '
so I can catch the ssh error.

How should I correct tghe command syntax?

Eric.

Bruce Hartweg

unread,
Apr 14, 2008, 5:10:38 PM4/14/08
to

The results (including errors) will come back to your expect script directly.
No need to redirect to a file - you can use expect commands to deal with them.

Bruce

eric...@gmail.com

unread,
Apr 14, 2008, 6:07:25 PM4/14/08
to
hi Bruce,

I just tested. The expect script will not catch the "No route to
host". It will only catch the "eof" afterward which left me no clue
about the "eof" is from a successful action or failed one.

Eric.


On Apr 14, 2:10 pm, Bruce Hartweg <doNOT...@nowhere.com> wrote:

> Bruce- Hide quoted text -
>
> - Show quoted text -

Bruce Hartweg

unread,
Apr 14, 2008, 6:49:24 PM4/14/08
to
eric...@gmail.com wrote:
> hi Bruce,
>
> I just tested. The expect script will not catch the "No route to
> host". It will only catch the "eof" afterward which left me no clue
> about the "eof" is from a successful action or failed one.
>

yes it does - the eof pattern is what you want.
inside there you can look at the contents of expect_out(buffer) to see
the messages, and also the results of a call to wait will give you
the exit status of your spawned program.

eric...@gmail.com

unread,
Apr 14, 2008, 7:24:49 PM4/14/08
to
Hi Bruce,

Got it. Appreciate your help. Thanks very much.

Eric.

> >> - Show quoted text -- Hide quoted text -

Bezoar

unread,
Apr 14, 2008, 8:00:52 PM4/14/08
to
On Apr 14, 4:25 pm, eric5...@gmail.com wrote:
> Sorry I hit the wrong key and the message just got sent. Here is a
> rewrite:

You've got several problems with this expect script see comments
in your code:


>
> I have a problem with this in expect:

spawn does not handle redirects nor should it if you
redirect the output to a file what will expect feed on?
if you want the ssh command to write to a file on the remote system
then you need to quote the spawn command like so
spawn ssh f..@123.123.123.123 \"ls -l > /tmp/mylog 2>&1\"


> spawn ssh f...@123.123.123.123 ls -l > /tmp/mylog 2>&1

If you are interested in the output then forget the redirection and
have
expect get the information.

This is a lousy way to loop use the expect command itself
set buffer ""
expect {
-i $spawn_id
-gl "Are you sure*" {
send "no\r"
# without exp_continue it breaks out
# but we always want to wait for eof
# you can always set a "bad" variable here
# to say you exited because of this reason
}
timeout {
send_user "Timeout\n"
# on timeout try to kill the spawned process this will
# not tell you why it died but you when you access the exit
status
# you will see a sigkill signal was used so something bad
happened
# you also will be able to reuse the spawn_id and prevent
zombies
exec kill -9 $pid
exp_continue; # wait for eof
}

> while (1) {
by calling exit here you exit the expect script not the spawned
process
that tells you nothing


> expect timeout { puts "get timeout\n"; exit 99} \

why are you doing this if your not sure you want to add this to your
known hosts
try to match on endings you don't want expect sending data too soon.
Change the below to :
-re {Are you sure.*\(yes/no\)\? } { send "yes\r";
exp_continue }

> "Are you sure*" { send "no\r"; break; } \

by default expect does globing since $ is not a special globbing
character are your really getting a literal '$' character output?
always specify what type of matching you wish to see and don't use
quotes if you can help it. Below translates to :
-re {ssword: $} { .....

> "*password: $" { send "$passwd\r"; continue; } \

don't use puts in an expect script always use send_user
BTW puts adds a line feed if you dont use the -nonewline option
so in the puts command below would end up with double \n's not
so with send_user

> eof { puts "get eof\n"; break;} \

eof {
send_user "got eof\n";
# lets get the data
set buffer $expect_out(buffer);
}
}
# now lets collect the exit information
# because you wait for eof you can safely call exp_wait without the
# no hang option the exitstatus variable will be a list of 4 items
# the pid the spawn_id the Signal if any , and the exit status
# spawned processes died with.
set exitstatus [ exp_wait -i $myid ];
catch { exp_close -i $myid };

Sorry but expect does not have a default this is wrong

> default { puts "get default\n"; break;};
>
> }
>
> The problem is if "ssh" failed, like the script get a dummy ip
> address, the erro message, "ssh: connect to host 123.123.123.123 port
> 22: No route to host" didn't get to /tmp/mylog. This is because
> expect think my command is
> 'spawn ssh f...@123.123.123.123 "ls -l > /tmp/mylog 2>&1" '
> but what I really want is
> 'spawn "ssh f...@123.123.123.123 ls -l" > /tmp/mylog 2>&1 '
> so I can catch the ssh error.
>
> How should I correct tghe command syntax?
>
> Eric.

Ok lets checkout the final result, I use a tcl shell and pull in
the Expect package but you can change this to just call expect
if thats what you want

#!/bin/sh
# the next line restarts using wish \
exec /opt/usr2/bin/tclsh8.5 "$0" ${1+"$@"}
if { [ catch {package require Expect } err ] != 0 } {
puts stderr "Unable to find package Expect ... adjust your
auto_path!";
}

set pid [ spawn ssh carl@spanky ls -l ]
set myid $spawn_id;
set passwd "xxxxxx"
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 buffer ""
expect {
-i $myid
-re {yes/no\)\?} { send "yes\r"; exp_continue; }
-re {word: $} { send "$passwd\r"; exp_continue; }
timeout {
senduser "get timeout\n";
exec kill -9 $pid
set bad 1
exp_continue;
}
fullbuffer {
append buffer $expect_out(buffer);
exp_continue;
}
eof {
send_user "Eof detected\r"
append buffer $expect_out(buffer);
set done 1 ;
}
}
set exitstatus [ exp_wait -i $myid ];
catch { exp_close -i $myid };
puts " exitstatus = $exitstatus"
puts "buffer\n$buffer"

------------------ END Script -----------------------
Ok lets run it I called the script exitstatus.tcl

> ./exitstatus.tcl
spawn ssh carl@spanky ls -l
exitstatus = 13550 exp4 0 0
buffer

total 10496
-rw-rw-r-- 1 carl carl 1140 2008-04-03 12:52 04032008.txt
...
-rw-rw-r-- 1 carl carl 634 2008-04-10 19:17 #x.tcl#
drwxrwxr-x 4 carl carl 4096 2007-06-19 11:26 zile

>

Bezoar

unread,
Apr 14, 2008, 8:09:35 PM4/14/08
to
On Apr 14, 7:00 pm, Bezoar <cwjo...@gmail.com> wrote:
> On Apr 14, 4:25 pm, eric5...@gmail.com wrote:
>
> > Sorry I hit the wrong key and the message just got sent. Here is a
> > rewrite:
>
> You've got several problems with this expect script see comments
> in your code:
>
> > I have a problem with this in expect:
>
> spawn does not handle redirects nor should it if you
> redirect the output to a file what will expect feed on?
> if you want the ssh command to write to a file on the remote system
> then you need to quote the spawn command like so
> spawn ssh f...@123.123.123.123 \"ls -l > /tmp/mylog 2>&1\"
One last thing. Using only one single expect loop means that their
can be no matches in your command output for the other regular
expressions. If this is possible once you send the password
then don't call exp_continue and enter into another expect loop
where only timeout, fullbuffer and eof are the targets. I should
have mentioned the fullbuffer. Sometimes the amount of data coming
back from your command is larger than expects buffer and if there
is no match it cannot empty its buffer so what's expect to do. Without
the fullbuffer expect would have to throw it away. In the example I
keep my own buffer so I can collect and append data in the event of
a fullbuffer.

HTH

Carl

0 new messages