Ansible fails with /bin/sh: 1: /usr/bin/python: no

2020-01-27 09:26发布

I'm running into an error I've never seen before. Here is the command and the error:

$ ansible-playbook create_api.yml

PLAY [straw] ******************************************************************

GATHERING FACTS ***************************************************************
failed: [104.55.47.224] => {"failed": true, "parsed": false}
/bin/sh: 1: /usr/bin/python: not found


TASK: [typical | install required system packages] *****************************
FATAL: no hosts matched or all hosts have already failed -- aborting


PLAY RECAP ********************************************************************
           to retry, use: --limit @/Users/john/create_api.retry

104.55.47.224               : ok=0    changed=0    unreachable=0    failed=1

Here is the create_api.yml file:

---

- hosts: api
  remote_user: root
  roles:
    - api

And here is the hosts file:

[api]
104.55.47.224

I can remove the roles section and it won't make it to the first TASK, it will instead make it will only make it to the line /bin/sh: 1: /usr/bin/python: not found. What could be going on here?


NOTE: In case anyone is pinging the IP address and failing to get a response, you should know I've changed the IP address since pasting code.

EDIT python was installed locally, the problem was that it was not installed on the remote machine, which was running Ubuntu 15.04

19条回答
▲ chillily
2楼-- · 2020-01-27 09:37

By default, Ansible requires Python 2, however, Ansible 2.2+ can work with Python 3 as well.

So either install Python 2 using the raw module, e.g.

ansible localhost --sudo -m raw -a "yum install -y python2 python-simplejson"

or set ansible_python_interpreter variable in the inventory file, like:

[local]
localhost ansible_python_interpreter="env python3"

For Docker, you can add the following line:

RUN printf '[local]\r\nlocalhost ansible_python_interpreter="env python3"\r\n' > /etc/ansible/hosts

or run it as:

ansible-playbook /ansible/provision.yml -e 'ansible_python_interpreter=/usr/bin/python3' -c local
查看更多
叼着烟拽天下
3楼-- · 2020-01-27 09:39

As others said, this is due to missing python2. Other answers here provide a workaround with pre_tasks and gather_facts: no, however if you're on EC2 and you spin up the instance with ansible you can use user_data option:

- ec2:
    key_name: mykey
    instance_type: t2.micro
    image: ami-123456
    wait: yes
    group: webserver
    count: 3
    vpc_subnet_id: subnet-29e63245
    assign_public_ip: yes
    user_data: |
      #!/bin/bash
      apt-get update
      apt-get install -y python-simplejson
    register: ec2

Then people usually wait for ssh to be available like this:

  - name: "Wait for the instances to boot and start ssh"
    wait_for:
      host: "{{item.public_ip}}"
      port: 22
      delay: 5
      timeout: 300
    with_items: "{{ ec2.tagged_instances }}"
    when: ec2|changed

However I've found, that this isn't always long enough as CloudInit is executed quite late in the boot process so the python2 still might not be installed right after ssh is available. So I've added a pause in case the instance was just created:

  - name: "Wait for cloud init on first boot"
    pause: minutes=2
    when: ec2|changed

This will do the job perfectly and as an advantage you're not checking for python2 on every run and you don't have to do any workarounds to gather facts later.

I'm sure other cloud providers provide similar CloudInit functionality, so adapt for your use case.

查看更多
等我变得足够好
4楼-- · 2020-01-27 09:40

According to this Gist you can install Python2 on Ubuntu 16.04 as follows:

enter code here
gather_facts: False
pre_tasks:
  - raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
  - setup: # aka gather_facts

tasks:
  # etc. etc.
查看更多
聊天终结者
5楼-- · 2020-01-27 09:42

I found out that it's actually possible to have multiple plays in a single playbook, so my setup now contains a "dependency provisioning" play which runs on all hosts, and other plays for specific hosts. So no more pre_tasks.

For example:

- name: dependency provisioning
  hosts: all
  become: yes
  become_method: sudo
  gather_facts: false
  tasks:
    - name: install python2
      raw: sudo apt-get -y install python-simplejson

- name: production
  hosts: production_host
  roles:
    - nginx
  tasks:
    - name: update apt cache
      apt: update_cache=yes cache_valid_time=3600
  # ....

- name: staging
  hosts: staging_host
  roles:
    - nginx
  tasks:
    - name: update apt cache
      apt: update_cache=yes cache_valid_time=3600
  # ....
查看更多
Summer. ? 凉城
6楼-- · 2020-01-27 09:43

To summarize everyone else's answers, here are the combined settings that worked for me:

 - hosts: all
   become: true
   gather_facts: false

   # Ansible requires python2, which is not installed by default on Ubuntu Xenial
   pre_tasks:
     - raw: sudo apt-get -y install python-simplejson
     # action: setup will gather facts after python2 has been installed
     - action: setup
查看更多
神经病院院长
7楼-- · 2020-01-27 09:44

You need python 2.7 to run Ansible. On Ubuntu 16.04, you can install it via this command:

sudo apt-get install python-minimal

After that, I could run

ansible-playbook -i inventories/staging playbook.yml

Run ansible successfully

Please check more at Using ansible on Ubuntu 16.04

查看更多
登录 后发表回答