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.
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: no
line est également critique (car nous ne pouvons pas rassembler les faits sans python)
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
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
Vous pouvez utiliser le module raw pour installer Python sur les hôtes distants:
- raw: Sudo apt-get install python-simplejson
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
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
Veuillez vérifier plus à Utiliser ansible sur Ubuntu 16.04
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.
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
# ....
J'ai personnellement trouvé 3 solutions possibles à ce problème qui fonctionnent bien dans différentes situations:
ansible_python_interpreter: /usr/bin/python3
pour les hôtes sur lesquels python3
est installé par défautJe 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.
python3
, vous pouvez ajouter la variable à votre group_vars/all.yml
(ou équivalent):# group_vars/all.yml
ansible_python_interpreter: /usr/bin/python3
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
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.
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:
apt
est sur le système et ignore les erreurs (par opposition à l'option 3)apt-get
sont lentes (contrairement à l'option 3)/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:
python3
est présent et python
ne l'est pas - il ne remplacera pas Python 2 s'il est déjà installé.apt
est installé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.
python3
, rendant ainsi option 1 beaucoup plus difficile et sujet aux erreurs./usr/bin/python
.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.
@ 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
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
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:
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.
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
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"
]
},
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
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!