【问题标题】:exec $SHELL executes from SSH, won't execute in playbookexec $SHELL 从 SSH 执行,不会在 playbook 中执行
【发布时间】:2016-01-07 23:28:50
【问题描述】:

我正在尝试在来宾 VM 上配置 Ruby + Rails。这是我在playbook.yml 中的内容:

---
- hosts: all
  sudo: true
  tasks:
    - apt: update_cache=yes
    - apt: name={{ item }} state=present
      with_items:
        - build-essential
        - git-core
        - zlib1g-dev
        - libssl-dev
        - libreadline-dev
        - libmysqlclient-dev
        - libyaml-dev
        - libxml2-dev
        - libxslt1-dev
        - libcurl4-openssl-dev
        - python-software-properties
        - libffi-dev
        - curl
    - command: git clone git://github.com/sstephenson/rbenv.git .rbenv
    - shell: echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    - shell: echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    - shell: exec $SHELL
    - command: git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
    - shell: echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
    - shell: exec $SHELL
    - command: git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash
    - command: rbenv install 2.2.3
    - command: rbenv global 2.2.3
    - shell: echo 'gem{{":"}} --no-ri --no-rdoc' >> ~/.gemrc
    - command: gem install bundler
    - command: add-apt-repository -y ppa:chris-lea/node.js
    - apt: update_cache=yes
    - apt: name=nodejs state=present
    - command: gem install rails -v 4.2.2
    - command: rbenv rehash

配置时,Ansible 总是在任务 - shell: exec $SHELL 处挂起并且不会返回。但是当我通过 SSH 连接到机器并运行 exec $SHELL 时,它会执行并返回。当我在我的剧本中使用 - command: exec $SHELL 时,Ansible 会打印此错误:

failed: [default] => {"cmd": "exec /bin/bash", "failed": true, "rc": 2}
msg: [Errno 2] No such file or directory

我可以确认/bin/bash 存在。

发生了什么事?我已经为此苦苦挣扎了半天了。请指教。

【问题讨论】:

    标签: bash vagrant ansible ansible-playbook


    【解决方案1】:

    首先我不建议你这样做:

    - shell: echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    - shell: echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    

    如果您碰巧多次针对主机运行此 playbook,那么您最终会在 .bashrc 文件中得到每个命令的多个实例,这是您不想要的。你应该考虑templating你的.bashrc文件,或者至少使用lineinfile之类的东西来确保这些条目只添加一次。

    就这项任务而言:

    - shell: exec $SHELL
    

    这是你根本不应该做的事情。这肯定不会产生您所期望的结果,这表明您没有完全理解任务(尤其是 shell 任务)是如何工作的。 exec 将退出的 shell 替换为指定的命令。如果您在尝试此操作时没有收到错误,那么您实际上要做的就是替换 Ansible 启动的 shell 以运行此命令。理论上会发生的是,Ansible 启动的 shell 被另一个 shell 替换,然后 Ansible 会简单地挂起,因为它正在等待 shell 终止,但是您执行的 shell 没有做任何事情,因此它永远不会终止。

    执行此任务后,您的剧本将无法继续运行。您需要 ctrl+c 来终止 ansible-playbook,或者您需要登录远程主机并终止 ansible 正在等待的 shell,此时 playbook 将由于任务失败而终止。

    切换到-command: shell $SHELL 也会失败,因为exec 是一个内置的shell 命令,但正如Ansible documentation for the command module 所述:

    给定的命令...不会通过shell处理

    由于command 模块是直接执行命令而不是通过shell,所以shell 内置的exec 将不会被识别。这就是您收到上述错误消息的原因。

    也许您应该详细说明您正在尝试做什么以及为什么您认为需要以这种方式调用exec $SHELL

    您还应该考虑更改以下任务:

     - command: gem install bundler
    

    改为使用Ansible gem module。一般来说,您希望尽可能使用内置的 Ansible 模块,并且只使用 shell/command 等作为最后的手段。内置模块提供更好的错误处理、参数验证等。

    【讨论】:

    • 哇。感谢所有这些信息,伙计。如您所知,我对 Ansible 和 bash 一无所知,我只想快速设置我的 Rails 开发环境并完成所有这些操作。我试图调整gorails.com/setup/ubuntu/14.04 上的说明以适应我的剧本,但显然我做错了。现在前进的道路很明确。谢谢!
    • @Dous:我和你有同样的错误。我还为 ruby​​ 安装了虚拟机。你能分享一下你的剧本吗?
    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2017-05-06
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    相关资源
    最近更新 更多