Ansible falla con / bin / sh: 1: / usr / bin / python: no encontrado

187

Me encuentro con un error que nunca había visto antes. Aquí está el comando y el error:

$ 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

Aquí está el archivo create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

Y aquí está el archivo de hosts:

[api]
104.55.47.224

Puedo eliminar la sección de roles y no llegará a la primera TAREA, sino que solo llegará a la línea /bin/sh: 1: /usr/bin/python: not found. ¿Qué podría estar pasando aquí?


NOTA: En caso de que alguien haga ping a la dirección IP y no pueda obtener una respuesta, debe saber que he cambiado la dirección IP desde que pegué el código.

EDITAR Python se instaló localmente, el problema era que no estaba instalado en la máquina remota, que ejecutaba Ubuntu 15.04

jdavis
fuente

Respuestas:

171

Me topé con este error al ejecutar ansible en el servidor Ubuntu 15.10 , porque se incluye con Python 3.4.3 y ansible requiere Python 2 .

Así es como se provision.ymlve ahora:

- 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
  • No olvide la opción -y (dice sí a todas las preguntas) con apt-get (o el módulo sin procesar se atascará en silencio)

  • gather_facts: no la línea también es crítica (porque no podemos recopilar datos sin python)

Lakesare
fuente
12
Entonces, los roles posteriores no pueden usar hechos ... ¿hay alguna manera de reunir hechos nuevamente? aha, stackoverflow.com/questions/31054453/…
stephen
16
Tenga en cuenta que la línea 'collect_facts: no' también es crítica.
rcreswick
66
@ surfer190 gran descubrimiento! También encontré que agregar action: setupcomo la pre_tarea final también funcionó muy bien :)
mrooney
1
@ surfer190 vea mi respuesta aquí si está utilizando EC2 con ansible, puede usar CloudInit para instalar python2 para poder recopilar datos como de costumbre.
Miroslav
1
En caso de que alguien también se pregunte, no es necesario ejecutar la rawtarea para instalar Python 2 pre_tasks; regular tasksfunciona bien también. Pero ponerlo pre_tasks, junto con otra tarea para llamar al setupmódulo Ansible también, garantizará que los hechos estén disponibles para cualquier rol asignado al host.
Kenny Evitt
125

Ansible 2.2 presenta una vista previa técnica del soporte de Python 3. Para aprovechar esto (para que no tenga que instalar Python 2 en Ubuntu 16.04), simplemente configure la ansible_python_interpreteropción de configuración en /usr/bin/python3. Esto se puede hacer por host en su archivo de inventario:

[db]
123.123.123.123 ansible_python_interpreter=/usr/bin/python3
jamix
fuente
Intenté agregar / usr / bin / python a esta variable, pero no funcionó. Agregar python3 en su lugar funcionó y este problema se solucionó
Deep LF
98

Solución 1:

Si está utilizando Ansible >2.2.0, puede configurar la ansible_python_interpreteropción de configuración para /usr/bin/python3:

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

o en su archivo de inventario:

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

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

Solución 2:

Si está utilizando Ansible <2.2.0, puede agregar estos pre_tasksa su libro de jugadas:

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

ACTUALIZACIÓN Con ansible 2.8.x, no tiene que preocuparse por eso, está funcionando de inmediato para python> 3.5 para el controlador y la (s) máquina (s) de destino

Arbab Nazar
fuente
Si ejecuta sus libros de jugadas usando etiquetas, asegúrese de agregar etiquetas: siempre a la tarea de configuración; de lo contrario, ansible no recopilará los datos cuando esté usando etiquetas.
Ionut Bajescu
16
Tengo ansible 2.3.0.0y no funciona fuera de la caja. El mismo error publicado por el OP.
The Coder
En caso de que esto no esté explícitamente claro, debe agregar esto al archivo de inventario del host, no a los vars incluidos, es decir, se encuentra en el mismo archivo de inventario que la dirección / nombre del host.
Shawn Mehan
32

Puede usar el módulo sin procesar para instalar Python en los hosts remotos:

- raw: sudo apt-get install python-simplejson
udondan
fuente
11
Para asegurarse de que esto se llame antes de las tareas en su rol, y antes de cualquier dependencia en su metaarchivo, agréguelo así a su libro de jugadas: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld
55
Tenga en cuenta que en un libro de jugadas, debe también gather_facts deshabilitar, o se producirá un error antes de ejecutar el comando prima. (collect_facts: no)
rcreswick
@rcreswick Ese fue mi problema y su solución funcionó para mí. Muchas gracias. Puse la línea "collect_facts: no" en mi archivo .yml principal (setup-ansible.yml) y ejecuté el libro de jugadas con este comando: "ansible-playbook -i hosts setup-ansible.yml --flush-cache -vvvvvv -kK ". Utilicé las opciones "-kK" con ansible-playbook porque la instalación predeterminada de ubuntu necesita contraseña para hacer "sudo".
Ali Yousefi Sabzevar
¿por qué estás instalando simplejson y no pytghon sino que hablas de instalar python?
Henning
@Henning python-simplejsonestá escrito en Python y, por lo tanto, requiere Python. simplejson también es un requisito para la mayoría de los módulos principales de Ansible. Mediante la instalación python-simplejsona través de apt-get/ yumtambién se instala Python y por lo tanto, cubrir todas las dependencias Ansible básicas ...
udondan
18

Para resumir las respuestas de todos los demás, aquí están las configuraciones combinadas que funcionaron para mí:

 - 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
Poli
fuente
14

Personalmente encontré 3 posibles soluciones a este problema que funcionan bien en diferentes situaciones:

Opción 1: configurada ansible_python_interpreter: /usr/bin/python3para hosts que se han python3instalado de manera predeterminada

Creo que este es el método superior para resolver el problema si tiene una forma de agrupar sus hosts por si se han python3instalado o no de manera predeterminada. Que yo sepa, python3está disponible en todas las versiones de Ubuntu 16.04 y superiores.

  • Si todos sus hosts definitivamente lo tienen python3, puede agregar la variable a su group_vars/all.yml(o equivalente):
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Si algunos de sus hosts no lo tienen python3y tiene una forma de etiquetarlos cuando usa un inventario dinámico (por ejemplo, etiquetado de AWS ec2.py), puede aplicar la variable a ciertos hosts como este:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Si usa un inventario estático y puede agrupar hosts en función de si tienen python3, podría hacer algo como esto:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

Esta opción me gusta más porque no requiere cambios en el host remoto y solo cambios menores en las variables, a diferencia de las opciones 2 y 3, que requieren adiciones a cada libro de jugadas.

Opción 2: instalar Python 2 usando raw

Esta opción requiere poner una jugada en la parte superior de cada libro de jugadas con la gather_facts: falseque se rawinstala 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: truees necesario si planea ejecutar la reproducción en hosts que no se han apt-getinstalado (por ejemplo, cualquier cosa basada en RHEL), de lo contrario, se producirá un error en la primera reproducción.

Esta solución funciona, pero es la más baja en mi lista por varias razones:

  1. Debe ir al principio de cada libro de jugadas (en oposición a la opción 1)
  2. Asume que aptestá en el sistema e ignora los errores (a diferencia de la opción 3)
  3. apt-get los comandos son lentos (a diferencia de la opción 3)

Opción 3: enlace simbólico /usr/bin/python -> /usr/bin/python3utilizandoraw

No he visto esta solución propuesta por nadie más. No es ideal, pero creo que es superior a la opción 2 en muchos sentidos. Mi sugerencia es utilizar rawpara ejecutar un comando de shell para enlace simbólico /usr/bin/python -> /usr/bin/python3si python3está en el sistema y python no es:

- 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

Esta solución es similar a la opción 2 en que necesitamos ponerla en la parte superior de cada libro de jugadas, pero creo que es superior en algunos aspectos:

  • Solo crea el enlace simbólico en el caso específico que python3está presente y pythonno lo está: no anulará Python 2 si ya está instalado
  • No asume que aptestá instalado
  • Puede ejecutarse contra todos los hosts sin ningún manejo especial de errores
  • Es súper rápido en comparación con cualquier cosa con apt-get

Obviamente, si necesita instalar Python 2 en /usr/bin/python, esta solución es una opción prohibida y la opción 2 es mejor.

Conclusión

  • Sugiero usar la opción 1 en todos los casos si puedes.
  • Sugiero usar la opción 3 si su inventario es realmente grande / complejo y no tiene forma de agrupar hosts fácilmente python3, lo que hace que la opción 1 sea mucho más difícil y propensa a errores.
  • Solo sugiero la opción 2 sobre la opción 3 si necesita instalar Python 2 en /usr/bin/python.

Fuentes

Percygrunwald
fuente
13

Necesita Python 2.7 para ejecutar Ansible. En Ubuntu 16.04, puede instalarlo mediante este comando:

sudo apt-get install python-minimal

Después de eso, podría correr

ansible-playbook -i inventories/staging playbook.yml

Ejecute ansible con éxito

Por favor, consulte más en el uso de Ansible en Ubuntu 16.04

phanvugiap
fuente
12

Lo que solía hacer que funcionara en ubuntu 15.10 en una nueva gota de 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

Para ubuntu 16.04 en un SSD OVH nuevo, tuve que apt-get upgrade antes de que los paquetes python2 estuvieran disponibles.

deadghost
fuente
8

Descubrí que en realidad es posible tener múltiples jugadas en un solo libro de jugadas, por lo que mi configuración ahora contiene una jugada de "aprovisionamiento de dependencias" que se ejecuta en todos los hosts y otras jugadas para hosts específicos. Entonces no más pre_tasks.

Por ejemplo:

- 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
fuente
6

Como otros dijeron, esto se debe a la falta de python2. Otras respuestas aquí proporcionan una solución alternativa pre_tasksy gather_facts: no, sin embargo, si está en EC2 y activa la instancia con ansible, puede usar la user_dataopción:

- 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

Entonces la gente generalmente espera que ssh esté disponible de esta manera:

  - 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

Sin embargo, he descubierto que esto no siempre es suficiente, ya que CloudInit se ejecuta bastante tarde en el proceso de arranque, por lo que Python2 podría no instalarse justo después de que ssh esté disponible. Así que he agregado una pausa en caso de que la instancia se haya creado:

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

Esto hará el trabajo perfectamente y, como ventaja, no está buscando python2 en cada ejecución y no tiene que hacer ninguna solución para recopilar datos más adelante.

Estoy seguro de que otros proveedores de la nube ofrecen una funcionalidad similar de CloudInit, así que adáptese a su caso de uso.

Miroslav
fuente
3

Los que usan Packer pueden encontrar útil la siguiente solución

supongamos que usa el aprovisionador ansible de empaquetador, su configuración puede verse a continuación

primero puede instalar python usando el aprovisionador de shell y luego configurar la opción ansible_python_intepreter como se muestra a continuación

"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
fuente
2

De manera predeterminada, Ansible requiere Python 2 , sin embargo, Ansible 2.2+ también puede funcionar con Python 3 .

Entonces, instale Python 2 usando el rawmódulo , por ejemplo

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

o establecer ansible_python_interpretervariable en el archivo de inventario, como:

[local]
localhost ansible_python_interpreter="env python3"

Para Docker, puede agregar la siguiente línea:

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

o ejecutarlo como:

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

De acuerdo con este Gist , puede instalar Python2 en Ubuntu 16.04 de la siguiente manera:

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

Muchas respuestas ... ¡Gracias por publicar ya que empecé desde esta página también!

Investigué un poco y fue sólido con Ubuntu 14.04LTS, Ubuntu 15.04LTS parecía haber caído lo último python, y Ubuntu 16.04LTS parece haber caído aptitude.

Puse la siguiente acción en mi rutina de carga antes de hacer cualquier aptllamada:

- 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 se las arregla en becomeotro lugar, no dude en despojarlo.

Fuentes:

sonjz
fuente
1

Pude solucionar el mismo problema instalando Python en la máquina de destino, es decir, la máquina a la que queremos SSH. Había usado el siguiente comando:

sudo apt-get install python-minimal
anshul
fuente
1

@Miroslav, gracias por señalarme en la dirección correcta. También utilicé user_dataen el ec2_instancemódulo y funciona como un regalo.

Es decir

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

Puede indicarle a Ubuntu 18.04 que desea usar python3 como la primera prioridad para /usr/bin/python.

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

Tuve el mismo problema, hasta que me di cuenta de que también necesita instalar Python en el host remoto, así como en su propia máquina local. ¡ahora funciona!

GAV
fuente
-2

Nos topamos con esto.

Implementamos ubuntu 16.04 en un vagabundo, por lo que si no está usando vagabundo, mi comentario no tiene sentido.

Instalamos los siguientes complementos vagabundos (trigger, shell-commander) y obtenemos python 2.7.6 instalado en la máquina (que no carecía de complementos tioose) y después de que ansible se puede implementar

Era nuestra última prueba, de lo contrario, estábamos a punto de incluir esta instalación en un comando de shell en el archivo Vagrant

Espero que pueda ayudar a alguien

wadoo
fuente
2
Si está utilizando Ansible, la solución Ansible a continuación es la solución correcta. Esperar que Vagrant lo instale accidentalmente para usted como efecto secundario de algunos complementos parece pedir problemas.
Paul Becotte
Disculpe, pero ¿cómo puede ejecutar una tarea previa ansible si no tiene Python? Probé la solución y falla en la configuración de la tarea, por lo que es un evento antes de la tarea previa. El comando de vagabundo shell en el archivo vagabundo ES la mejor manera de hacerlo (para el caso vagabundo, por supuesto), pero acabo de notar que el plugin vagabundo que había instalado en mi dev hace el trabajo. No estoy confiando en el complemento, sino en el archivo vagabundo, solo señalé que funciona también con el complemento, pero el archivo vagabundo es una mejor opción (también para la automatización) porque manualmente no necesita hacer nada en cada uno destruir / provisión
wadoo
1
Copié ese bloque de código exactamente como estaba, y funcionó exactamente como se describe justo antes de publicar su respuesta. Creo que probablemente no pusiste la gather_facts: nolínea que requiere python. La otra posibilidad es que también necesite python en la máquina host, pero supongo que eso le habría causado errores incluso antes en el proceso.
Paul Becotte
Copié pasta también pero era viernes por la noche en el trabajo. Sinceramente, no puedo recordar si tomé la parte de collect_fact. De todos modos, en otra computadora lo presioné nuevamente esta mañana y acabo de poner el comando en vagrantfile, es suficiente para mí hasta que pasemos a producción en un servidor real. Voy a probar de nuevo con una mente fresca (así que no es un viernes por la noche) la respuesta;)
wadoo