Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can someone please post some examples of how to to make this code work

Status
Not open for further replies.

codescripter5

Technical User
Jun 3, 2003
2
US
Example expect script post, that has missing code.
The concept is exactly what ive been trying to accoplish, but there are parts missing to the cause/and if statement checks. Could anyone tell me how to do those checks in expect? I want to know what happened in the code when a spawn ssh fails in a loop and for it not to error out and quit over one host problem. I cant find any complete examples on debuggine spawn and su in a expect loop like this.


A basic overview of what this script is doing is in order.
First it spawns an ssh session to host/hosts, su - to root, runs a
simple command to stop/kill a process then restart it.
The command run to restart the process works from the command line on
the servers themselves.
Copy of restart command that is called by the expect script.

#!/bin/sh
cd /opt/prfmgr/prfmgr/bin
./hepm-shutdown.csh
sleep 3
ps -ef |grep jmq |awk '{print $2}' |xargs kill -9
sleep 1
ps -ef |grep DSPIRIT |awk '{print $2}' |xargs kill -9
sleep 1
ps -ef |grep PingApmSer |awk '{print $2}' |xargs kill -9
sleep 1
./hepm-startup.csh
sleep 3
cd /opt/SpiritWave4_31/bin
nohup jmq &
sleep 2
cd /opt/prfmgr/scripts
./KeepAlive.sh
sleep 2

When i run the expect script it logs into the machine/machines in
question and will su with success. The restart command has to be run
as the specific user, so in order to call the restart script, i call a
simple script that executes
su - prfmgr -c "/opt/prfmgr/scripts/apmrestart.sh"
this also works from the command line, but when the expect script
calls this script it shuts down the processes, kills them if they
hang, restarts everything sucessfully, (in the script is a ps -ef
|egrep "all|the|process|names" that returns and shows sucessful
restart. But it seems that when the script exits, it kills the
processes it just started up. Is there anyway to keep this from
happening? I've attatched the important parts of the script (sans
passwords of course). If anyone can see why this would happen please
let me know.



proc restart_apm {} {

global ssh_id DEBUG

# Return code constants
set SUCCESS 0
set EFAIL 1
set ETIME 255 ;# Interaction timedout

set timeout 30
set return_value -1

# Login responses
set root_prompt "# "
set password_prompt "Password:"
set sorry "Sorry, try again."
set no_access "is not in the sudoers file.*"
set syntax_err "sudoers file: syntax error*"

# Commands
set restart "/root/apmstart.sh"
set ps "/root/prfmgr-ps.sh"

send -i $ssh_id "$restart\n"
expect -i $ssh_id -re "$root_prompt"
send -i $ssh_id "$ps\r"
expect {
-i $ssh_id "dstb.utils.PingApmSer" {
set return_value $SUCCESS
}

} ;# end expect
expect -i $ssh_id -re "$root_prompt"
return $return_value
} ;# end restart_apm

########
# #
# MAIN #
# #
########

foreach host $hosts {
set timeout 30
if { $DEBUG == 1} {
exp_internal 1
}
# make sure host is pingable
if { $DEBUG == 0} {
log_user 0
}

# Start SSH process
spawn /opt/local/bin/ssh -l biscadm $host; set ssh_id $spawn_id
if { $DEBUG == 1} {
exp_internal 1
}
if { $DEBUG == 0} {
log_user 0
}

# Execute login procedure
set return_code [ssh_login 0]
switch -- $return_code 0 {
# If this is the final host status, we failed further down
# but did not catch it.
set status($host) "ssh: Successfully logged in"
} 1 {
set status($host) "FAILED: ssh: Known password(s) did not work"
close -i $ssh_id; wait -i $ssh_id
continue
} 2 {
set status($host) "FAILED: ssh: Authentication failed: account does not exist"
close -i $ssh_id; wait -i $ssh_id
continue
} 3 {
set status($host) "FAILED: ssh: Connection Refused: SSH not running or not
allowed"
close -i $ssh_id; wait -i $ssh_id
continue
} 4 {
set status($host) "FAILED: ssh: SecurID prompt: requires interactive login"
close -i $ssh_id; wait -i $ssh_id
continue
} 255 {
# This is here just in case. This status should not show
# up. We should be collecting something more specfic
# than a timeout.
set status($host) "FAILED: ssh: timeout (unexpected response)"
close -i $ssh_id; wait -i $ssh_id
continue
} default {
# This is BAD. The script should NEVER end up here.
set status($host) "ERROR: ssh: check script (unknown return
code)"
close -i $ssh_id; wait -i $ssh_id
continue
}

if { $DEBUG == 0} {
log_user 1
}

# Should be at a prompt at this point so send su
set return_code [su_to_root 0]
switch -- $return_code 0 {
# If this is the final host status, we failed further down
# but did not catch it.
set status($host) "su: OK"
} 1 {
set status($host) "FAILED: su: Known password(s) did not work"
close -i $ssh_id; wait -i $ssh_id
continue
} 2 {
set status($host) "FAILED: su: No root account or bad passwd
file"
close -i $ssh_id; wait -i $ssh_id
continue
} 255 {
# This is here just in case. This status should not show
# up. We should be collecting something more specfic
# than a timeout.
set status($host) "FAILED: su: timeout (unexpected response)"
close -i $ssh_id; wait -i $ssh_id
continue
} default {
# This is BAD. The script should NEVER end up here.
set status($host) "ERROR: su: check script (unknown return
code)"
close -i $ssh_id; wait -i $ssh_id
continue
}

# Should be at a root prompt at this point so send restart
# Restart apm processes
set return_code [restart_apm]
switch -- $return_code 0 {
set status($host) "SUCCESS"
} 1 {
set status($host) "FAILED: restart_prfmgr: prfmgr failed to
restart"
close -i $ssh_id; wait -i $ssh_id
continue
} 2 {
set status($host) "FAILED: restart_prfmgr:
/opt/prfmgr/scripts/apmrestart.sh: command not found"
close -i $ssh_id; wait -i $ssh_id
continue
} 255 {
# This is here just in case. This status should not show
# up. We should be collecting something more specfic
# than a timeout.
set status($host) "FAILED: restart_prfmgr: timeout (unexpected
response)"
close -i $ssh_id; wait -i $ssh_id
continue
} default {
# This is BAD. The script should NEVER end up here.
set status($host) "ERROR: restart_prfmgr: check script
(unknown return code)"
close -i $ssh_id; wait -i $ssh_id
continue
}

if { $DEBUG == 0} {
log_user 0
}

#expect -i $ssh_id "$ "

send -i $ssh_id "exit\r"
expect -i $ssh_id -re $prompt
close -i $ssh_id; wait -i $ssh_id
} ;# end foreach host $hosts

puts "\n\n\nHost: Status:"
puts "-------------------------------------------------------------"
#Print the status of all hosts
foreach host [array names status] {
if { $host != "" } {
set line [format "%-30s%-s" $host $status($host)]
puts "$line\n"
}
}
 
Basically what I need to know is how to capture the status code of spawn ssh so I know if there was a problem and can translate those to human readable errors. Then act accordingly
 
Expect is tcl, you can use catch.
Code:
   if {![catch {spawn su $opts} err_spawn]} {
       rest of script here..
   } else {
       error "$err_spawn"
   }

You can also test for eof on your spawn_id periodically
if that's your problem. I confess I didn't
look real closely at the code.

Something like
Code:
proc checkUp {id interval} {
  if {![eof $id]} {
     after $interval {checkUp $id}
  } else {
     error "$id reports error: eof"
  }
}

spawn ssh $opts
checkUp $spawn_id 30000
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top