使用expect脚本 服务器自动登陆部署

之前写过一篇blog,使用公钥和私钥来实现自动登录,后来发现这种方式有一些局限性,比如说服务器设置了用户权限,不允许root用户直接登录,而其它用户又没有~/.ssh的权限,又或者使用了跳转机等。每次登录都要复制两次密码来登录,很是麻烦,后来google了一下,了解了一下expect,来实现服务器的自动登录、跳转、部署等。

1.Expect用途

Expect是一个用来处理交互的命令。借助Expect,我们可以将交互过程写在一个脚本上,使之自动化完成。形象的说,ssh登录,ftp登录等都符合交互的定义。

2.expect的安装

1
2
brew install expect #mac
apt-get install expect #ubuntu

3.介绍一下我碰到的实际问题,以及写好的脚本。服务器A,有root用户以及test用户,服务器A只允许test用户登录,并且服务器上很多服务是用root安装的,需要用test用户登录,然后在切换到root来执行服务器部署操作命令。

  • 3.1.本地的登录服务器脚本 test.exp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/usr/bin/expect
    set timeout 15
    spawn ssh test@192.168.1.300
    expect {
    "(yes/no)" { send "yes\r"; exp_continue }
    "*assword:" { send "test password\r" }
    }
    send "su - root \r"
    expect {
    "*assword:" { send "root password\r"}
    }
    send "yun\r"
    interact

其中,expect判断返回的信息,如果有匹配的就直接执行相应得命令,如果一直匹配不到,当timeout时间超过之后才会继续执行。send是要执行的命令。interact是交互模式,用户会停留在服务器A上。

  • 3.2.新建的exp脚本要设置成可执行文件

    1
    chmod +x test.exp
  • 3.3.然后就可以直接执行,这个时候就会直接登录到服务器A

    1
    ./text.exp
  • 3.4.我们登录到服务器上大部分都是执行重新部署命令,可以参考一下我的rails、nginx自动部署。服务器A上有脚本 a.sh

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash
    cd /project/
    git pull origin master
    bundle
    bundle exec rake assets:precompile RAILS_ENV=production
    bundle exec rake db:migrate RAILS_ENV=production
    god restart nginx
  • 3.5.这个时候我们在重新创建一个本地的expect服务器部署脚本。为test_restart.exp,登录到服务器A,然后执行脚本a.sh,部署完成后退出。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/usr/bin/expect
    set timeout 200
    spawn ssh test@192.168.1.300
    expect {
    "(yes/no)" { send "yes\r"; exp_continue }
    "*assword:" { send "test password\r" }
    }
    send "su - root \r"
    expect {
    "*assword:" { send "root password\r"}
    }
    expect "~#"
    send "/shell/a.sh\r"
    expect "nginx"
    send "exit\r"
    send "exit\r"
    expect eof ;

因为编译和migrate的时间可能会有点长,所以这里设置timeout为200。

  • 3.6.这个时候本地直接执行脚本就会自动部署。

    1
    ./test_restart.exp
  • 3.7.当然为了更方便,我们还可以设置alias设置永久别名。

首先你要看下你用的是什么shell,执行 echo $shell。

1
2
3
bash 配置 '~/.bashrc'
csh 配置 '~/.cshrc'
zsh 配置 '~/.zshrc'

比如我用的zsh,vi ~/.zshrc,在后面添加。

1
2
alias test='./test.exp'
alias test_restart='./test_restart.exp'

  • 3.8.这个时候无论在哪个目录,只要执行命令就可以直接登录,部署。跳转机的和此类似

    1
    2
    test #登录服务器
    test_restart #部署

参考链接1 mac terminal的一些困惑
参考链接2 expect - 自动交互脚本