Ansible ha esito negativo con / bin / sh: 1: / usr / bin / python: non trovato


187

Sto riscontrando un errore che non ho mai visto prima. Ecco il comando e l'errore:

$ 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

Ecco il file create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

Ed ecco il file hosts:

[api]
104.55.47.224

Posso rimuovere la sezione dei ruoli e non arriverà al primo TASK, invece lo farà, lo farà solo sulla linea /bin/sh: 1: /usr/bin/python: not found. Cosa potrebbe succedere qui?


NOTA: nel caso in cui qualcuno esegua il ping dell'indirizzo IP e non riesca a ottenere una risposta, dovresti sapere che ho cambiato l'indirizzo IP dall'incollare il codice.

EDIT python è stato installato localmente, il problema era che non era installato sul computer remoto, che eseguiva Ubuntu 15.04

Risposte:


171

Mi sono imbattuto in questo errore in esecuzione ansible sul server Ubuntu 15.10 , perché viene fornito con Python 3.4.3 e ansible richiede Python 2 .

Ecco come provision.ymlappare ora il mio :

- 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
  • Non dimenticare l'opzione -y (dice sì a tutte le domande) con apt-get (o il modulo raw rimarrà bloccato in silenzio)

  • gather_facts: no la linea è anche critica (perché non possiamo raccogliere fatti senza Python)


12
Quindi i ruoli successivi non possono usare i fatti ... c'è un modo per raccogliere nuovamente i fatti? aha, stackoverflow.com/questions/31054453/…
stephen,

16
Si noti che il 'gather_facts: no' linea è anche critica.
rcreswick,

6
@ surfer190 grande scoperta! Ho anche scoperto che l'aggiunta action: setupcome pre_task finale ha funzionato benissimo :)
mrooney

1
@ surfer190 vedi la mia risposta qui se stai usando EC2 con ansible, puoi usare CloudInit per installare python2 in modo da poter usare raccogliere i fatti come al solito.
Miroslav,

1
Nel caso qualcuno si stia anche chiedendo, non è necessario eseguire l' rawattività per installare Python 2 pre_tasks; tasksfunziona regolarmente anche bene. Ma inserendolo pre_tasks, con un altro compito di chiamare anche il setupmodulo Ansible , si assicureranno che i fatti siano disponibili per tutti i ruoli assegnati all'host.
Kenny Evitt,

125

Ansible 2.2 offre un'anteprima tecnologica del supporto di Python 3. Per trarne vantaggio (quindi non è necessario installare Python 2 su Ubuntu 16.04), basta impostare l' ansible_python_interpreteropzione di configurazione su /usr/bin/python3. Questo può essere fatto su base per host nel file di inventario:

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

Ho provato ad aggiungere / usr / bin / python a questa variabile, ma non ha funzionato. L'aggiunta di python3 invece ha funzionato e questo problema è stato risolto
Deep LF

98

Soluzione 1:

Se stai usando Ansible >2.2.0, puoi impostare l' ansible_python_interpreteropzione di configurazione su /usr/bin/python3:

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

o nel tuo file di inventario:

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

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

Soluzione 2:

Se lo stai usando Ansible <2.2.0, puoi aggiungerli pre_tasksal tuo 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

AGGIORNAMENTO Con ansible 2.8.x, non devi preoccuparti, sta funzionando per python> 3.5 sia per i controller che per i computer di destinazione


Se esegui i tuoi playbook utilizzando i tag, assicurati di aggiungere tag: sempre all'attività di configurazione, altrimenti Ansible non raccoglierà i fatti quando si utilizzano i tag.
Ionut Bajescu,

16
Ho ansible 2.3.0.0e non funziona fuori dagli schemi. Stesso errore pubblicato dall'OP.
The Coder,

Nel caso in cui ciò non sia esplicitamente chiaro, è necessario aggiungerlo al file di inventario host, non a un vars incluso, ovvero, si trova nello stesso file di inventario dell'indirizzo / nome host.
Shawn Mehan,

32

Puoi usare il modulo raw per installare Python sugli host remoti:

- raw: sudo apt-get install python-simplejson

11
Per assicurarti che questo venga chiamato prima delle attività nel tuo ruolo e prima di qualsiasi dipendenza nel tuo meta file, aggiungilo in questo modo al tuo playbook: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld

5
Si noti che in un playbook, è necessario disabilitare anche gather_facts, altrimenti ciò non riuscirà prima di eseguire il comando raw. (gather_facts: no)
rcreswick,

@rcreswick Quello era il mio problema e la tua soluzione ha funzionato per me. Grazie mille. Ho inserito la riga "gather_facts: no" nel mio file .yml principale (setup-ansible.yml) ed eseguito il playbook con questo comando: "ansible-playbook -i hosts setup-ansible.yml --flush-cache -vvvvvv -kK ". Ho usato le opzioni "-kK" con ansible-playbook perché l'installazione di Ubuntu predefinita richiede una password per eseguire "sudo".
Ali Yousefi Sabzevar,

perché stai installando simplejson e non pytghon ma stai parlando dell'installazione di python?
Henning,

@Henning python-simplejsonè scritto in Python e quindi richiede Python. simplejson è anche un requisito per la maggior parte dei moduli core Ansible. Installando python-simplejsontramite apt-get/ yuminstalli anche Python e quindi copri tutte le dipendenze Ansible di base ...
udondan

18

Per riassumere le risposte di tutti gli altri, ecco le impostazioni combinate che hanno funzionato per me:

 - 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

Personalmente ho trovato 3 possibili soluzioni a questo problema che funzionano bene in diverse situazioni:

Opzione 1: impostare ansible_python_interpreter: /usr/bin/python3per gli host python3installati per impostazione predefinita

Penso che questo sia il metodo migliore per risolvere il problema se hai un modo per raggruppare i tuoi host, indipendentemente dal fatto che abbiano python3 installati di default. Per quanto ne so, python3è disponibile su tutte le versioni di Ubuntu 16.04 e successive.

  • Se tutti i tuoi host lo hanno sicuramente python3, puoi aggiungere la variabile al tuo group_vars/all.yml(o equivalente):
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Se alcuni dei tuoi host non hanno python3e hai un modo per taggarli quando usi lo spazio pubblicitario dinamico (ad es. Tag AWS per ec2.py), puoi applicare la variabile a determinati host in questo modo:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Se si utilizza l'inventario statico e si è in grado di raggruppare gli host in base al fatto che abbiano python3, è possibile fare qualcosa del genere:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

Mi piace di più questa opzione perché non richiede modifiche sull'host remoto e solo piccole modifiche alle variabili, al contrario delle opzioni 2 e 3, che richiedono aggiunte a ogni playbook.

Opzione 2: installa Python 2 usando raw

Questa opzione richiede di mettere un gioco in cima a ogni playbook gather_facts: falseche usi rawper installare 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 è necessario se si prevede di eseguire la riproduzione su host che non dispongono di apt-get installati (ad es. qualsiasi cosa basata su RHEL), altrimenti si guasteranno alla prima riproduzione.

Questa soluzione funziona, ma è la più bassa della mia lista per alcuni motivi:

  1. Deve andare in cima a ogni playbook (al contrario dell'opzione 1)
  2. Presuppone che aptsia presente nel sistema e ignora gli errori (rispetto all'opzione 3)
  3. apt-get i comandi sono lenti (al contrario dell'opzione 3)

Opzione 3 - Symlink /usr/bin/python -> /usr/bin/python3 tramiteraw

Non ho visto questa soluzione proposta da nessun altro. Non è l'ideale, ma penso che sia superiore all'opzione 2 in molti modi. Il mio suggerimento è di usare rawper eseguire un comando shell per il collegamento simbolico /usr/bin/python -> /usr/bin/python3se si python3trova sul sistema e python non è:

- 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

Questa soluzione è simile all'opzione 2 in quanto dobbiamo metterla in cima a ogni playbook, ma penso che sia superiore in alcuni modi:

  • Crea il collegamento simbolico solo nel caso specifico python3presente epython non lo è - non sostituirà Python 2 se è già installato
  • Non assume apt sia installato
  • Può essere eseguito su tutti gli host senza gestione di errori speciali
  • È super veloce rispetto a qualsiasi cosa con apt-get

Ovviamente se ne hai bisogno Python 2 installato su/usr/bin/python , questa soluzione è assolutamente no e l'opzione 2 è migliore.

Conclusione

  • Suggerisco di usare l' opzione 1 in tutti i casi, se possibile.
  • Ti suggerisco di utilizzare l' opzione 3 se il tuo inventario è davvero grande / complesso e non hai modo di raggruppare facilmente gli host python3, facendo l' opzione 1 molto più difficile e soggetta a errori.
  • Suggerisco solo l' opzione 2 rispetto all'opzione 3 se è necessario installare Python 2 su /usr/bin/python.

fonti


13

È necessario Python 2.7 per eseguire Ansible. Su Ubuntu 16.04, puoi installarlo tramite questo comando:

sudo apt-get install python-minimal

Dopo quello, potrei correre

ansible-playbook -i inventories/staging playbook.yml

Esegui ansible correttamente

Per ulteriori informazioni, consultare Utilizzo di Ansible su Ubuntu 16.04


12

Cosa ho usato per farlo funzionare su Ubuntu 15.10 su una nuova goccia di 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

Per Ubuntu 16.04 su un nuovo SSD OVH, ho dovuto apt-get upgrade prima che fossero disponibili i pacchetti python2.


8

Ho scoperto che in realtà è possibile avere più giochi in un singolo playbook, quindi la mia configurazione ora contiene un gioco di "provisioning delle dipendenze" che funziona su tutti gli host e altri giochi per host specifici. Quindi non di piùpre_tasks .

Per esempio:

- 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

Come altri hanno detto, ciò è dovuto alla mancanza di python2. Altre risposte qui forniscono una soluzione alternativa pre_taskse gather_facts: no, tuttavia se sei su EC2 e fai girare l'istanza con ansible puoi usare l' user_dataopzione:

- 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

Quindi le persone di solito aspettano che ssh sia disponibile in questo modo:

  - 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

Tuttavia, ho scoperto che questo non è sempre abbastanza lungo poiché CloudInit viene eseguito abbastanza tardi nel processo di avvio, quindi python2 potrebbe non essere installato subito dopo la disponibilità di ssh. Quindi ho aggiunto una pausa nel caso in cui l'istanza fosse appena stata creata:

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

Questo farà il lavoro alla perfezione e come vantaggio non stai controllando python2 ad ogni corsa e non devi fare alcuna soluzione alternativa per raccogliere fatti in seguito.

Sono sicuro che altri provider di cloud forniscono funzionalità CloudInit simili, quindi adattati al tuo caso d'uso.


3

Chi utilizza Packer può trovare utile la soluzione seguente

supponiamo che tu usi anser provisioner di packer, la tua configurazione potrebbe apparire come di seguito

è possibile installare python utilizzando il provisioning della shell, quindi configurare l'opzione ansible_python_intepreter come mostrato di seguito

"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

Per impostazione predefinita, Ansible richiede Python 2 , tuttavia, Ansible 2.2+ può funzionare anche con Python 3 .

Quindi installa Python 2 usando il rawmodulo , ad es

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

o imposta la ansible_python_interpretervariabile nel file di inventario, come:

[local]
localhost ansible_python_interpreter="env python3"

Per Docker, è possibile aggiungere la seguente riga:

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

o eseguilo come:

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

1

Secondo questo Gist è possibile installare Python2 su Ubuntu 16.04 come segue:

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

Molte risposte .. Grazie per aver pubblicato come ho iniziato anche da questa pagina!

Ho scavato un po 'ed è stato solido con Ubuntu 14.04LTS, Ubuntu 15.04LTS sembra aver lasciato cadere l'ultimo python, e Ubuntu 16.04LTS sembra essere cadutoaptitude .

Ho messo la seguente azione nel mio bootstrap prima di fare qualsiasi aptchiamata:

- 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

Se ci riesci become altrove, sentiti libero di spogliarlo.

fonti:


1

Sono stato in grado di risolvere lo stesso problema installando Python sulla macchina di destinazione, ovvero la macchina a cui vogliamo SSH. Avevo usato il seguente comando:

sudo apt-get install python-minimal

1

@ Miroslav, grazie per avermi indicato nella giusta direzione. Ho usato user_datainec2_instance modulo e funziona come un piacere.

ie

- 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

Puoi indicare a Ubuntu 18.04 che vuoi usare python3 come prima priorità /usr/bin/python.

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

0

Ho avuto lo stesso problema, fino a quando ho capito che è necessario installare anche Python sull'host remoto e sul proprio computer locale. ora funziona!


-2

Ci siamo appena imbattuti in questo.

Distribuiamo ubuntu 16.04 su un vagabondo quindi se non stai usando vagabondo il mio commento è inutile.

Abbiamo installato i seguenti plug-in vagabondi (trigger, shell-commander) e otteniamo python 2.7.6 installato sulla macchina (che non erano privi di plug-in thioose) e dopo ansible può essere distribuito

Era il nostro ultimo test, altrimenti stavamo per includere questa installazione in un comando shell nel file Vagrant

Spero che possa aiutare qualcuno


2
Se si utilizza Ansible, la soluzione Ansible di seguito è la soluzione corretta. Sperare che Vagrant lo installi accidentalmente per te come effetto collaterale di alcuni plugin sembra chiedere problemi.
Paul Becotte,

Mi scusi, ma come si può eseguire un pretask ansible se non ha Python ??? Ho provato la soluzione e non è riuscito durante l'impostazione dell'attività quindi evento prima dell'attività pre. Il comando vagrant shell nel file vagrant È il modo migliore per farlo (ovviamente per il caso vagrant) ma noto solo che il plugin vagrant che avevo installato sul mio dev fa il lavoro. Non mi affido al plug-in ma al file vagrant, ho appena sottolineato che funziona anche con il plug-in ma il file vagrant è una scelta migliore (anche per l'automazione) perché non è necessario eseguire manualmente alcuna operazione su ciascuno
destro

1
Ho copiato quel blocco di codice esattamente com'era e ha funzionato esattamente come descritto prima di pubblicare la tua risposta. Credo che probabilmente non hai inserito la gather_facts: nolinea che richiede Python. L'altra possibilità è che hai bisogno anche di Python sul computer host, ma immagino che ti avrebbe causato errori anche prima nel processo.
Paul Becotte,

ho copiato anche la pasta ma era venerdì notte al lavoro. Non riesco a ricordare caldamente se ho preso la parte gather_fact. Ad ogni modo, stamattina, su un altro computer, è stato di nuovo risolto e ho appena inserito il comando in vagrantfile, è abbastanza per me finché non andiamo in produzione su un vero server.
Proverò di
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.