web-dev-qa-db-fra.com

Ansible échoue avec/bin/sh: 1:/usr/bin/python: non trouvé

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 ne parviendra pas à la première tâche, mais à la ligne /bin/sh: 1: /usr/bin/python: not found. Que pourrait-il se passer ici? 


NOTE: Si quelqu'un envoie une requête ping à l'adresse IP et ne reçoit pas de réponse, sachez que j'ai changé d'adresse IP depuis le collage du code.

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

158
jdavis

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

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

  • gather_facts: noline est également critique (car nous ne pouvons pas rassembler les faits sans python)

154
lakesare

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

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

Solution 1:

Si vous utilisez Ansible >2.2.0, vous pouvez définir l'option de configuration ansible_python_interpreter 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.0, vous pouvez ajouter ces 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
74
Arbab Nazar

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

- raw: Sudo apt-get install python-simplejson
31
udondan

Pour résumer les réponses de chacun, 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
17
Bobby

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 cela, je pourrais courir 

ansible-playbook -i inventories/staging playbook.yml

 Run ansible successfully

Veuillez vérifier plus à Utiliser ansible sur Ubuntu 16.04

13
phanvugiap

Ce que je faisais auparavant avec 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 nouveau disque SSD OVH, je devais mettre à jour apt-get avant que les paquets python2 soient disponibles.

11
deadghost

J'ai découvert qu'il est en fait possible d'avoir plusieurs jeux dans un seul livre de lecture. Ma configuration contient donc maintenant un jeu "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
  # ....
8
Koen.

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

Option 1 - Définissez ansible_python_interpreter: /usr/bin/python3 pour les hôtes sur lesquels python3 est installé par défaut

Je pense que c'est la méthode la plus efficace pour résoudre le problème si vous avez le moyen de regrouper vos hôtes en fonction du fait qu'ils aient ou non python3 installé par défaut. Autant que je sache, python3 est disponible sur toutes les versions Ubuntu 16.04 et supérieures.

  • Si tous vos hôtes 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 possèdent pas python3 et que vous disposez d'un moyen de les taguer lorsque vous utilisez un inventaire dynamique (par exemple, le balisage 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 pouvez grouper des hôtes en fonction de leur code python3, vous pouvez procéder comme suit:
# 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 de l'hôte distant et uniquement 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 placer une pièce en haut de chaque livre de lecture avec gather_facts: false qui utilise raw pour 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: true est requis si vous prévoyez d'exécuter la lecture sur des hôtes sur lesquels apt-get n'est pas installé (par exemple, tout système basé sur RHEL), sinon ils se tromperont lors de la première lecture.

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

  1. Doit aller au sommet de chaque livre de jeu (par opposition à l'option 1)
  2. Suppose que apt est sur le système et ignore les erreurs (par opposition à l'option 3)
  3. Les commandes apt-get sont lentes (contrairement à l'option 3)

Option 3 - Lien symbolique /usr/bin/python -> /usr/bin/python3 utilisant raw

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 raw pour exécuter une commande Shell afin de créer un lien symbolique /usr/bin/python -> /usr/bin/python3 si python3 est présent sur le système et quepython n'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 tête de chaque livre de jeu, mais je pense qu'elle est supérieure à plusieurs égards:

  • Crée uniquement le lien symbolique dans le cas spécifique où python3 est présent et python ne l'est pas - il ne remplacera pas Python 2 s'il est déjà installé.
  • Ne suppose pas que apt est installé
  • Peut fonctionner sur tous les hôtes sans traitement d'erreur spécial
  • Est super rapide comparé à n'importe quoi avec apt-get

Évidemment, si vous avez besoin Python 2 installé à /usr/bin/python, cette solution n’est pas valable et l’option 2 est préférable.

Conclusion

  • Je suggère d'utiliser option 1 dans tous les cas si vous le pouvez. 
  • Je suggère d'utiliser option 3 si votre inventaire est vraiment volumineux/complexe et que vous n'avez aucun moyen de regrouper facilement les hôtes avec python3, rendant ainsi option 1 beaucoup plus difficile et sujet aux erreurs.
  • Je ne suggère que option 2 à option 3 si vous avez besoin de Python 2 installé à /usr/bin/python.

Sources

6
percygrunwald

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

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 constaté que cela n’est pas toujours assez long car CloudInit est exécuté assez tard dans le processus de démarrage, de sorte que python2 n’est toujours pas installé juste après la disponibilité de ssh. J'ai donc ajouté une pause au cas où l'instance venait d'être créée:

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

Cela fera parfaitement l'affaire et, comme avantage, vous ne rechercherez pas python2 à chaque exécution et vous n'aurez pas à contourner le problème pour rassembler les faits plus tard.

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

5
Miroslav

@ Miroslav, merci de m'avoir orienté dans la bonne direction. J'ai utilisé user_data dans le module ec2_instance 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     
1
Luuk

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
1
anshul

Beaucoup de réponses .. Merci d'avoir posté cette page aussi!

J'ai creusé un peu et tout était solide avec Ubuntu 14.04LTS, Ubuntu 15.04LTS semblait avoir abandonné la dernière python et Ubuntu 16.04LTS semblait avoir abandonné aptitude.

Je mets l'action suivante dans mon boot avant de faire des appels 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

Si vous gérez become ailleurs, n'hésitez pas à le déshabiller.

Sources:

1
sonjz

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

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

Donc, soit installer Python 2 en utilisant le module raw , par ex.

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

ou définissez ansible_python_interpreter variable dans le fichier d'inventaire, par exemple:

[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
1
kenorb

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

supposons que vous utilisiez le ravitailleur ansible du packer, votre configuration peut ressembler à celle ci-dessous

vous pouvez d'abord installer python en utilisant le provisioner 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"
      ]
    },
1
smakintel.com

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

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

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 ordinateur local. maintenant ça marche!

0
GAV