Linux 在expect脚本中使用if/else

Linux 在expect脚本中使用if/else,linux,expect,Linux,Expect,我最近更新并重新格式化了我的/etc/hosts文件,并希望通过每个系统(大约1000个)来刷新我已知的_hosts文件。我正在考虑使用expect脚本向RSA指纹问题发送“是”。很简单。然而,我知道其中一些系统对我来说是全新的,我的密码还没有设置。这创造了两种可能性: “是”发送到RSA指纹问题,我已登录 服务器。然后我需要发送一个出口来关闭连接 在移动到下一个主机之前。或者 “是”被发送到RSA指纹问题,我收到 提示从当前密码和密码开始更新我的密码 然后输入两次新密码。连接将 更新密码后自动

我最近更新并重新格式化了我的/etc/hosts文件,并希望通过每个系统(大约1000个)来刷新我已知的_hosts文件。我正在考虑使用expect脚本向RSA指纹问题发送“是”。很简单。然而,我知道其中一些系统对我来说是全新的,我的密码还没有设置。这创造了两种可能性:

  • “是”发送到RSA指纹问题,我已登录 服务器。然后我需要发送一个出口来关闭连接 在移动到下一个主机之前。或者

  • “是”被发送到RSA指纹问题,我收到 提示从当前密码和密码开始更新我的密码 然后输入两次新密码。连接将 更新密码后自动关闭移动到 下一位主持人

  • 我想我已经基本掌握了expect中“if/else”的概念,但我不完全理解如何嵌套它们,是否有更好的方法,或者是否一开始就完全偏离了基准

    这就是我现在拥有的:

    set file1 [open [lindex $argv 0] r]
    
    set pw1 [exec cat /home/user/.pw1.txt]
    set pw2 [exec cat /home/user/.pw2.txt]
    
    while {[gets $file1 host] != -1} {
    
        puts $host
        spawn -noecho "ssh $host"
        expect {
            "continue connecting"{
                send "yes\r"
                expect {
                    "current" {
                        send $pw2\r
                    } "New password" {
                        send $pw1\r
                    } "Retype new password" {
                        send $pw1\r
                    }
                }
            expect "msnyder"
            send "exit\r"
        }
        interact
    }
    
    file1变量是要运行脚本的主机列表


    我知道它不准确,因为它在第22行出错。但是,我不知道需要修复什么。

    您可能可以避免让脚本像人一样运行,而只是生成一个预期会失败的ssh连接,该连接将自动接受主机RSA密钥,而无需提示输入密码;稍后,对于需要启动密码的新系统,您可以这样做

    暂时尝试将其添加到~/.ssh/config文件中,直到脚本完成:

    Host *
      Protocol 2
      PasswordAuthentication 0
      StrictHostKeyChecking 'no'
      CheckHostIP 'no'
      UserKnownHostsFile ~/.ssh/known_hosts_new
    

    然后当新的know_hosts_新文件加载时,您可以替换默认的~/.ssh/known_主机,并从配置中删除UserKnownHostsFile行。

    您可以避免让脚本像人一样运行,只需生成一个预期会失败的ssh连接,该连接将自动接受主机RSA密钥,而无需提示密码;稍后,对于需要启动密码的新系统,您可以这样做

    暂时尝试将其添加到~/.ssh/config文件中,直到脚本完成:

    Host *
      Protocol 2
      PasswordAuthentication 0
      StrictHostKeyChecking 'no'
      CheckHostIP 'no'
      UserKnownHostsFile ~/.ssh/known_hosts_new
    
    然后,当加载新的known\u hosts\u新文件时,您可以替换默认的~/.ssh/known\u hosts,并从配置中删除userknown hosts文件行。

    我发现了两个错误:

  • 缺少闭合大括号,可能用于“继续连接”块
  • “继续连接”的大括号前缺少空格。Tcl(因此Expect)对空格非常敏感,因为它在计算命令之前被解析为单词。有关极少数血淋淋的细节,请参阅
  • 您的代码可能如下所示:

    while {[gets $file1 host] != -1} {
        puts $host
        spawn -noecho "ssh $host"
        expect {
            "continue connecting" {
                send "yes\r"
                expect {
                    "current" {
                        send -- $pw2\r
                        exp_continue
                    } 
                    "New password" {
                        send -- $pw1\r
                        exp_continue
                    } 
                    "Retype new password" {
                        send -- $pw1\r
                        exp_continue
                    }
                    msnyder
                }
                send "exit\r"
            }
        }
        interact
    }
    
    注:

    • exp\u continue
      用于“循环”到
      expect
      语句:在这种情况下,您将看到所有的“当前”、“新建”和“重新键入”,因此在看到提示之前,您不想退出
    • 养成键入
      send--something
      的习惯。如果没有双破折号,当有人用前导破折号输入密码时,你会感到惊讶
        我发现了两个错误:

      • 缺少闭合大括号,可能用于“继续连接”块
      • “继续连接”的大括号前缺少空格。Tcl(因此Expect)对空格非常敏感,因为它在计算命令之前被解析为单词。有关极少数血淋淋的细节,请参阅
      • 您的代码可能如下所示:

        while {[gets $file1 host] != -1} {
            puts $host
            spawn -noecho "ssh $host"
            expect {
                "continue connecting" {
                    send "yes\r"
                    expect {
                        "current" {
                            send -- $pw2\r
                            exp_continue
                        } 
                        "New password" {
                            send -- $pw1\r
                            exp_continue
                        } 
                        "Retype new password" {
                            send -- $pw1\r
                            exp_continue
                        }
                        msnyder
                    }
                    send "exit\r"
                }
            }
            interact
        }
        
        注:

        • exp\u continue
          用于“循环”到
          expect
          语句:在这种情况下,您将看到所有的“当前”、“新建”和“重新键入”,因此在看到提示之前,您不想退出
        • 养成键入
          send--something
          的习惯。如果没有双破折号,当有人用前导破折号输入密码时,你会感到惊讶
        在这种规模的环境中,RSA指纹旁路通常是个好主意。尽管如此,我不认为我会把它推荐给那些不完全信任的环境。谢谢你的建议。不过,我必须解决其余问题,以处理需要更改密码的系统。这可能是一个更简单的解决方案,因为它的if/else嵌套更少。在这种规模的环境中,RSA指纹旁路通常是一个好主意。尽管如此,我不认为我会把它推荐给那些不完全信任的环境。谢谢你的建议。不过,我必须解决其余问题,以处理需要更改密码的系统。这可能是一个更简单的解决方案,因为它没有那么多嵌套的if/else来处理。谢谢。在运行代码之前,我会仔细检查代码,以便了解它在做什么,以及将来如何实现类似的方法。我意识到的一件事是,我现在有两个系统不需要RSA指纹就可以被接受。此脚本是否假定将询问它?如果它没有出现并直接下降到远程服务器上的命令提示符,该块是否会短路并从msnyder块发送“exit”?似乎我只需要将它向上移动一个级别,成为“继续连接”“如果”下的“其他”。这是正确的吗?或者我可能在两个地方需要它:一次是在接受RSA指纹(如果提供)之后,另一次是在我已经接受RSA指纹的情况下替代它。我运行了脚本。我想我看到了一些可以改变我的方法的变化,但是我“我在这方面遇到了问题。我可能会考虑这个问题,并提出另一个问题与新的问题,以保持分离的问题。谢谢。在运行代码之前,我会仔细检查代码,以便了解它在做什么,以及将来如何实现类似的方法。我意识到的一件事是,我现在有两个系统不需要RSA fingerpr