Ansible schlägt fehl mit / bin / sh: 1: / usr / bin / python: nicht gefunden


187

Ich stoße auf einen Fehler, den ich noch nie gesehen habe. Hier ist der Befehl und der Fehler:

$ 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

Hier ist die Datei create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

Und hier ist die Hosts-Datei:

[api]
104.55.47.224

Ich kann den Rollenabschnitt entfernen und er schafft es nicht bis zur ersten AUFGABE, sondern nur bis zur Zeile /bin/sh: 1: /usr/bin/python: not found. Was könnte hier los sein?


HINWEIS: Falls jemand die IP-Adresse anpingt und keine Antwort erhält, sollten Sie wissen, dass ich die IP-Adresse seit dem Einfügen des Codes geändert habe.

EDIT Python wurde lokal installiert. Das Problem war, dass es nicht auf dem Remote-Computer installiert war, auf dem Ubuntu 15.04 ausgeführt wurde

Antworten:


171

Ich bin auf diesen Fehler gestoßen, der ansible auf dem Ubuntu 15.10- Server ausführt , da er mit Python 3.4.3 geliefert wird und ansible Python 2 erfordert .

So sehe ich provision.ymljetzt aus:

- 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
  • Vergessen Sie nicht die Option -y (sagt Ja zu allen Fragen) mit apt-get (oder das Rohmodul bleibt lautlos hängen).

  • gather_facts: no Linie ist auch kritisch (weil wir ohne Python keine Fakten sammeln können)


12
Nachfolgende Rollen können also keine Fakten verwenden. Gibt es eine Möglichkeit, Fakten erneut zu sammeln? aha, stackoverflow.com/questions/31054453/…
stephen

16
Beachten Sie, dass die Zeile 'collect_facts: no' ebenfalls kritisch ist.
Rcreswick

6
@ surfer190 toller Fund! Ich fand auch, dass das Hinzufügen action: setupals letzte pre_task auch großartig funktionierte :)
mrooney

1
@ surfer190 siehe meine Antwort hier Wenn Sie EC2 mit ansible verwenden, können Sie mit CloudInit python2 installieren, damit Sie wie gewohnt Fakten sammeln können.
Miroslav

1
Falls sich jemand wundert, ist es nicht erforderlich , die rawAufgabe auszuführen , um Python 2 zu installieren pre_tasks. regelmäßig tasksfunktioniert auch gut. Wenn Sie es jedoch zusammen pre_tasksmit einer anderen Aufgabe eingeben, um auch das Ansible- setupModul aufzurufen , wird sichergestellt, dass Fakten für alle Rollen verfügbar sind, die dem Host zugewiesen sind.
Kenny Evitt

125

Ansible 2.2 bietet eine technische Vorschau der Python 3-Unterstützung. Um dies zu nutzen (damit Sie Python 2 nicht unter Ubuntu 16.04 installieren müssen), setzen Sie einfach die ansible_python_interpreterKonfigurationsoption auf /usr/bin/python3. Dies kann pro Host in Ihrer Inventardatei erfolgen:

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

Ich habe versucht, dieser Variablen / usr / bin / python hinzuzufügen, aber es hat nicht funktioniert. Das Hinzufügen von Python3 funktionierte stattdessen und dieses Problem wurde behoben
Deep LF

97

Lösung 1:

Wenn Sie verwenden Ansible >2.2.0, können Sie die ansible_python_interpreterKonfigurationsoption auf Folgendes einstellen /usr/bin/python3:

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

oder in Ihrer Inventardatei:

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

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

Lösung 2:

Wenn Sie verwenden Ansible <2.2.0, können Sie diese pre_tasksIhrem Playbook hinzufügen :

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 Mit ansible 2.8.x, Sie müssen sich keine Sorgen machen, es funktioniert sofort für Python> 3.5 für Controller und Zielcomputer.


Wenn Sie Ihre Playbooks mit Tags ausführen, stellen Sie sicher, dass Sie Tags hinzufügen: immer zur Setup-Aufgabe - andernfalls sammelt ansible die Fakten nicht, wenn Sie Tags verwenden.
Ionut Bajescu

16
Ich habe ansible 2.3.0.0und es funktioniert nicht sofort. Gleicher Fehler wie vom OP gepostet.
Der Coder

Falls dies nicht explizit klar ist, müssen Sie dies zur Host-Inventardatei hinzufügen, nicht zu einer enthaltenen Vars, dh es befindet sich in derselben Inventardatei wie die Hostadresse / der Hostname.
Shawn Mehan

32

Mit dem Raw-Modul können Sie Python auf den Remote-Hosts installieren:

- raw: sudo apt-get install python-simplejson

11
Um sicherzustellen, dass dies vor Aufgaben in Ihrer Rolle und vor Abhängigkeiten in Ihrer Metadatei aufgerufen wird, fügen Sie es folgendermaßen zu Ihrem Playbook hinzu: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld

5
Beachten Sie, dass Sie in einem Playbook auch collect_facts deaktivieren müssen. Andernfalls schlägt dies fehl, bevor Sie den Befehl raw ausführen. (collect_facts: no)
Rcreswick

@rcreswick Das war mein Problem und Ihre Lösung hat bei mir funktioniert. Vielen Dank. Ich habe die Zeile "collect_facts: no" in meine Haupt-.yml-Datei (setup-ansible.yml) eingefügt und das Playbook mit dem folgenden Befehl ausgeführt: "ansible-playbook -i hostet setup-ansible.yml --flush-cache -vvvvvv -kK ". Ich habe "-kK" -Optionen mit ansible-playbook verwendet, da für die Standard-Ubuntu-Installation ein Kennwort erforderlich ist, um "sudo" auszuführen.
Ali Yousefi Sabzevar

Warum installieren Sie simplejson und nicht pytghon, sondern sprechen über die Installation von Python?
Henning

@Henning python-simplejsonist in Python geschrieben und erfordert daher Python. simplejson ist auch eine Voraussetzung für die meisten Ansible-Kernmodule. Durch die Installation python-simplejsonüber apt-get/ yuminstallieren Sie auch Python und decken damit alle grundlegenden Ansible-Abhängigkeiten ab ...
udondan

18

Um die Antworten aller anderen zusammenzufassen, sind hier die kombinierten Einstellungen, die für mich funktioniert haben:

 - 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

Ich persönlich habe 3 mögliche Lösungen für dieses Problem gefunden, die in verschiedenen Situationen gut funktionieren:

Option 1 - ansible_python_interpreter: /usr/bin/python3Für Hosts festlegen, die python3standardmäßig installiert wurden

Ich denke, dies ist die überlegene Methode zur Lösung des Problems, wenn Sie eine Möglichkeit haben, Ihre Hosts danach zu gruppieren, ob sie python3standardmäßig installiert sind oder nicht . Soweit mir bekannt ist, python3ist es auf allen Ubuntu-Versionen 16.04 und höher verfügbar.

  • Wenn alle Ihre Hosts definitiv haben python3, können Sie die Variable zu Ihrem group_vars/all.yml(oder einem gleichwertigen) hinzufügen :
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Wenn einige Ihrer Hosts keine haben python3und Sie eine Möglichkeit haben, sie zu kennzeichnen, wenn Sie dynamisches Inventar verwenden (z. B. AWS-Tagging für ec2.py), können Sie die Variable auf bestimmte Hosts wie folgt anwenden:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Wenn Sie statisches Inventar verwenden und Hosts danach gruppieren können python3, können Sie Folgendes tun:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

Ich mag diese Option am meisten, weil sie keine Änderungen auf dem Remote-Host und nur geringfügige Änderungen an Variablen erfordert, im Gegensatz zu den Optionen 2 und 3, die Ergänzungen zu jedem Playbook erfordern.

Option 2 - Installieren Sie Python 2 mit raw

Für diese Option muss ein Spiel oben in jedes Spielbuch eingefügt werden, mit gather_facts: falsedem Folgendes rawinstalliert wird 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 ist erforderlich, wenn Sie das Spiel auf Hosts ausführen möchten, die dies nicht haben apt-get installiert sind (z. B. RHEL-basiert), da diese sonst beim ersten Spiel fehlerhaft sind.

Diese Lösung funktioniert, ist jedoch aus mehreren Gründen die niedrigste auf meiner Liste:

  1. Muss an die Spitze von jedem gehen Spielbuch stehen (im Gegensatz zu Option 1)
  2. Angenommen, es aptbefindet sich im System und ignoriert Fehler (im Gegensatz zu Option 3).
  3. apt-get Befehle sind langsam (im Gegensatz zu Option 3)

Option 3 - Symlink /usr/bin/python -> /usr/bin/python3mitraw

Ich habe diese von niemand anderem vorgeschlagene Lösung gesehen. Es ist nicht ideal, aber ich denke, es ist Option 2 in vielerlei Hinsicht überlegen. Mein Vorschlag ist, raweinen Shell-Befehl zum Symlink auszuführen, /usr/bin/python -> /usr/bin/python3wenn er python3sich auf dem System befindet und python nicht:

- 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

Diese Lösung ähnelt Option 2 insofern, als wir sie in jedes Spielbuch einfügen müssen, aber ich denke, dass sie in einigen Punkten überlegen ist:

  • Erstellt den Symlink nur in dem speziellen Fall, der python3vorhanden ist undpython nicht - Python 2 wird nicht überschrieben, wenn es bereits installiert ist
  • Nimmt nicht an apt installiert ist
  • Kann ohne spezielle Fehlerbehandlung auf allen Hosts ausgeführt werden
  • Ist super schnell im Vergleich zu allem mit apt-get

Natürlich , wenn Sie benötigen Python 2 installiert an/usr/bin/python , ist diese Lösung ein nicht gehen und Option 2 ist besser.

Fazit

  • Ich schlage vor, in allen Fällen Option 1 zu verwenden, wenn Sie können.
  • Ich schlage vor, Option 3 zu verwenden, wenn Ihr Inventar wirklich groß / komplex ist und Sie keine Möglichkeit haben, Hosts einfach zu gruppieren python3, was Option 1 viel schwieriger und fehleranfälliger macht.
  • Ich empfehle Option 2 gegenüber Option 3 nur, wenn Python 2 unter installiert sein muss /usr/bin/python.

Quellen



12

Was ich verwendet habe, um dies auf Ubuntu 15.10 auf einem frischen Digital Ocean-Tröpfchen zum Laufen zu bringen:

# 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

Für Ubuntu 16.04 auf einer neuen OVH-SSD musste ich ein Upgrade durchführen, bevor die Python2-Pakete verfügbar waren.


8

Ich habe herausgefunden, dass es tatsächlich möglich ist, mehrere Spiele in einem einzigen Playbook zu haben. Daher enthält mein Setup jetzt ein Spiel zur Bereitstellung von Abhängigkeiten, das auf allen Hosts ausgeführt wird, und andere Spiele für bestimmte Hosts. Also nicht mehrpre_tasks .

Beispielsweise:

- 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

Wie andere sagten, liegt dies an fehlendem Python2. Andere Antworten hier bieten eine Abhilfe mit pre_tasksund gather_facts: no, aber wenn Sie auf EC2 sind und Sie drehen die Instanz mit ansible up Sie verwenden können , 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

Dann warten die Leute normalerweise darauf, dass ssh wie folgt verfügbar ist:

  - 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

Ich habe jedoch festgestellt, dass dies nicht immer lang genug ist, da CloudInit ziemlich spät im Startvorgang ausgeführt wird, sodass python2 möglicherweise immer noch nicht direkt nach der Verfügbarkeit von ssh installiert wird. Daher habe ich eine Pause hinzugefügt, falls die Instanz gerade erstellt wurde:

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

Dies macht den Job perfekt und als Vorteil suchen Sie nicht bei jedem Lauf nach Python2 und müssen keine Problemumgehungen durchführen, um später Fakten zu sammeln.

Ich bin sicher, dass andere Cloud-Anbieter ähnliche CloudInit-Funktionen bereitstellen. Passen Sie sie daher an Ihren Anwendungsfall an.


3

Für diejenigen, die Packer verwenden, ist die folgende Lösung möglicherweise hilfreich

Nehmen wir an, Sie verwenden einen ansible Provisioner von Packer. Ihre Konfiguration sieht möglicherweise wie folgt aus

Sie können Python zuerst mit dem Shell-Provisioner installieren und dann die Option ansible_python_intepreter wie unten gezeigt konfigurieren

"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

Standardmäßig benötigt Ansible Python 2 , Ansible 2.2+ kann jedoch auch mit Python 3 verwendet werden.

Installieren Sie also entweder Python 2 mit dem rawModul , z

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

oder setzen Sie eine ansible_python_interpreterVariable in der Inventardatei wie:

[local]
localhost ansible_python_interpreter="env python3"

Für Docker können Sie die folgende Zeile hinzufügen:

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

oder führen Sie es aus als:

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

1

Entsprechend dieser Zusammenfassung können Sie Python2 unter Ubuntu 16.04 wie folgt installieren:

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

Viele Antworten. Vielen Dank für die Veröffentlichung, da ich auch von dieser Seite angefangen habe!

Ich habe ein bisschen gegraben und es war solide mit Ubuntu 14.04LTS, Ubuntu 15.04LTS schien das neueste fallen gelassen zu haben pythonund Ubuntu 16.04LTS scheint gefallen zu sein aptitude.

Ich habe die folgende Aktion in meinen Bootstrap eingefügt, bevor ich aptAnrufe tätige:

- 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

Wenn Sie es becomeanderswo schaffen, können Sie es gerne entfernen.

Quellen:


1

Ich konnte das gleiche Problem beheben, indem ich Python auf dem Zielcomputer installierte, dh auf dem Computer, auf dem SSH ausgeführt werden soll. Ich hatte folgenden Befehl verwendet:

sudo apt-get install python-minimal

1

@ Miroslav, danke, dass du mich in die richtige Richtung gelenkt hast. Ich habe user_datain derec2_instance Modul verwendet und es funktioniert wie ein Genuss.

Dh

- 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

Sie können Ubuntu 18.04 mitteilen, dass Sie Python3 als erste Priorität für verwenden möchten /usr/bin/python.

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

0

Ich hatte das gleiche Problem, bis mir klar wurde, dass Sie Python auch auf dem Remote-Host sowie auf Ihrem eigenen lokalen Computer installieren müssen. jetzt gehts!


-2

Wir stoßen einfach darauf.

Wir stellen Ubuntu 16.04 für einen Vagabunden bereit. Wenn Sie also keinen Vagabund verwenden, ist mein Kommentar sinnlos.

Wir haben die folgenden Vagrant-Plugins (Trigger, Shell-Commander) installiert und Python 2.7.6 auf dem Computer installiert (die nicht ohne diese Plugins waren) und nach Ansible bereitstellen können

Es war unser letzter Test, ansonsten wollten wir diese Installation in einen Shell-Befehl in der Vagrant-Datei aufnehmen

Hoffe es kann jemandem helfen


2
Wenn Sie Ansible verwenden, ist die folgende Ansible-Lösung die richtige Lösung. Die Hoffnung, dass Vagrant es versehentlich als Nebeneffekt einiger Plugins für Sie installiert, scheint nach Problemen zu fragen.
Paul Becotte

Entschuldigung, aber wie können Sie eine ansible Pretask ausführen, wenn sie nicht Python hat? Ich habe die Lösung ausprobiert und sie schlägt beim Einrichten der Aufgabe fehl, also Ereignis vor der Voraufgabe. Der Vagrant Shell-Befehl in der Vagrant-Datei ist der beste Weg, dies zu tun (natürlich für Vagrant-Fälle), aber ich bemerke nur, dass das Vagrant-Plugin, das ich auf meinem Entwickler installiert habe, den Job macht. Ich verlasse mich nicht auf das Plugin, sondern auf die Vagrant-Datei. Ich habe nur darauf hingewiesen, dass es auch mit dem Plugin funktioniert, aber die Vagrant-Datei ist eine bessere Wahl (auch für die Automatisierung), da Sie nicht manuell etwas tun müssen zerstören / Bereitstellung
Wadoo

1
Ich habe diesen Codeblock genau so kopiert, wie er war, und er hat genau wie beschrieben funktioniert, bevor Sie Ihre Antwort gepostet haben. Ich glaube, Sie haben wahrscheinlich nicht die gather_facts: noZeile eingefügt, die Python erfordert. Die andere Möglichkeit ist, dass Sie auch Python auf dem Host-Computer benötigen, aber ich würde vermuten, dass dies Ihnen noch früher im Prozess Fehler verursacht hätte.
Paul Becotte

Ich habe auch Paste kopiert, aber es war Freitag Nacht bei der Arbeit. Ich kann mich nicht ehrlich erinnern, ob ich den Gather_Fact-Teil übernommen habe. Wie auch immer, wenn es heute Morgen auf einem anderen Computer erneut angezeigt wird und ich den Befehl gerade in eine Vagrant-Datei geschrieben habe, reicht es mir, bis wir auf einem echten Server zur Produktion gehen. Ich werde die Antwort noch einmal mit einem frischen Verstand testen (also nicht an einem
Freitagabend
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.