期望 运行 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 不够快时杀死它).
我写了一个 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 不够快时杀死它).