Ansible失败,出现/ bin / sh:1:/ usr / bin / python:找不到


187

我遇到了从未见过的错误。这是命令和错误:

$ 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

这是create_api.yml文件:

---

- hosts: api
  remote_user: root
  roles:
    - api

这是主机文件:

[api]
104.55.47.224

我可以删除角色部分,但不会进入第一个任务,而是使其仅进入第一个任务行/bin/sh: 1: /usr/bin/python: not found。这可能是怎么回事?


注意:万一任何人都无法ping通IP地址并且无法获得响应,您应该知道自粘贴代码以来我已经更改了IP地址。

EDIT python是本地安装的,问题是它没有安装在运行Ubuntu 15.04的远程计算机上

Answers:


171

我偶然发现这个错误 Ubuntu 15.10服务器,因为它是Python 3.4.3附带的,而ansible需要Python 2

这是我provision.yml现在的样子:

- hosts: my_app
  sudo: yes
  remote_user: root
  gather_facts: no
  pre_tasks:
    - name: 'install python2'
      raw: sudo apt-get -y install python

  tasks:
    - name: 'ensure user {{ project_name }} exists'
      user: name={{ project_name }} state=present
  • 不要忘记使用apt-get的-y(对所有问题都回答是)选项(否则原始模块将被静默卡住)

  • gather_facts: no 行也很关键(因为没有python我们无法收集事实)


12
因此,后续角色无法使用事实...是否有办法再次收集事实?啊哈,stackoverflow.com
questions/31054453/…

16
请注意,“ gather_facts:no”这一行很关键。
rcreswick

6
@ surfer190很棒的发现!我还发现,将action: setup作为最终pre_task也很好工作:)
mrooney

1
@ surfer190如果在ansible中使用EC2,请在这里查看我的答案,可以使用CloudInit安装python2,以便可以照常使用收集事实。
米罗斯拉夫

1
如果有人也想知道,则无需运行该raw任务即可在中安装Python 2 pre_tasks。常规也tasks很好。但是,将它pre_tasks与另一个任务一起调用Ansible setup模块,将确保事实可用于分配给主机的任何角色。
肯尼·埃维特

125

Ansible 2.2具有对Python 3支持的技术预览。要利用此优势(因此您不必在Ubuntu 16.04上安装Python 2),只需将ansible_python_interpreterconfig选项设置为即可/usr/bin/python3。可以在清单文件中按主机进行此操作:

[db]
123.123.123.123 ansible_python_interpreter=/usr/bin/python3

我尝试将/ usr / bin / python添加到此变量,但是没有用。添加python3反而有效,此问题已得到解决
Deep LF

98

解决方案1:

如果您使用Ansible >2.2.0,则可以将ansible_python_interpreter配置选项设置为/usr/bin/python3

ansible my_ubuntu_host -m ping -e 'ansible_python_interpreter=/usr/bin/python3'

或在您的库存文件中:

[ubuntu_hosts]
<xxx.xxx.xxx.xxx>

[ubuntu_hosts:vars]
ansible_python_interpreter=/usr/bin/python3

解决方案2:

如果您正在使用,Ansible <2.2.0则可以将它们添加pre_tasks到您的剧本中:

gather_facts: False
pre_tasks:
  - name: Install python for Ansible
    raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
    register: output
    changed_when: output.stdout != ""
    tags: always
  - setup: # aka gather_facts

UPDATE 使用ansible 2.8.x,您无需担心,它对于python> 3.5的控制器和目标机器都是开箱即用的


如果您使用标签运行您的剧本,请确保添加标签:始终添加到设置任务中-否则在使用标签时ansible不会收集事实。
Ionut Bajescu

16
我有ansible 2.3.0.0,但没有开箱即用。与OP发布的错误相同。
编码员

如果不清楚,则必须将其添加到主机清单文件中,而不是添加到包含的变量中,即,它与主机地址/名称位于相同的清单文件中。
肖恩·梅汉

32

您可以使用raw模块在远程主机上安装Python:

- raw: sudo apt-get install python-simplejson

11
为确保在角色任务之前以及元文件中的任何依赖项之前调用此方法,请将其添加到您的剧本中: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld 2015年

5
请注意,在剧本中,您必须禁用collect_facts,否则在运行raw命令之前这将失败。(gather_facts:no)
rcreswick

@rcreswick那是我的问题,您的解决方案对我有用。非常感谢。我在主.yml文件(setup-ansible.yml)中放入“ gather_facts:no”行,并使用以下命令执行了剧本:“ ansible-playbook -i托管setup-ansible.yml --flush-cache -vvvvvv -kK ”。我在ansible-playbook中使用了“ -kK”选项,因为默认的ubuntu安装需要密码才能执行“ sudo”。
Ali Yousefi Sabzevar

为什么要安装simplejson而不是pytghon,但要谈论安装python?
亨宁

@Henning python-simplejson用Python编写,因此需要Python。大多数大多数Ansible核心模块都需要simplejson。python-simplejson通过apt-get/ 安装,yum您还将安装Python,因此涵盖了所有基本的Ansible依赖项……
udondan

18

总结其他所有人的答案,以下是对我有用的组合设置:

 - 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

14

我个人发现了针对此问题的3种可能的解决方案,它们在不同情况下均能很好地起作用:

选项1- ansible_python_interpreter: /usr/bin/python3python3默认安装的主机设置

我认为,如果可以python3通过默认情况下是否安装主机来对主机分组,则这是解决该问题的上乘方法。据我所知,python3它在所有Ubuntu 16.04及更高版本中均可用。

  • 如果您的所有主机都肯定有python3,则可以将变量添加到您的group_vars/all.yml(或等效变量)中:
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • 如果您的某些主机没有,python3并且您可以在使用动态清单时对它们进行标记(例如,对AWS进行AWS标记ec2.py),则可以将变量应用于某些主机,如下所示:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • 如果您使用静态清单,并且能够根据主机是否具有对主机进行分组python3,则可以执行以下操作:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

[python3_hosts:vars]
ansible_python_interpreter=/usr/bin/python3

我最喜欢此选项,因为它不需要在远程主机上进行任何更改,而只需对变量进行较小的更改,而选项2和3则需要对每个剧本进行添加。

选项2-使用以下命令安装Python 2 raw

此选项需要把一个戏在每剧本的顶部gather_facts: false,使用raw安装python

- name: install python2 on all instances
  hosts: "*"
  gather_facts: false
  tasks:
    - name: run apt-get update and install python
      raw: "{{ item }}"
      loop:
        - sudo apt-get update
        - sudo apt-get -y install python
      become: true
      ignore_errors: true

ignore_errors: true如果您打算在尚未apt-get安装的主机(例如,基于RHEL的任何主机)上运行该播放,则是必需的,否则它们将在第一次播放中出错。

此解决方案有效,但由于某些原因,它是我列出的最低解决方案:

  1. 需要放在每个剧本的顶部(与选项1相对)
  2. 假设apt在系统上并且忽略错误(与选项3相反)
  3. apt-get 命令很慢(与选项3相反)

选项3- /usr/bin/python -> /usr/bin/python3使用符号链接raw

我还没有看到其他人提出过这种解决方案。这并不理想,但是我认为它在很多方面都优于选项2。我的建议是,如果系统上没有则使用raw运行shell命令进行符号链接:/usr/bin/python -> /usr/bin/python3python3 python

- name: symlink /usr/bin/python -> /usr/bin/python3
  hosts: "*"
  gather_facts: false
  tasks:
    - name: symlink /usr/bin/python -> /usr/bin/python3
      raw: |
        if [ -f /usr/bin/python3 ] && [ ! -f /usr/bin/python ]; then
          ln --symbolic /usr/bin/python3 /usr/bin/python; 
        fi
      become: true

此解决方案与选项2相似,因为我们需要将其放在每本剧本的顶部,但我认为在某些方面它是优越的:

  • 仅在python3存在和python不存在的特定情况下创建符号链接-如果已经安装,它将不会覆盖Python 2
  • 不假设apt已安装
  • 可以针对所有主机运行,而无需任何特殊的错误处理
  • 与任何东西相比都超级快速 apt-get

显然,如果您需要在处安装Python 2 /usr/bin/python,则此解决方案是不可行的,选项2更好。

结论

  • 如果可以,我建议在所有情况下都使用选项1
  • 如果您的清单确实很大/很复杂,并且您无法轻松地将主机分组,则建议使用选项3python3,这会使选项1更加困难且容易出错。
  • 如果您需要在处安装Python 2,我只建议选项2胜过选项3/usr/bin/python

资料来源


13

您需要python 2.7才能运行Ansible。在Ubuntu 16.04上,可以通过以下命令进行安装:

sudo apt-get install python-minimal

之后,我可以跑步

ansible-playbook -i inventories/staging playbook.yml

成功运行ansible

请查看在Ubuntu 16.04使用ansible的更多信息


12

我以前是如何在ubuntu 15.10上使用新鲜的Digital Ocean小滴进行此工作的:

# my-playbook.yml
- name: python2
  hosts: test
  gather_facts: no
  pre_tasks:
    - raw: sudo apt-get -y install python-simplejson

$ ansible-playbook path/to/my-playbook.yml

对于新的OVH SSD上的ubuntu 16.04,在python2软件包可用之前,我不得不apt-get升级。


8

我发现实际上可以在一个剧本中包含多个剧本,因此我的设置现在包含一个在所有主机上运行的“依赖关系调配”剧本,以及针对特定主机的其他剧本。所以没有了pre_tasks

例如:

- 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
  # ....

6

正如其他人所说,这是由于缺少python2。此处的其他答案提供了pre_tasks和的解决方法gather_facts: no,但是,如果您使用的是EC2,并且使用ansible启动了实例,则可以使用user_dataoption:

- 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

然后人们通常等待ssh可用,如下所示:

  - 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

但是我发现,这并不总是足够长,因为CloudInit在启动过程中执行得很晚,因此在ssh可用后仍可能无法立即安装python2。所以我添加了一个暂停,以防实例被创建:

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

这将完美地完成这项工作,并且优点是您无需在每次运行时都检查python2,并且无需采取任何变通办法来稍后收集事实。

我确定其他云提供商也提供类似的CloudInit功能,因此请适应您的用例。


3

使用Packer的人可能会发现以下解决方案有帮助

假设您使用打包程序的Ansible Provisioner,您的配置可能如下所示

您可以先使用Shell Provisioner安装python,然后配置ansible_python_intepreter选项,如下所示

"provisioners": [
    {
      "type": "shell",
      "inline": [
        "apk update && apk add --no-cache python python-dev ansible bash"
      ]
    },
    {
      "type": "ansible-local",
      "playbook_file": "playbooks/your-play-book.yml",
      "playbook_dir": "playbooks",
      "extra_arguments": [
        "-e",
        "'ansible_python_interpreter=/usr/bin/python3'",
        "-vvv"
      ]
    },

2

默认情况下,Ansible需要Python 2,但是Ansible 2.2+也可以与Python 3一起使用

所以要么使用raw模块安装Python 2 ,例如

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

或在清单文件中设置ansible_python_interpreter变量,例如:

[local]
localhost ansible_python_interpreter="env python3"

对于Docker,您可以添加以下行:

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

或运行为:

ansible-playbook /ansible/provision.yml -e 'ansible_python_interpreter=/usr/bin/python3' -c local

1

根据这个要点,您可以按照以下步骤在Ubuntu 16.04上安装Python2:

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.

1

很多答案..感谢您的张贴,因为我也是从此页面开始的!

我做了一些挖掘工作,对Ubuntu 14.04LTS来说很可靠,Ubuntu 15.04LTS似乎已经删除了最新版本python,而Ubuntu 16.04LTS似乎已删除了aptitude

在进行任何apt调用之前,我将以下操作放入引导程序:

- name: "FIX: Ubuntu 16.04 LTS doesn't come with certain modules, required by ansible"
  raw: apt-get install python-minimal aptitude -y
  become: true
  become_user: root
  become_method: sudo

如果您become在其他地方进行管理,请随时进行剥离。

资料来源:


1

通过在目标机器(即我们要SSH的机器)上安装Python,我能够解决相同的问题。我使用了以下命令:

sudo apt-get install python-minimal

1

@Miroslav,感谢您为我指明了正确的方向。我user_data也在ec2_instance模块中使用过,它像对待一样。

- name: Creating single EC2 instance 
  ec2_instance:
    region: "{{ aws_region }}"
    key_name: "{{ aws_ec2_key_pair }}"
    name: "some-cool-name"
    instance_type: t1.micro
    image_id: ami-d38a4ab1
    security_group: sg-123456
    vpc_subnet_id: sn-678901234
    network:
        assign_public_ip: no
    volumes:
      - device_name: /dev/sda1
        ebs:
          volume_type: gp2
          volume_size: 15
    user_data: |
      #!/bin/bash
      #
      apt update
      apt install -y python-simplejson              
    termination_protection: yes
    wait: yes     

1

您可以向Ubuntu 18.04表示要使用python3作为的第一优先级/usr/bin/python

- hosts: all
  become: true
  pre_tasks:
    - raw: update-alternatives --install /usr/bin/python python /usr/bin/python3 1

0

我遇到了同样的问题,直到我意识到您还需要在远程主机以及您自己的本地计算机上安装python。现在可以了!


-2

我们只是碰到这个。

我们在流浪汉上部署了ubuntu 16.04,因此,如果您不使用流浪汉,我的评论将毫无意义。

我们安装了以下无业游民的插件(trigger,shell-commander),并在机器上安装了python 2.7.6(并非没有硫糖插件),并且在ansible之后可以部署

这是我们的最后一次测试,否则我们将在Vagrant文​​件的shell命令中包含此安装

希望它可以帮助某人


2
如果您使用的是Ansible,则下面的Ansible解决方案是正确的解决方案。希望Vagrant会由于某些插件的副作用而意外地为您安装它,似乎在自找麻烦。
Paul Becotte

打扰一下,但是如果没有python,您将如何运行它呢?我尝试了该解决方案,但它在任务设置时失败,因此在前置任务之前发生了事件。流浪者文件中的vagrant shell命令是做到这一点的最佳方法(当然,对于流浪者而言),但我只是注意到我已经在我的开发人员上安装的流浪者插件可以完成这项工作。我不是依赖于插件,而是依赖于流浪者文件,我只是指出它也可以与插件一起使用,但是流浪者文件是一个更好的选择(也用于自动化),因为您无需手动对每个文件进行任何操作销毁/供应
wadoo

1
我完全按照原样复制了该代码块,并且在您发布答案之前,它完全按照描述的方式工作。我相信您可能没有将这gather_facts: no行放到需要python 的行中。另一种可能性是您在主机上也需要python,但是我想这甚至会在此过程的早期导致您出错。
Paul Becotte

我也复制粘贴,但这是周五的工作。我不记得我是否参加过collect_fact部分。无论如何,今天早上又在另一台计算机上恢复了该命令,我只是将命令放在了vagrantfile中,对我来说足够了,直到我们在真实服务器上投入生产为止。我将重新思考(而不是在周五晚上)进行测试;)
wadoo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.