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.