Falha no Ansible com / bin / sh: 1: / usr / bin / python: não encontrado


187

Estou com um erro que nunca vi antes. Aqui está o comando e o erro:

$ 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

Aqui está o arquivo create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

E aqui está o arquivo hosts:

[api]
104.55.47.224

Eu posso remover a seção de funções e ela não chegará à primeira TAREFA, mas sim apenas a linha /bin/sh: 1: /usr/bin/python: not found . O que poderia estar acontecendo aqui?


NOTA: Caso alguém esteja executando ping no endereço IP e não obtenha uma resposta, você deve saber que eu mudei o endereço IP desde a colagem do código.

O EDIT python foi instalado localmente, o problema era que não estava instalado na máquina remota, que estava executando o Ubuntu 15.04

Respostas:


171

Eu me deparei com esse erro ao executar o ansible no servidor Ubuntu 15.10 , porque ele é fornecido com o Python 3.4.3 e o ansible requer o Python 2 .

É assim que minha provision.ymlaparência agora:

- 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ão esqueça a opção -y (diz sim para todas as perguntas) com o apt-get (ou o módulo bruto ficará bloqueado silenciosamente)

  • gather_facts: no A linha também é crítica (porque não podemos coletar fatos sem python)


12
Então os papéis subseqüentes não podem usar fatos ... existe uma maneira de reunir fatos novamente? Aha, stackoverflow.com/questions/31054453/…
stephen

16
Observe que a linha 'gather_facts: no' também é crítica.
rcreswick

6
@ surfer190 ótimo encontrar! Eu também achei que a adição action: setupcomo o pre_task final também funcionou muito bem :)
mrooney

1
@ surfer190 veja minha resposta aqui, se você estiver usando o EC2 com o ansible, você pode usar o CloudInit para instalar o python2 para que você possa coletar fatos como de costume.
Miroslav

1
Caso alguém também esteja se perguntando, não é necessário executar a rawtarefa para instalar o Python 2 pre_tasks; tasksTrabalhos regulares também. Mas colocá-lo pre_tasks, com outra tarefa para chamar o setupmódulo Ansible , garantirá que os fatos estejam disponíveis para todas as funções atribuídas ao host.
precisa saber é o seguinte

125

O Ansible 2.2 apresenta uma prévia técnica do suporte ao Python 3. Para tirar proveito disso (para que você não precise instalar o Python 2 no Ubuntu 16.04), basta definir a ansible_python_interpreteropção de configuração como /usr/bin/python3. Isso pode ser feito por host no seu arquivo de inventário:

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

Tentei adicionar / usr / bin / python a essa variável, mas não funcionou. Adicionando python3 vez trabalhou e esta questão ficou fixo
Profundo LF

97

Solução 1:

Se você estiver usando Ansible >2.2.0, poderá definir a ansible_python_interpreteropção de configuração para /usr/bin/python3:

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

ou no seu arquivo de inventário:

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

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

Solução 2:

Se você estiver usando Ansible <2.2.0, poderá adicioná-los pre_tasksao seu 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

ATUALIZAÇÃO Com ansible 2.8.x, você não precisa se preocupar com isso, está funcionando imediatamente para python> 3.5 para o (s) controlador (es) e as máquinas de destino


Se você executar seus playbooks usando tags, adicione tags: sempre à tarefa de configuração - caso contrário, o ansible não coletará os fatos quando você estiver usando tags.
Ionut Bajescu

16
Eu tenho ansible 2.3.0.0e não funciona fora da caixa. Mesmo erro postado pelo OP.
The Coder

Caso isso não esteja explicitamente claro, você deve adicioná-lo ao arquivo de inventário do host, não aos vars incluídos, ou seja, ele fica no mesmo arquivo de inventário que o endereço / nome do host.
precisa

32

Você pode usar o módulo bruto para instalar o Python nos hosts remotos:

- raw: sudo apt-get install python-simplejson

11
Para garantir que isso seja chamado antes das tarefas em sua função e antes de qualquer dependência no seu arquivo meta, adicione-o assim ao seu manual: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld

5
Observe que em um manual, você também deve desativar o gather_facts, ou isso falhará antes de executar o comando bruto. (reúna_fatos: não)
rcreswick 13/07

@rcreswick Esse era o meu problema e sua solução funcionou para mim. Muito obrigado. Coloquei a linha "gather_facts: no" no meu arquivo .yml principal (setup-ansible.yml) e executei o manual com este comando: "ansible-playbook -i hospeda setup-ansible.yml --flush-cache -vvvvvv -kK " Eu usei as opções "-kK" com o ansible-playbook porque a instalação padrão do ubuntu precisa de senha para executar o "sudo".
Ali Yousefi Sabzevar

por que você está instalando simplejson e não pytghon, mas fala sobre a instalação de python?
Henning Henning

@ Henning python-simplejsoné escrito em Python e, portanto, requer Python. O simplejson também é um requisito para a maioria dos módulos principais do Ansible. Ao instalar python-simplejsonatravés apt-get/ yumvocê também instalar o Python e, portanto, abranger todas as dependências ansible básicos ...
udondan

18

Para resumir as respostas de todos os outros, aqui estão as configurações combinadas que funcionaram para mim:

 - 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

Eu, pessoalmente, encontrei 3 soluções possíveis para esse problema que funcionam bem em diferentes situações:

Opção 1 - Configure ansible_python_interpreter: /usr/bin/python3para hosts que foram python3instalados por padrão

Eu acho que esse é o método superior para resolver o problema se você tiver uma maneira de agrupar seus hosts, independentemente de eles terem ou não sido python3instalados por padrão. Tanto quanto sei, python3está disponível em todas as versões 16.04 e posteriores do Ubuntu.

  • Se todos os seus hosts tiverem definitivamente python3, você poderá adicionar a variável ao seu group_vars/all.yml(ou equivalente):
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Se alguns de seus hosts não tiverem python3e você tiver uma maneira de marcá-los ao usar o inventário dinâmico (por exemplo, marcação da AWS ec2.py), você poderá aplicar a variável a determinados hosts como este:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Se você usa inventário estático e pode agrupar hosts com base no que eles têm python3, você pode fazer algo assim:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

Eu gosto mais dessa opção porque ela não requer alterações no host remoto e apenas pequenas alterações nas variáveis, em oposição às opções 2 e 3, que exigem adições a todos os manuais.

Opção 2 - Instale o Python 2 usando raw

Esta opção requer colocar uma reprodução na parte superior de todos os playbooks gather_facts: falseusados rawpara instalar 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 é necessário se você planeja executar a peça em hosts que não possuem apt-get instalado (por exemplo, qualquer coisa baseada em RHEL), caso contrário, eles ocorrerão na primeira reprodução.

Esta solução funciona, mas é a mais baixa da minha lista por alguns motivos:

  1. Precisa ir no topo de cada manual (em oposição à opção 1)
  2. Assume apt está no sistema e ignora erros (em oposição à opção 3)
  3. apt-get comandos são lentos (em oposição à opção 3)

Opção 3 - Symlink /usr/bin/python -> /usr/bin/python3 usandoraw

Eu não vi essa solução proposta por mais ninguém. Não é o ideal, mas acho que é superior à opção 2 de várias maneiras. Minha sugestão é usar rawpara executar um comando shell para ligar simbolicamente /usr/bin/python -> /usr/bin/python3se python3estiver no sistema e python não estiver:

- 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

Essa solução é semelhante à opção 2, pois precisamos colocá-la no topo de todos os manuais, mas acho que é superior em alguns aspectos:

  • Cria apenas o link simbólico no caso específico python3presente epython não está - ele não substituirá o Python 2 se já estiver instalado
  • Não assume apt está instalado
  • Pode ser executado em todos os hosts sem nenhum tratamento especial de erros
  • É super rápido comparado a qualquer coisa com apt-get

Obviamente, se você precisar do Python 2 instalado em/usr/bin/python , esta solução é proibida e a opção 2 é melhor.

Conclusão

  • Sugiro usar a opção 1 em todos os casos, se puder.
  • Sugiro usar a opção 3 se seu inventário for realmente grande / complexo e você não tiver como agrupar hosts facilmente python3, tornando a opção 1 muito mais difícil e propensa a erros.
  • Eu só sugiro a opção 2 sobre a opção 3 se você precisar do Python 2 instalado em /usr/bin/python.

Fontes


13

Você precisa do python 2.7 para executar o Ansible. No Ubuntu 16.04, você pode instalá-lo através deste comando:

sudo apt-get install python-minimal

Depois disso, eu poderia correr

ansible-playbook -i inventories/staging playbook.yml

Execute ansible com sucesso

Por favor, verifique mais em Using ansible no Ubuntu 16.04


12

O que eu usei para fazer isso funcionar no ubuntu 15.10 em uma nova gota do 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 o ubuntu 16.04 em um novo SSD da OVH, tive que fazer o apt-get upgrade antes que os pacotes python2 estivessem disponíveis.


8

Eu descobri que é realmente possível ter várias execuções em um único manual, então minha configuração agora contém uma execução de "provisionamento de dependência" que é executada em todos os hosts e outras executadas em hosts específicos. Então não maispre_tasks .

Por exemplo:

- 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

Como outros disseram, isso ocorre devido à falta do python2. Outras respostas aqui fornecem uma solução alternativa pre_taskse gather_facts: no, no entanto, se você estiver no EC2 e girar a instância com ansible, poderá usar a user_dataopção:

- 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

Em seguida, as pessoas geralmente esperam que o ssh esteja disponível assim:

  - 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

No entanto, descobri que isso nem sempre é longo o suficiente, pois o CloudInit é executado bastante tarde no processo de inicialização, portanto o python2 ainda pode não ser instalado logo após o ssh estar disponível. Então, adicionei uma pausa caso a instância tenha sido criada:

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

Isso fará o trabalho perfeitamente e, como vantagem, você não verifica o python2 a cada execução e não precisa executar nenhuma solução alternativa para reunir fatos posteriormente.

Tenho certeza de que outros provedores de nuvem fornecem funcionalidade semelhante ao CloudInit, portanto, adapte-se ao seu caso de uso.


3

Aqueles que usam o Packer podem encontrar abaixo a solução útil

vamos supor que você use o provedor de pacotes ansible, sua configuração pode parecer abaixo

você pode instalar o python usando o provisionador de shell primeiro e, em seguida, configure a opção ansible_python_intepreter, como mostrado abaixo

"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

Por padrão, o Ansible requer o Python 2 ; no entanto, o Ansible 2.2+ também pode funcionar com o Python 3 .

Portanto, instale o Python 2 usando o rawmódulo , por exemplo

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

ou defina a ansible_python_interpretervariável no arquivo de inventário, como:

[local]
localhost ansible_python_interpreter="env python3"

Para o Docker, você pode adicionar a seguinte linha:

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

ou execute-o como:

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

1

De acordo com este Gist, você pode instalar o Python2 no Ubuntu 16.04 da seguinte maneira:

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

Muitas respostas .. Obrigado por postar como também comecei nesta página!

Eu pesquisei um pouco e estava sólido com o Ubuntu 14.04LTS, o Ubuntu 15.04LTS parecia ter caído o mais recente pythone o Ubuntu 16.04LTS parece ter caído aptitude.

Coloquei a seguinte ação no meu bootstrap antes de fazer qualquer aptchamada:

- 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 você gerencia em becomeoutro lugar, sinta-se à vontade para removê-lo.

Fontes:


1

Consegui resolver o mesmo problema instalando o Python na máquina de destino, ou seja, a máquina na qual queremos fazer o SSH. Eu tinha usado o seguinte comando:

sudo apt-get install python-minimal

1

@Miroslav, obrigado por me apontar na direção certa. Eu usei user_datanoec2_instance módulo e funciona como um presente.

Ou seja,

- 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

Você pode indicar ao Ubuntu 18.04 que deseja usar python3 como a primeira prioridade para /usr/bin/python.

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

0

Eu tive o mesmo problema, até perceber que você também precisa instalar o python no host remoto e na sua máquina local. agora funciona!


-2

Nós apenas nos deparamos com isso.

Nós implantamos o ubuntu 16.04 em um vagrant, portanto, se você não estiver usando o vagrant, meu comentário será inútil.

Instalamos os seguintes plugins vagantes (trigger, shell-commander) e obtemos o python 2.7.6 instalado na máquina (que não estava sem os plugins thioose) e, depois que o ansible pode implantar

Foi nosso último teste, caso contrário estávamos prestes a incluir esta instalação em um comando shell no arquivo Vagrant

Espero que possa ajudar alguém


2
Se você estiver usando o Ansible, a solução do Ansible abaixo é a correção correta. Esperar que o Vagrant o instale acidentalmente para você como efeito colateral de alguns plugins parece pedir problemas.
Paul Becotte 17/06/16

Com licença, mas como você pode executar um ansk pretask se não tiver python ??? Eu tentei a solução e ela falhou na configuração da tarefa, portanto, evento antes da pré-tarefa. O comando vagrant shell no arquivo vagrant É a melhor maneira de fazer isso (no caso do vagrant, é claro), mas eu apenas observei que o plugin vagrant que eu havia instalado no meu dev faz o trabalho. Eu não estou confiando no plug-in, mas no arquivo vagrant, apenas apontei que ele também funciona com o plug-in, mas o arquivo vagrant é uma escolha melhor (também para automação) porque você manualmente não precisa fazer nada em cada destruir / provisão
wadoo

1
Copiei esse bloco de código exatamente como era e funcionou exatamente como descrito antes de você postar sua resposta. Acredito que você provavelmente não colocou a gather_facts: nolinha em que requer python. A outra possibilidade é que você também precise de python na máquina host, mas acho que isso teria causado erros ainda mais cedo no processo.
Paul Becotte

copiei colar também, mas foi sexta-feira nigth no trabalho. Honestamente, não me lembro se participei da parte gather_fact. De qualquer forma, em outro computador, o identificamos novamente esta manhã e eu acabei de colocar o comando no vagrantfile, é o suficiente para mim até que possamos iniciar a produção no servidor real. Vou testar novamente com uma mente fresca (de modo não uma noite de sexta-feira) a resposta;)
wadoo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.