I have an interest in using node-suppose instead of expect. I use expect sometimes but i get frustrated trying to deal with different conditions. For example, I use an expect script to change my passwords on a group of servers before my passwords expire.
Some servers might prompt me to change my password automatically, some might require me to run the passwd command, some might disconnect the session remotely immediately following the password change, some don't.
The way I deal with this in expect is ugly and doesn't work correctly 100% of the time.
So basically I am trying to find a way to properly use 'if' statements with suppose
The readme page (https://github.com/jprichardson/node-suppose/blob/master/README.md) doesn't really show how I would do this and I can't find any other examples. Here is the example in the README.md on github.
var suppose = require('suppose')
, fs = require('fs')
, assert = require('assert')
process.chdir('/tmp/awesome');
fs.writeFileSync('/tmp/awesome/README.md', 'READ IT')
suppose('npm', ['init'])
.debug(fs.createWriteStream('/tmp/debug.txt')) //optional writeable output stream
.on(/name\: \([\w|\-]+\)[\s]*/).respond('awesome_package\n')
.on('version: (0.0.0) ').respond('0.0.1\n')
.on('description: ').respond("It's an awesome package man!\n")
.on('entry point: (index.js) ').respond("\n")
.on('test command: ').respond('npm test\n')
.on('git repository: ').respond("\n")
.on('keywords: ').respond('awesome, cool\n')
.on('author: ').respond('JP Richardson\n')
.on('license: (BSD) ').respond('MIT\n')
.on('ok? (yes) ' ).respond('yes\n')
.error(function(err){
console.log(err.message);
})
.end(function(code){
var packageFile = '/tmp/awesome/package.json';
fs.readFile(packageFile, function(err, data){
var packageObj = JSON.parse(data.toString());
console.log(packageObj.name); //'awesome_package'
})
})
EDIT: I'm including an expect script I use. This only works on AIX servers. I tried to make a script that did both AIX and Linux servers but I got frustrated because I couldn't figure out how to handle when the server closes the connection. It would completely stop the script instead of moving on to the next server in the list. Apparently I was so frustrated I deleted it because I can't find it anymore.
But in this other script, you can see how I am trying to make case like scenarios but I end up having to repeat code over and over because I can't make functions, even a goto would make this easier. And I have to store passwords in environment variables. Like I said, its ugly. I would much rather spend time working on more modern stuff than TCL.
#!/usr/bin/expect -f
#
# set some variables
set timeout 5
set ::logfile [open ./AIX_password_update.log a]
set stamp [clock format [clock seconds] -format {%Y-%m-%d-%T}]
#start task
puts "\n\n\n"
puts "$stamp\nStarting!\nLog file AIX_password_update.log"
puts "\n\n"
#prepare host list for processing
set fd [open $env(HOSTLIST) r]
set hosts [read -nonewline $fd]
close $fd
foreach host [split $hosts "\n" ] {
#connect to host and start sending commands
spawn /usr/bin/ssh $env(LOGINID)@$host
set stamp [clock format [clock seconds] -format {%Y-%m-%d-%T}]
puts "\n############################"
puts "## Connecting to $host ##"
puts "############################"
#deal with SSH client and log in if needed
expect {
"yes/no" {
send "yes\r"
expect {
"password:" {
send "$env(PASSWDU)\r"
expect {
"ermission denied" {
puts "Permission Denied!!!\nmoving on to the next host in the list\n"
puts $::logfile "$stamp - $host - Permission denied, wrong password for $env(LOGINID)"
continue
}
}
}
}
}
}
#deal with SSH/DNS/Network problems and log in if needed
expect {
"ssh: Could not resolve hostname" {
puts "Could not resolve hostname!!!\nmoving to the next host in the list\n"
puts $::logfile "$stamp - $host - Could not resolve hostname"
continue
}
timeout {
puts "Request timed out!!!\nmoving to the next host in the list\n"
puts $::logfile "$stamp - $host - Request timed out"
continue
}
"password:" {
send "$env(PASSWDU)\r"
expect {
"ermission denied" {
puts "Permission Denied!!!\nmoving on to the next host in the list\n"
puts $::logfile "$stamp - $host - Permission denied, wrong password for $env(LOGINID)"
continue
}
}
}
"\\$" {
}
}
#make sure this is an AIX server, skip if it is not
send "uname\r"
expect {
"Linux" {
set uname Linux
}
"AIX" {
set uname AIX
}
}
if { $uname != "AIX" } {
puts "This server is not AIX!!!\nmoving on to the next host in the list"
puts $::logfile "$stamp - $host - Not AIX"
continue
}
#su to root
expect {
"\\$" {
send "su -\r"
expect {
"assword:" {
send "$env(ROOTPW)\r"
expect eof
puts $::logfile "$stamp - $host - su to root success"
}
}
}
}
#detect root prompt and change the password for the user
expect {
"#" {
send "\r"
send "passwd $env(USERID)\r"
expect {
"New password:" {
send "$env(PASSWDN)\r"
expect {
"Re-enter" {
send "$env(PASSWDN)\r"
expect eof
send "pwdadm -c $env(USERID)\r"
expect eof
puts $::logfile "$stamp - $host - Password changed for $env(USERID)"
puts "$stamp - $host - Password changed for $env(USERID)"
}
"again" {
send "$env(PASSWDN)\r"
expect eof
send "pwdadm -c $env(USERID)\r"
expect eof
puts $::logfile "$stamp - $host - Password changed for $env(USERID)"
puts "$stamp - $host - Password changed for $env(USERID)"
}
}
}
}
}
"root" {
send "\r"
send "passwd $env(USERID)\r"
expect {
"New password:" {
send "$env(PASSWDN)\r"
expect {
"Re-enter" {
send "$env(PASSWDN)\r"
expect eof
send "pwdadm -c $env(USERID)\r"
expect eof
puts $::logfile "$stamp - $host - Password changed for $env(USERID)"
puts "$stamp - $host - Password changed for $env(USERID)"
}
"again" {
send "$env(PASSWDN)\r"
expect eof
send "pwdadm -c $env(USERID)\r"
expect eof
puts $::logfile "$stamp - $host - Password changed for $env(USERID)"
puts "$stamp - $host - Password changed for $env(USERID)"
}
}
}
}
}
}
expect eof
}
expect eof