Ansible失败,/bin/sh:1:/usr/bin/python:未找到

我遇到了一个我从未见过的错误。下面是命令和错误:

$ 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

下面是创建_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地址。

编辑 Python是在本地安装的,问题是它没有安装在运行Ubuntu 15.04

的远程计算机上
105625 次浏览

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

- raw: sudo apt-get install python-simplejson

我在Ubuntu 15.10服务器上运行Ansible时偶然发现了这个错误,因为它附带了Python 3.4.3Ansible需要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(对所有问题都说“是”)选项(否则原始模块将静默地卡住)

  • _,ABC_0行也很关键(因为没有Python我们无法收集事实)。

我用来在Ubuntu15.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

对于新的OVH SSD上的Ubuntu16.04,我必须在Python2软件包可用之前进行升级。

我们刚刚遇到了这个。

我们在Vagrant上部署了Ubuntu16.04,所以如果你没有使用Vagrant,我的评论是毫无意义的。

我们安装了以下Vagrant插件(Trigger,Shell-Commander),并在机器上安装了Python 2.7.6(不是没有Thioose插件),然后可以部署Ansible

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

希望它能帮助一些人

正如其他人所说,这是由于缺少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

然而,我发现这并不总是足够长的,因为克劳迪尼特在引导过程中执行得很晚,所以Python2仍然可能不会在SSH可用后立即安装。因此,我添加了一个暂停,以防实例刚刚创建:

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

这将完美地完成这项工作,并且作为一个优势,您不必在每次运行时检查Python2,并且您不必做任何变通方法来收集以后的事实。

我相信其他云提供商也提供类似的CloudInit功能,所以请根据您的使用情形进行调整。

您需要Python2.7来运行Ansible. 在Ubuntu 16.04上,您可以通过以下命令安装它:

sudo apt-get install python-minimal

在那之后,我可以跑了。

ansible-playbook -i inventories/staging playbook.yml

Run ansible successfully

总结一下其他人的回答,下面是对我有用的组合设置:

 - 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

根据这个要点,您可以在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.

Ansible 2.2提供了对Python 3的技术预览版支持。利用这一点。(因此您不必在Ubuntu 16.04上安装Python 2),只需将ansible_python_interpreter配置选项设置为/usr/bin/python3。这可以在清单文件中按主机进行:

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

解决方案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中开箱即用。

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

sudo apt-get install python-minimal

很多答案..谢谢你的帖子,因为我也是从这个页面开始的!

我做了一点挖掘,它与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,请随意删除它。

来源:

  • https://github.com/ansible/ansible-modules-core/issues/3523#issuecomment-222368182.
  • https://github.com/ansible/ansible/issues/16884#issuecomment-278138707.

我发现实际上可以在一个行动手册中包含多个行动,因此我的设置现在包含一个在所有主机上运行的“依赖关系配置”行动,以及针对特定主机的其他行动。所以没有更多的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
# ....

我也遇到了同样的问题,直到我意识到您还需要在远程主机和您自己的本地计算机上安装Python.现在成功了!

默认情况下,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

@Miroslav,谢谢你给我指出正确的方向。我在ec2_instance模块中也使用了user_data,它就像一种享受。

- 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

对于这个问题,我个人找到了3种可能的解决方案,它们在不同的情况下都能很好地工作:

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

我认为这是解决问题的最好方法,如果您有办法根据主机是否默认安装了python3来对主机进行分组。据我所知,python3在所有Ubuntu版本16.04和更高版本上都可用。

  • 如果所有主机的_ABC_确实为0,则可以将变量添加到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则需要添加到每个剧本中。

选项2-使用raw安装Python 2

此选项要求在每个包含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

如果您计划在未安装apt-get的主机(例如任何基于RHEL的主机)上运行播放,则需要ignore_errors: true,否则它们将在第一个播放中出错。

这个解决方案是可行的,但由于以下几个原因,它在我的列表中排名最低:

  1. 需要位于每一行动手册的顶部(与选项1相对)
  2. 假定系统上的_ABC_为0,并忽略错误(与选项3相反)
  3. apt-get命令速度较慢(与选项3相反)

选项3-符号链接/usr/bin/python -> /usr/bin/python3,使用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上的ABC_1 Python 2,则此解决方案是不可行的,而选项2更好。

结论

  • 如果可以的话,我建议在所有情况下都使用选择1
  • 我建议使用备选方案3,如果您的清单非常大/复杂,并且您无法轻松地将主机与python3分组,这使得选择1更加困难和容易出错。
  • 我只建议选择2,而不是备选方案3,如果您需要将Python2安装在/usr/bin/python上。

消息来源

你可以告诉Ubuntu18.04你想使用Python3作为/usr/bin/python的第一优先级。

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

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

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

您可以首先使用shell provisioner安装Python,然后配置Ansible_Python_解释程序选项,如下所示

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

如果您对本地主机运行Ansible(换句话说,尝试配置自己的机器),您可以执行以下操作。

获取到的路径python3

$ which python3
/usr/bin/python3

更新ansible.cfg与.一起归档interpreter_python设置为python3路径

# ansible.cfg
[defaults]
interpreter_python  = /usr/bin/python3
transport           = local