Ansible失败了/ bin / sh:1:/ usr / bin / python:找不到

问题描述 投票:176回答:19

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

$ 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

这是hosts文件:

[api]
104.55.47.224

我可以删除角色部分,它不会进入第一个任务,它将使它只会使它到线/bin/sh: 1: /usr/bin/python: not found。这可能会发生什么?


注意:如果有人正在ping IP地址并且没有得到响应,您应该知道自从粘贴代码后我已经更改了IP地址。

编辑python是在本地安装的,问题是它没有安装在运行Ubuntu 15.04的远程机器上

ansible ansible-playbook
19个回答
166
投票

我偶然发现在Ubuntu 15.10服务器上运行ansible时出现这个错误,因为它附带了Python 3.4.3和ansible requires 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我们无法收集事实)

6
投票

正如其他人所说,这是由于缺少python2。这里的其他答案提供了pre_tasksgather_facts: no的解决方法,但是如果您使用EC2并且使用ansible旋转实例,则可以使用user_data选项:

- 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功能,因此请根据您的使用情况进行调整。


2
投票

默认情况下,Ansible requires Python 2Ansible 2.2+ can work with Python 3也是如此。

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

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

或者在库存文件中设置ansible_python_interpreter variable,例如:

[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

2
投票

使用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"
      ]
    },

1
投票

根据this Gist,您可以在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
投票

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

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,所以如果你不使用流浪汉,我的评论毫无意义。

我们安装了以下vagrant插件(触发器,shell-commander),我们在机器上安装了python 2.7.6(不是没有thioose插件)并且在ansible可以部署之后

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

希望它可以帮助某人


117
投票

Ansible 2.2具有Python 3支持的技术预览。 To take advantage of this(所以你不必在Ubuntu 16.04上安装Python 2),只需将ansible_python_interpreter配置选项设置为/usr/bin/python3即可。这可以在您的库存文件中基于每个主机完成:

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

92
投票

解决方案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

更新使用ansible 2.8.x,你不需要担心它,它的开箱即用,对于控制器和目标机器的python> 3.5


32
投票

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

- raw: sudo apt-get install python-simplejson

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

13
投票

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

sudo apt-get install python-minimal

在那之后,我可以跑了

ansible-playbook -i inventories/staging playbook.yml

Run ansible successfully

请在Using ansible on Ubuntu 16.04查看更多信息


12
投票

我曾经在新鲜的数字海洋液滴上使用ubuntu 15.10进行此操作:

# 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

对于ubuntu 16.04在新的OVH SSD上,我必须在python2包可用之前进行apt-get升级。


12
投票

我个人发现了3个可能解决这个问题的方法,它在不同情况下运行良好:

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

我认为这是解决问题的最佳方法,如果你有办法按照他们是否默认安装python3来分组你的主机。据我所知,python3适用于所有Ubuntu版本16.04及更高版本。

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

ansible_python_interpreter: /usr/bin/python3
  • 如果您的某些主机没有python3并且您在使用动态库存时可以标记它们(例如,为ec2.py标记AWS标记),您可以将变量应用于某些主机,如下所示:
# 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,这需要添加到每个playbook。

选项2 - 使用raw安装Python 2

此选项要求使用gather_facts: false安装rawpython在每个剧本的顶部播放:

- 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的主机上运行游戏(例如任何基于RHEL的游戏),则需要使用apt-get,否则它们将在第一次播放时出错。

此解决方案有效,但由于以下几个原因,我的列表中最低:

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

选项3 - 使用/usr/bin/python -> /usr/bin/python3的Symlink raw

我没有看到其他人提出的这个解决方案。这不是理想的,但我认为它在很多方面都优于选项2。我的建议是使用raw运行shell命令到符号链接/usr/bin/python -> /usr/bin/python3如果python3在系统上并且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的任何东西相比都是超级快的

显然如果你需要在/usr/bin/python安装Python 2,这个解决方案是不行的,选项2更好。

结论

  • 如果可以的话,我建议在所有情况下使用选项1。
  • 我建议使用选项3,如果您的库存非常大/复杂,并且您无法使用python3轻松地对主机进行分组,那么选项1将变得更加困难且容易出错。
  • 如果您需要在/usr/bin/python安装Python 2,我只建议选项2而不是选项3。

来源


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
  # ....
© www.soinside.com 2019 - 2024. All rights reserved.