期望 运行 Ansible 剧本的脚本

Expect script to run Ansible playbooks

我写了一个 Ansible 剧本,提示我为 SSH 和 SUDO 交互输入密码,如下所示。

$ ansible-playbook -i test --limit dev  app_name.yml  -vv --tags=stop
SSH password:
SUDO password[defaults to SSH password]:

Ansible 有多种选项可用,例如在 group_vars 下的 ansible_ssh_password 中定义密码,但它似乎对我不起作用,因为我无法在我的目标服务器中安装 sshpass,也不能我可以对我的 sudoers 文件进行任何更改。

我尝试从下面的一个小脚本执行 ansible-playbook

#!/usr/bin/expect -f
set password PASSWORD
set where_to_execute  [lindex $argv 0]
set which_app_to_execute  [lindex $argv 1]
set what_to_execute  [lindex $argv 2]

send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute  -vv --tags=$what_to_execute \r"
expect "SSH password:"
send "$password \r"
expect "SUDO password*"
send "$password \r"
expect "$"
send "exit \r"

不幸的是,这也不起作用,可能是因为 SSH 进程不是由 expect 产生的。有没有人尝试过这种方法并使它正常工作。请建议。谢谢

它适用于我使用 expect 的 python 实现。 pexpect

使用 pip 安装 pexpect:pip install pexpect

您可以使用此代码作为 expect 脚本的解决方法:

#!/usr/bin/python
import pexpect

def main(args):

  #Setup variables
  password, where, which, what = args

  cmd = "ansible-playbook -i test --limit %s %s  -vv --tags=%s" % (where, which, what)

  child = pexpect.spawn(cmd)
  child.sendline(password)
  child.expect('SSH password:')
  child.sendline(password)
  child.expect('SUDO password*')
  child.expect(pexpect.EOF)

  print child.before


if __name__ == '__main__':
  main(sys.argv[1:])

这是最简单的示例,但对我来说效果很好。

./myscript.py mypassword dev app_name.yml stop

正如@Etan Reisner 所指出的,您的无效代码与我的预期代码之间的主要区别在于 spawn ansible 命令。上面的 expect 代码也可以正常工作:

#!/usr/bin/expect -f
spawn /usr/bin/ansible -m ping myserver --ask-pass
expect "SSH password:"
send "mypassword\r"
expect "$ "

你的 expect 脚本的问题是你实际上 运行 那里的 ansible 命令(或与此相关的任何命令)。

您使用

send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute  -vv --tags=$what_to_execute \r"

which 发送 该字符串到...据我所知无处可去。它无处可去。

想要做的是spawn执行该ansible命令,然后使用expect与其通信。

像这样:

spawn ansible-playbook -i test --limit $where_to_execute $which_app_to_execute  -vv --tags=$what_to_execute

如果 ansible 命令可能需要一些时间,您可能还想设置 timeout 值(以防止 expect 在 return 不够快时杀死它).