Ansible échoue avec / bin / sh: 1: / usr / bin / python: introuvable

190

Je rencontre une erreur que je n'ai jamais vue auparavant. Voici la commande et l'erreur:

$ 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

Voici le fichier create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

Et voici le fichier hosts:

[api]
104.55.47.224

Je peux supprimer la section des rôles et cela ne parviendra pas à la première TÂCHE, mais au lieu de cela, cela ne fera que passer à la ligne /bin/sh: 1: /usr/bin/python: not found. Que pourrait-il se passer ici?


REMARQUE: Si quelqu'un envoie une requête ping à l'adresse IP et n'obtient pas de réponse, vous devez savoir que j'ai changé l'adresse IP depuis le collage du code.

EDIT python a été installé localement, le problème était qu'il n'était pas installé sur la machine distante, qui exécutait Ubuntu 15.04

jdavis
la source

Réponses:

172

Je suis tombé sur cette erreur lors de l'exécution d'ansible sur le serveur Ubuntu 15.10 , car il est livré avec Python 3.4.3 et ansible nécessite Python 2 .

Voici comment je provision.ymlregarde maintenant:

- 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
  • N'oubliez pas l'option -y (dit oui à toutes les questions) avec apt-get (ou le module brut restera bloqué en silence)

  • gather_facts: no la ligne est également critique (car nous ne pouvons pas rassembler des faits sans python)

Lakesare
la source
12
Ainsi, les rôles suivants ne peuvent pas utiliser des faits ... y a-t-il un moyen de rassembler à nouveau des faits? aha, stackoverflow.com/questions/31054453/…
stephen
16
Notez que la ligne 'rassembler_facts: non' est également critique.
rcreswick
6
@ surfer190 super trouvaille! J'ai également trouvé que l'ajout en action: setuptant que pré_tâche finale fonctionnait également très bien :)
mrooney
1
@ surfer190 voir ma réponse ici si vous utilisez EC2 avec ansible, vous pouvez utiliser CloudInit pour installer python2 afin que vous puissiez utiliser collecter des faits comme d'habitude.
Miroslav
1
Au cas où quelqu'un se demanderait également, il n'est pas nécessaire d'exécuter la rawtâche pour installer Python 2 dans pre_tasks; régulière tasksfonctionne bien aussi. Mais le mettre en place pre_tasks, avec une autre tâche pour appeler également le setupmodule Ansible , garantira que les faits sont disponibles pour tous les rôles attribués à l'hôte.
Kenny Evitt
127

Ansible 2.2 propose un aperçu technique de la prise en charge de Python 3. Pour en profiter (vous n'avez donc pas besoin d'installer Python 2 sur Ubuntu 16.04), définissez simplement l' ansible_python_interpreteroption de configuration sur /usr/bin/python3. Cela peut être fait par hôte dans votre fichier d'inventaire:

[db]
123.123.123.123 ansible_python_interpreter=/usr/bin/python3
Jamix
la source
J'ai essayé d'ajouter / usr / bin / python à cette variable, mais cela n'a pas fonctionné. L'ajout de python3 a plutôt fonctionné et ce problème a été corrigé
Deep LF
99

Solution 1:

Si vous utilisez Ansible >2.2.0, vous pouvez définir l' ansible_python_interpreteroption de configuration sur /usr/bin/python3:

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

ou dans votre fichier d'inventaire:

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

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

Solution 2:

Si vous utilisez, Ansible <2.2.0vous pouvez les ajouter pre_tasksà votre playbook:

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

MISE À JOUR Avec ansible 2.8.x, vous n'avez pas à vous en soucier, cela fonctionne hors de la boîte pour python> 3.5 pour le contrôleur et la ou les machines cibles

Arbab Nazar
la source
Si vous exécutez vos playbooks à l'aide de balises, assurez-vous d'ajouter des balises: toujours à la tâche de configuration - sinon ansible ne rassemblera pas les faits lorsque vous utilisez des balises.
Ionut Bajescu
17
J'ai ansible 2.3.0.0et cela ne fonctionne pas hors de la boîte. Même erreur que celle signalée par l'OP.
The Coder
Au cas où ce n'est pas explicitement clair, vous devez l'ajouter au fichier d'inventaire de l'hôte, pas à un vars inclus, c'est-à-dire qu'il se trouve dans le même fichier d'inventaire que l'adresse / le nom de l'hôte.
Shawn Mehan
32

Vous pouvez utiliser le module raw pour installer Python sur les hôtes distants:

- raw: sudo apt-get install python-simplejson
udondan
la source
11
Pour vous assurer que cela est appelé avant les tâches de votre rôle, et avant toute dépendance dans votre méta-fichier, ajoutez-le comme ceci à votre playbook: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld
5
Notez que dans un playbook, vous devez également désactiver rassembler_facts, sinon cela échouera avant d'exécuter la commande raw. (Gather_facts: Non)
rcreswick
@rcreswick C'était mon problème et votre solution a fonctionné pour moi. Merci beaucoup. J'ai mis la ligne «ather_facts: no »dans mon fichier .yml principal (setup-ansible.yml) et exécuté le playbook avec cette commande:« ansible-playbook -i hosts setup-ansible.yml --flush-cache -vvvvvv -kK ". J'ai utilisé les options "-kK" avec ansible-playbook car l'installation par défaut d'ubuntu a besoin d'un mot de passe pour faire "sudo".
Ali Yousefi Sabzevar
pourquoi installez-vous simplejson et non pytghon mais parlez-vous d'installer python?
Henning
@Henning python-simplejsonest écrit en Python et nécessite donc Python. simplejson est également une exigence pour la plupart des modules principaux d'Ansible. En installant python-simplejsonvia apt-get/ yumvous installez également Python et couvrez donc toutes les dépendances de base d'Ansible ...
udondan
18

Pour résumer les réponses de tous les autres, voici les paramètres combinés qui ont fonctionné pour moi:

 - 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
Policier
la source
14

J'ai personnellement trouvé 3 solutions possibles à ce problème qui fonctionnent bien dans différentes situations:

Option 1 - Définie ansible_python_interpreter: /usr/bin/python3pour les hôtes python3installés par défaut

Je pense que c'est la meilleure méthode pour résoudre le problème si vous avez un moyen de regrouper vos hôtes selon qu'ils ont ou non python3installés par défaut. Pour autant que je sache, python3est disponible sur toutes les versions d'Ubuntu 16.04 et supérieures.

  • Si tous vos hôtes l'ont définitivement python3, vous pouvez ajouter la variable à votre group_vars/all.yml(ou équivalent):
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Si certains de vos hôtes ne l'ont pas python3et que vous avez un moyen de les baliser lors de l'utilisation d'un inventaire dynamique (par exemple, le marquage AWS pour ec2.py), vous pouvez appliquer la variable à certains hôtes comme ceci:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Si vous utilisez un inventaire statique et que vous êtes en mesure de regrouper les hôtes selon qu'ils l'ont fait python3, vous pouvez faire quelque chose comme ceci:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

J'aime le plus cette option car elle ne nécessite aucune modification sur l'hôte distant et seulement des modifications mineures des variables, par opposition aux options 2 et 3, qui nécessitent des ajouts à chaque playbook.

Option 2 - Installez Python 2 en utilisant raw

Cette option nécessite de mettre un jeu en haut de chaque playbook avec gather_facts: falsequi utilise rawpour installer 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: trueest requis si vous prévoyez d'exécuter la lecture sur des hôtes qui n'ont pas été apt-getinstallés (par exemple, tout ce qui est basé sur RHEL), sinon ils se trompent lors de la première lecture.

Cette solution fonctionne, mais est la plus basse de ma liste pour plusieurs raisons:

  1. Doit aller en haut de chaque playbook (par opposition à l'option 1)
  2. Suppose qu'il se apttrouve sur le système et ignore les erreurs (par opposition à l'option 3)
  3. apt-get les commandes sont lentes (contrairement à l'option 3)

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

Je n'ai vu cette solution proposée par personne d'autre. Ce n'est pas idéal, mais je pense que c'est supérieur à l'option 2 à bien des égards. Ma suggestion est d'utiliser rawpour exécuter une commande shell pour créer un lien symbolique /usr/bin/python -> /usr/bin/python3si se python3trouve sur le système et python ne l'est pas:

- 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

Cette solution est similaire à l'option 2 en ce sens que nous devons la placer en haut de chaque playbook, mais je pense qu'elle est supérieure à plusieurs égards:

  • Crée uniquement le lien symbolique dans le cas spécifique python3présent et pythonnon - il ne remplacera pas Python 2 s'il est déjà installé
  • Ne suppose pas aptest installé
  • Peut s'exécuter sur tous les hôtes sans aucune gestion d'erreur particulière
  • Est super rapide par rapport à n'importe quoi avec apt-get

Évidemment, si vous avez besoin d' installer Python 2 sur /usr/bin/python, cette solution est interdite et l'option 2 est meilleure.

Conclusion

  • Je suggère d'utiliser l' option 1 dans tous les cas si vous le pouvez.
  • Je suggère d'utiliser l' option 3 si votre inventaire est vraiment volumineux / complexe et que vous n'avez aucun moyen de regrouper facilement les hôtes python3, ce qui rend l' option 1 beaucoup plus difficile et sujette aux erreurs.
  • Je ne suggère que l' option 2 par rapport à l' option 3 si vous avez besoin d'installer Python 2 sur /usr/bin/python.

Sources

Percygrunwald
la source
13

Vous avez besoin de python 2.7 pour exécuter Ansible. Sur Ubuntu 16.04, vous pouvez l'installer via cette commande:

sudo apt-get install python-minimal

Après ça, je pourrais courir

ansible-playbook -i inventories/staging playbook.yml

Exécuter ansible avec succès

Veuillez vérifier plus à Utilisation d'ansible sur Ubuntu 16.04

phanvugiap
la source
12

Ce que j'ai utilisé pour faire fonctionner cela sur ubuntu 15.10 sur une nouvelle gouttelette 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

Pour ubuntu 16.04 sur un SSD OVH frais, j'ai dû effectuer une mise à niveau apt-get avant que les packages python2 ne soient disponibles.

Deadghost
la source
8

J'ai découvert qu'il est en fait possible d'avoir plusieurs jeux dans un seul playbook, donc ma configuration contient maintenant un jeu de "provisioning de dépendance" qui fonctionne sur tous les hôtes, et d'autres jeux pour des hôtes spécifiques. Donc pas plus pre_tasks.

Par exemple:

- 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
  # ....
Koen.
la source
6

Comme d'autres l'ont dit, cela est dû à l'absence de python2. D'autres réponses ici fournissent une solution de contournement avec pre_taskset gather_facts: no, cependant, si vous êtes sur EC2 et que vous faites tourner l'instance avec ansible, vous pouvez utiliser l' 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

Ensuite, les gens attendent généralement que ssh soit disponible comme ceci:

  - 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

Cependant, j'ai trouvé que ce n'est pas toujours assez long car CloudInit est exécuté assez tard dans le processus de démarrage, de sorte que python2 peut toujours ne pas être installé juste après que ssh soit disponible. J'ai donc ajouté une pause au cas où l'instance venait juste d'être créée:

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

Cela fera parfaitement le travail et comme avantage, vous ne vérifiez pas python2 à chaque exécution et vous n'avez pas à faire de contournement pour rassembler des faits plus tard.

Je suis sûr que d'autres fournisseurs de cloud fournissent des fonctionnalités CloudInit similaires, alors adaptez-vous à votre cas d'utilisation.

Miroslav
la source
3

Ceux qui utilisent Packer peuvent trouver la solution ci-dessous utile

Supposons que vous utilisez un provisioner ansible de packer, votre configuration peut ressembler à ci-dessous

vous pouvez installer python en utilisant d'abord le fournisseur de shell, puis configurer l'option ansible_python_intepreter comme indiqué ci-dessous

"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"
      ]
    },
smakintel.com
la source
2

Par défaut, Ansible nécessite Python 2 , cependant, Ansible 2.2+ peut également fonctionner avec Python 3 .

Donc, soit installez Python 2 en utilisant le rawmodule , par exemple

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

ou définissez une ansible_python_interpretervariable dans le fichier d'inventaire, comme:

[local]
localhost ansible_python_interpreter="env python3"

Pour Docker, vous pouvez ajouter la ligne suivante:

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

ou exécutez-le comme:

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

Selon ce Gist, vous pouvez installer Python2 sur Ubuntu 16.04 comme suit:

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.
wedesoft
la source
1

Beaucoup de réponses ... Merci d'avoir posté car j'ai commencé à partir de cette page aussi!

J'ai fait un peu de fouille et c'était solide avec Ubuntu 14.04LTS, Ubuntu 15.04LTS semblait avoir abandonné le dernier pythonet Ubuntu 16.04LTS semble avoir chuté aptitude.

J'ai mis l'action suivante dans mon bootstrap avant de faire des aptappels:

- 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

Si vous vous débrouillez becomeailleurs, n'hésitez pas à le dépouiller.

Sources:

sonjz
la source
1

J'ai pu résoudre le même problème en installant Python sur la machine cible, c'est-à-dire la machine sur laquelle nous voulons SSH. J'avais utilisé la commande suivante:

sudo apt-get install python-minimal
Anshul
la source
1

@Miroslav, merci de m'avoir pointé dans la bonne direction. Je l'ai utilisé user_datadans le ec2_instancemodule aussi et cela fonctionne comme un régal.

C'est à dire

- 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     
Luuk
la source
1

Vous pouvez indiquer à Ubuntu 18.04 que vous souhaitez utiliser python3 comme première priorité pour /usr/bin/python.

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

J'ai eu le même problème, jusqu'à ce que je réalise que vous devez également installer python sur l'hôte distant ainsi que sur votre propre machine locale. maintenant ça marche!

GAV
la source
-2

Nous venons de rencontrer ça.

Nous déployons ubuntu 16.04 sur un vagabond donc si vous n'utilisez pas vagrant, mon commentaire est inutile.

Nous avons installé les plugins vagrant suivants (trigger, shell-commander) et nous obtenons python 2.7.6 installé sur la machine (qui n'étaient pas sans plugins thioose) et après ansible peut déployer

C'était notre dernier test, sinon nous étions sur le point d'inclure cette installation dans une commande shell du fichier Vagrant

J'espère que ça peut aider quelqu'un

wadoo
la source
2
Si vous utilisez Ansible, la solution Ansible ci-dessous est le correctif correct. Espérer que Vagrant l'installera accidentellement pour vous en tant qu'effet secondaire de certains plugins semble demander des ennuis.
Paul Becotte
Excusez-moi mais comment pouvez-vous exécuter une pré-tâche ansible si elle n'a pas de python ??? J'ai essayé la solution et elle a échoué lors de la configuration de la tâche, donc événement avant la tâche préalable. La commande vagrant shell dans le fichier vagrant EST la meilleure façon de le faire (pour le cas vagrant bien sûr) mais je remarque juste que le plugin vagrant que j'avais installé sur mon développeur fait le travail. Je ne compte pas sur le plugin mais sur le fichier vagrant, je viens de souligner que cela fonctionne aussi avec le plugin mais le fichier vagrant est un meilleur choix (également pour l'automatisation) car vous n'avez rien à faire manuellement sur chacun détruire / approvisionner
wadoo
1
J'ai copié ce bloc de code exactement tel qu'il était, et cela fonctionnait exactement comme décrit juste avant que vous ne postiez votre réponse. Je crois que vous n'avez probablement pas mis la gather_facts: noligne dans ce qui nécessite python. L'autre possibilité est que vous ayez également besoin de python sur la machine hôte, mais je suppose que cela vous aurait causé des erreurs encore plus tôt dans le processus.
Paul Becotte
J'ai copié de la pâte aussi mais c'était vendredi soir au travail. Je ne me souviens pas honnêtement si j'ai pris la partie rassembler_fact. Quoi qu'il en soit, dans un autre ordinateur, je l'ai encore fait ce matin et je viens de mettre la commande dans vagrantfile, cela me suffit jusqu'à ce que nous passions en production sur un vrai serveur. Je vais tester à nouveau avec un esprit frais (donc pas un vendredi soir) la réponse;)
wadoo