尽管用 CentOS 的人多,但我是推崇 Ubuntu Server,简洁易用,包管理可靠稳健。

但是,用 ubuntu server xenial 或以上的版本,就会遇到一个新装的系统,无法执行 ansible 的问题。因为 ubuntu xenial 以上版本已经默认使用 python3 了。通常的解决方法就是安装 python-minimal 包。

最近设计一套 ansible 脚本时,预设的环境是离线内网集群,那么如何解决这个问题呢?我编写了一个初始化 playbook 代码。

以下我的 hosts 内容,ubuntu_hosts是空的:

[servers]
centos7 ansible_host=192.168.1.146 ansible_ssh_port=22
ubuntu16 ansible_host=192.168.3.231 ansible_ssh_port=22

[ubuntu_hosts]

以下我的 playbook 内容:

- hosts: all
  become: yes
  gather_facts: no
  tasks:
    - include_role:
        name: init
        tasks_from: check_python.yml

- hosts: all
  become: yes
  roles:
    - init

我们来看看 init 里的 check_python.yml 做了什么动作:

- block:
    - name: checking python2
      raw: test -e /usr/bin/python
      changed_when: false
      when: ansible_python_interpreter is not defined
  rescue:
    - name: checking python3
      raw: test -e /usr/bin/python3
      changed_when: false
    - name: add host into group 'ubuntu_hosts'
      lineinfile:
        path: hosts
        line: '{{ inventory_hostname }} ansible_python_interpreter=/usr/bin/python3'
        insertafter: '\[ubuntu_hosts\]'
        state: present
      delegate_to: localhost
      become: no
    - meta: clear_host_errors
    - meta: refresh_inventory

- block:
    - name: checking python3
      raw: test -e /usr/bin/python3
      changed_when: false
      when: ansible_python_interpreter is defined
  rescue:
    - name: checking python2
      raw: test -e /usr/bin/python
      changed_when: false
    - name: remove host from group 'ubuntu_hosts'
      lineinfile:
        path: hosts
        line: '{{ inventory_hostname }} ansible_python_interpreter=/usr/bin/python3'
        state: absent
      delegate_to: localhost
      become: no
    - meta: clear_host_errors
    - meta: refresh_inventory
  1. 首先检查是否有 python 命令。
  2. 如果检查失败,那么执行 resuce 部分的 tasks,把这台机器写入到 hosts 文件里,指定使用 python3 作为交互命令。
  3. 清除错误,刷新 inventory 列表。为之后的动作扫清障碍。
  4. 下一个 block 则是反过来操作。解决在使用云主机的场景里,用户可能会更换操作系统的问题。

这样我们就得到了一个新的 hosts 列表:

[servers]
centos7 ansible_host=192.168.1.146 ansible_ssh_port=22
ubuntu16 ansible_host=192.168.3.231 ansible_ssh_port=22

[ubuntu_hosts]
ubuntu16 ansible_python_interpreter=/usr/bin/python3

以下是输出截图
Screenshot_2018-03-01_15-14-26

原本我是用了个偷懒的方法,直接在 Ubuntu Xenial 上建一个软链 /usr/bin/python 指向 /usr/bin/python3 的,也能解决 ansible 的执行问题。但考虑到这样可能会给以后运行其它 python 应用挖坑,所以还是稍微折腾一下,确保我们不改动系统级别的命令工具。