如何在节点假设下正确使用条件

时间:2014-01-30 17:09:00

标签: node.js expect

我有兴趣使用node-suppose而不是expect。我有时会使用期望,但我会因为处理不同的条件而感到沮丧。例如,在密码过期之前,我使用expect脚本在一组服务器上更改密码。

有些服务器可能会提示我自动更改密码,有些可能要求我运行passwd命令,有些服务器可能会在密码更改后立即远程断开会话,有些则不然。

我期待处理这种方式的方式很难看,并且在100%的时间内无法正常工作。

所以基本上我试图找到一种方法来正确使用'if'语句与假设

自述文件页面(https://github.com/jprichardson/node-suppose/blob/master/README.md)并没有真正展示我将如何做到这一点,我找不到任何其他示例。以下是github上的README.md中的示例。

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'
  })
})

编辑:我包含了一个我使用的期望脚本。这仅适用于AIX服务器。我试图创建一个同时执行AIX和Linux服务器的脚本,但我感到很沮丧,因为我无法弄清楚当服务器关闭连接时如何处理。它将完全停止脚本而不是移动到列表中的下一个服务器。显然我很沮丧,因为我再也找不到它了。

但是在这个其他的脚本中,你可以看到我是如何尝试制作类似场景的情况但是我最终不得不一遍又一遍地重复代码,因为我无法创建函数,即使是goto也会使这更容易。我必须将密码存储在环境变量中。就像我说的,它的丑陋。我宁愿花时间研究比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

3 个答案:

答案 0 :(得分:1)

这是一个简单的脚本,用于以LOGINID用户身份登录并调用" passwd"对于USERID用户。从你的剧本中,我无法理解你必须使用的情况" su - "或" pwdadm"

exp_continue的使用减少了很多代码重复。 exp_continue基本上在expect命令中循环,以便您可以等待另一个模式出现。

#!/user/bin/expect -f

set timeout 5
set fd [open $env(HOSTLIST) r]
while {[gets $fd host] != -1} {
    puts ""
    puts "################################################"
    puts "# CONNECTING TO $host #"
    puts "################################################"

    spawn /usr/bin/ssh $env(LOGINID)@$host

    expect {
        "yes/no" {
            send "yes\r"
            exp_continue
        }
        "assword:" {
            send "$env(PASSWDU)\r"
            exp_continue
        }
        "ssh: Could not resolve hostname" {
            puts "Could not resolve hostname!!!\nmoving to the next host in the list\n"
            continue
        }
        timeout {
            puts "Request timed out!!!\nmoving to the next host in the list\n"
            continue
        }
        -re {\$\s*$}
    }

    send "passwd $env(USERID)\r"

    expect {
        "Old password:" {
            send "$env(PASSWDU)\r"
            exp_continue
        }
        -re "New password:|again:|Re-enter" {
            send "$env(PASSWDTEMP)\r"
            exp_continue
        }
        -re {\$\s*$}
    }

    send "exit\r"
    expect eof
}

答案 1 :(得分:1)

如果您已经在使用node.js,则应该使用ssh2而不是使用类似于期望的脚本来连接到ssh服务器。

编辑:此外,您应该考虑使用公钥身份验证而不是密码,无论是直接使用密钥还是通过ssh-agent等代理使用密码。

答案 2 :(得分:1)

node-suppose的作者......

不幸的是,node-suppose不支持条件。我与expect的比较可能比较差,因为它不支持很多expect功能。但是,将来它可能会支持条件。我在这里发布了一个问题来引用它:https://github.com/jprichardson/node-suppose/issues/7