为什么我的 Ansible 任务挂起?

Why does my Ansible task hang?

我有以下 ansible 剧本:

- hosts: node1
  sudo: yes
  gather_facts: no

  tasks:
  - name: update apt
    apt: update_cache=yes
  - name: install python-setuptools
    apt: name=python-setuptools update_cache=yes
  - name: easy_install pexpect module
    easy_install: name=pexpect state=latest
  - name: add geonode repo
    apt_repository: repo='ppa:geonode/stable' state=present
  - name: update apt
    apt: update_cache=yes
  - name: install geonode
    apt: name=geonode update_cache=yes
  - expect:
        command: geonode createsuperuser
        responses:
          (?i)username: 'test'
          (?i)email: 'test@test.com'

当我 运行 它时,我得到:

PLAY [node1] *******************************************************************

TASK [update apt] **************************************************************
ok: [node1]

TASK [install python-setuptools] ***********************************************
changed: [node1]

TASK [easy_install pexpect module] *********************************************
changed: [node1]

TASK [add geonode repo] ********************************************************
changed: [node1]

TASK [update apt] **************************************************************
ok: [node1]

TASK [install geonode] *********************************************************

然后无限期挂起。 在远程节点 (node1) 中,我检查了目录

/home/vagrant/.ansible/tmp/ansible-tmp-1470059145.13-122191240803512/

运行里面的文件看看我的任务为什么挂了

vagrant@node1:~/.ansible/tmp/ansible-tmp-1470059145.13-122191240803512$ python apt

并得到:

{"msg": "Failed to lock apt for exclusive operation", "failed": true, "invocation": {"module_args": {"dpkg_options": "force-confdef,force-confold", "autoremove": false, "force": false, "name": "geonode", "install_recommends": null, "package": ["geonode"], "purge": false, "allow_unauthenticated": false, "state": "present", "upgrade": null, "update_cache": true, "default_release": null, "only_upgrade": false, "deb": null, "cache_valid_time": null}}}

你有什么见解吗?

编辑 1:

我启动这个脚本已经一整天了,但一直没有运行。当我发布这个问题时,很明显,脚本在 15 分钟内成功执行到结束。我今天午餐前启动它,1 小时后它仍然挂起。为什么我会得到如此不同的行为?有什么方法可以控制它吗?

此问题可能是由于 /var/lib/apt folder 为空造成的。

Vagrant 可能需要一段时间来填充这些文件夹,这可能会导致 apt 锁定。

此外,剧本效率低下,因为 update_cache 被多次使用。我建议使用这样的东西:

- hosts: node1
  sudo: yes
  gather_facts: no

  tasks:
    # Pause for 5 minutes to make sure vagrant does not hold apt lock.
    - pause:
        minutes: 5

    - name: add geonode repo
      apt_repository:
        repo: 'ppa:geonode/stable'
        state: present

    - name: Install apt packages.
      apt:
        name: "{{ item }}"
        state: present
        update_cache: true
      with_items:
        - python-setuptools
        - geonode

  - name: Create geonode superuser.
    expect:
      command: geonode createsuperuser
      responses:
        (?i)username: 'test'
        (?i)email: 'test@test.com'        

这样 Ansible 就不会在播放过程中多次更新存储库了。

由于您最后看到的是 TASK [install geonode],因此卡住了。

您要求它 运行 geonode createsuperuser 您希望它会提示您输入用户名和密码。

但可能发生的情况是该命令产生错误,并且 expect 任务没有处理错误,而是挂起。

您可以登录到您正在 运行 对其执行此操作的服务器,然后手动 运行 geonode createsuperuser 命令以查看产生了什么错误。

在我的例子中,这是由于我已经在这台机器上成功 运行 命令后用户名已经被占用的结果。

Error: That username is already taken.

即使使用 echo: yes 参数,ansible 似乎也没有传递响应以明确发生了什么。而且它不接受ignore_errors,所以似乎没有办法处理expect模块的错误。

为了解决这个问题,我在 createsuperuser 任务之后添加了另一个任务,该任务在项目中放置了一个文件,指示用户已创建一次,然后将 creates: {{ path }}/superuser_exists.txt 添加到 createsuperuser 任务中,以便它不会 运行 如果该文件已经存在。

这是一种 hack,但很简单,在模块得到更好的错误处理之前,它会很好地工作。

- name: Create the django superuser
  expect:
    command: "{{ virtualenv_path }}/bin/python3 {{ project_path }}/{{ api_app_name }}/manage.py createsuperuser"
    creates: "{{ project_path }}/{{ api_app_name }}/superuser_exists.txt"
    responses:
      (?i)username: "{{ superuser_username }}"
      (?i)email: "{{ superuser_email }}"
      (?i)password: "{{ superuser_password }}"
      (?i)again: "{{ superuser_password }}"

- name: Create a file to indicate that the superuser was already created
  file: path="{{ project_path }}/{{ api_app_name }}/superuser_exists.txt" state=touch