Сбой Ansible с / bin / sh: 1: / usr / bin / python: не найден


187

Я сталкиваюсь с ошибкой, которую никогда не видел прежде. Вот команда и ошибка:

$ 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

Вот файл create_api.yml:

---

- hosts: api
  remote_user: root
  roles:
    - api

И вот файл hosts:

[api]
104.55.47.224

Я могу удалить раздел ролей, и он не попадет в первую ЗАДАЧУ, вместо этого он сделает это только в строке /bin/sh: 1: /usr/bin/python: not found. Что здесь может происходить?


ПРИМЕЧАНИЕ. Если кто-либо пингует IP-адрес и не получает ответ, вы должны знать, что я изменил IP-адрес с момента вставки кода.

EDIT Python был установлен локально, проблема была в том, что он не был установлен на удаленной машине, на которой работал Ubuntu 15.04

Ответы:


171

Я наткнулся на эту ошибку при запуске ansible на сервере Ubuntu 15.10 , потому что он поставляется с Python 3.4.3, а ansible требует Python 2 .

Вот так 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
  • Не забудьте опцию -y (ответьте «да» на все вопросы) с помощью apt-get (иначе модуль raw будет зависать молча)

  • gather_facts: no линия также важна (потому что мы не можем собрать факты без питона)


12
Тогда последующие роли не могут использовать факты ... есть ли способ собрать факты снова? ага, stackoverflow.com/questions/31054453/…
Стивен

16
Обратите внимание, что строка 'collect_facts: no' также важна.
rcreswick

6
@ Surfer190 отличная находка! Я также обнаружил, что добавление action: setupв качестве окончательного pre_task также отлично работало :)
mrooney

1
@ surfer190 смотрите мой ответ здесь, если вы используете EC2 с ansible, вы можете использовать CloudInit для установки python2, чтобы вы могли использовать сбор фактов как обычно.
Мирослав

1
В случае, если кому-то тоже интересно, запускать задачу для установки Python 2 не обязательно ; обычный тоже работает нормально. Но его вставка вместе с другой задачей для вызова модуля Ansible обеспечит доступность фактов для любых ролей, назначенных хосту. rawpre_taskstaskspre_taskssetup
Кенни Эвитт

125

Ansible 2.2 имеет технический предварительный просмотр поддержки Python 3. Чтобы воспользоваться этим (чтобы вам не нужно было устанавливать Python 2 в Ubuntu 16.04), просто установите ansible_python_interpreterопцию config в /usr/bin/python3. Это можно сделать для каждого хоста в файле инвентаризации:

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

Я попытался добавить / usr / bin / python к этой переменной, но это не сработало. Добавление python3 вместо этого сработало, и эта проблема была исправлена
Deep LF

98

Решение 1:

Если вы используете Ansible >2.2.0, вы можете установить ansible_python_interpreterопцию конфигурации на /usr/bin/python3:

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

или в вашем инвентарном файле:

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

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

Решение 2:

Если вы используете, Ansible <2.2.0то вы можете добавить их pre_tasksв свой 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

ОБНОВЛЕНИЕ С ansible 2.8.x, вам не нужно беспокоиться об этом, это работает из коробки для Python> 3,5 для контроллера и целевой машины (ей)


Если вы запускаете свои книги с использованием тегов, убедитесь, что вы добавили теги: всегда в задачу установки - в противном случае ansible не будет собирать факты при использовании тегов.
Ионут Байеску

16
У меня есть, ansible 2.3.0.0и это не работает из коробки. Та же ошибка, что и ОП.
Кодер

В случае, если это неясно, вам нужно добавить это в файл инвентаризации хоста, а не во включенный vars, то есть он находится в том же файле инвентаризации, что и адрес / имя хоста.
Шон Механ,

32

Вы можете использовать модуль raw для установки Python на удаленных хостах:

- raw: sudo apt-get install python-simplejson

11
Чтобы убедиться, что это вызывается перед задачами в вашей роли и перед какими-либо зависимостями в вашем метафайле, добавьте его в свою пьесу следующим образом: pre_tasks: - raw: sudo apt-get install python-simplejson
Laurens Rietveld

5
Обратите внимание, что в playbook вы также должны отключить collect_facts, иначе произойдет сбой перед запуском необработанной команды. (collect_facts: no)
rcreswick

@rcreswick Это была моя проблема, и ваше решение сработало для меня. Спасибо. Я поместил строку «collect_facts: no» в свой основной файл .yml (setup-ansible.yml) и выполнил playbook с помощью этой команды: «ansible-playbook -i hosts setup-ansible.yml --flush-cache -vvvvvv -kK ». Я использовал параметры "-kK" с ansible-playbook, потому что для установки Ubuntu по умолчанию требуется пароль для "sudo".
Али Юсефи Сабзевар

почему вы устанавливаете simplejson, а не pytghon, а говорите об установке python?
Хеннинг

@Henning python-simplejsonнаписан на Python и поэтому требует Python. simplejson также является требованием для большинства основных модулей Ansible. Устанавливая python-simplejsonчерез apt-get/, yumвы также устанавливаете Python и, следовательно, покрываете все основные зависимости Ansible ...
udondan

18

Чтобы суммировать ответы всех остальных, вот объединенные настройки, которые работали для меня:

 - 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

Я лично нашел 3 возможных решения этой проблемы, которые хорошо работают в разных ситуациях:

Вариант 1 - установить ansible_python_interpreter: /usr/bin/python3для хостов, которые python3установлены по умолчанию

Я думаю, что это лучший метод для решения проблемы, если у вас есть способ сгруппировать ваши хосты, независимо от того, python3установлены они по умолчанию или нет . Насколько я знаю, python3доступно на всех выпусках Ubuntu 16.04 и выше.

  • Если все ваши хосты определенно имеют python3, вы можете добавить переменную в ваш group_vars/all.yml(или эквивалентный):
# group_vars/all.yml

ansible_python_interpreter: /usr/bin/python3
  • Если у некоторых из ваших хостов их нет, python3и у вас есть возможность пометить их при использовании динамического инвентаризации (например, тегирование AWS для ec2.py), вы можете применить переменную к определенным хостам, например так:
# group_vars/tag_OS_ubuntu1804.yml

ansible_python_interpreter: /usr/bin/python3
  • Если вы используете статическую инвентаризацию и можете группировать хосты в зависимости от их наличия python3, вы можете сделать что-то вроде этого:
# inventory/hosts

[python2_hosts]
centos7_server

[python3_hosts]
u1804_server

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

Мне больше нравится этот вариант, потому что он не требует никаких изменений на удаленном хосте и только незначительные изменения переменных, в отличие от вариантов 2 и 3, которые требуют дополнений к каждой пьесе.

Вариант 2 - установить Python 2 с помощью raw

Эта опция требует размещения пьесы в верхней части каждой книги с тем, gather_facts: falseчто используется rawдля установки 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требуется, если вы планируете запускать игру на хостах, которые не apt-getустановлены (например, на основе RHEL), иначе они выдадут ошибку в первой игре.

Это решение работает, но является самым низким в моем списке по нескольким причинам:

  1. Нужно идти вверху каждой пьесы (в отличие от варианта 1)
  2. Предполагается, aptнаходится в системе и игнорирует ошибки (в отличие от варианта 3)
  3. apt-get Команды медленные (в отличие от варианта 3)

Вариант 3 - /usr/bin/python -> /usr/bin/python3использование символической ссылкиraw

Я не видел такого решения, предложенного кем-либо еще. Это не идеал, но я думаю, что он превосходит вариант 2 во многих отношениях. Я предлагаю использовать rawкоманду оболочки для символической ссылки, /usr/bin/python -> /usr/bin/python3если она python3находится в системе, а python ее нет:

- 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

Это решение аналогично варианту 2 в том смысле, что нам нужно ставить его в начале каждой книги, но я думаю, что оно превосходит несколько способов:

  • Создает только символическую ссылку в конкретном случае, который python3присутствует, а pythonего нет - он не переопределит Python 2, если он уже установлен
  • Не предполагает aptустановлен
  • Может работать на всех хостах без специальной обработки ошибок
  • Это супер быстро по сравнению с чем-либо с apt-get

Очевидно, что если вам нужен установленный Python 2 /usr/bin/python, это решение не требуется, и вариант 2 лучше.

Вывод

  • Я предлагаю использовать вариант 1 во всех случаях, если вы можете.
  • Я предлагаю использовать вариант 3, если ваш инвентарь действительно большой / сложный и у вас нет возможности легко сгруппировать хосты python3, что делает вариант 1 намного более сложным и подверженным ошибкам.
  • Я предлагаю только вариант 2 вместо варианта 3, если вам нужен Python 2, установленный на /usr/bin/python.

источники


13

Вам нужен Python 2.7 для запуска Ansible. В Ubuntu 16.04 вы можете установить его с помощью этой команды:

sudo apt-get install python-minimal

После этого я мог бежать

ansible-playbook -i inventories/staging playbook.yml

Выполнить ANSIBLE успешно

Пожалуйста, проверьте больше на Использование ansible в Ubuntu 16.04


12

Что я использовал, чтобы заставить это работать на Ubuntu 15.10 на свежей капле Digital Digital:

# 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

Для Ubuntu 16.04 на новом SSD OVH мне пришлось обновить apt-get до того, как пакеты python2 стали доступны.


8

Я обнаружил, что на самом деле можно иметь несколько воспроизведений в одной книге воспроизведения, поэтому в моей настройке теперь есть воспроизведение «обеспечения зависимости», которое выполняется на всех хостах, и другие игры для конкретных хостов. Так больше не надо pre_tasks.

Например:

- 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

Как говорили другие, это связано с отсутствием python2. Другие ответы здесь предоставляют обходной путь pre_tasksи gather_facts: no, однако, если вы работаете в EC2 и запускаете экземпляр с ansible, вы можете использовать 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

Тогда люди обычно ждут, когда ssh будет доступен следующим образом:

  - 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

Однако я обнаружил, что это не всегда достаточно долго, так как CloudInit выполняется довольно поздно в процессе загрузки, поэтому python2 может быть не установлен сразу после того, как ssh станет доступен. Поэтому я добавил паузу на случай, если экземпляр был только что создан:

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

Это отлично сработает, и в качестве преимущества вы не проверяете python2 при каждом запуске, и вам не нужно обходиться, чтобы собрать факты позже.

Я уверен, что другие облачные провайдеры предоставляют аналогичную функциональность CloudInit, поэтому адаптируйтесь к своему варианту использования.


3

Поэтому использование Packer может оказаться полезным для решения ниже.

давайте предположим, что вы используете ansible Provider упаковщика, ваш конфиг может выглядеть следующим образом

вы можете сначала установить python, используя утилиту инициализации оболочки, а затем настроить параметр ansible_python_intepreter, как показано ниже

"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

По умолчанию Ansible требует Python 2 , однако Ansible 2.2+ может работать с Python 3 .

Так что либо установите Python 2 с помощью rawмодуля , например

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

или установите ansible_python_interpreterпеременную в файле инвентаря, например:

[local]
localhost ansible_python_interpreter="env python3"

Для Docker вы можете добавить следующую строку:

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

или запустите его как:

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

1

В соответствии с этим Gist вы можете установить Python2 на Ubuntu 16.04 следующим образом:

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

Много ответов .. Спасибо за сообщение, как я начал с этой страницы тоже!

Я немного покопался, и с Ubuntu 14.04LTS все шло хорошо, Ubuntu 15.04LTS, похоже, потерял последнюю pythonверсию, а Ubuntu 16.04LTS, похоже, упал aptitude.

Я помещаю следующее действие в мой загрузчик перед выполнением любых 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

Если вам удастся в becomeдругом месте, не стесняйтесь раздеть это.

Источники:


1

Я смог решить ту же проблему, установив Python на целевой машине, то есть на машине, к которой мы хотим использовать SSH. Я использовал следующую команду:

sudo apt-get install python-minimal

1

@ Мирослав, спасибо, что указал мне правильное направление. Я использовал user_dataв ec2_instanceмодуле тоже, и он работает как удовольствие.

Т.е.

- 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

Вы можете указать Ubuntu 18.04, что вы хотите использовать python3 в качестве первого приоритета для /usr/bin/python.

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

0

У меня была такая же проблема, пока я не понял, что вам также нужно установить python на удаленном хосте, а также на вашем собственном локальном компьютере. теперь это работает!


-2

Мы просто сталкиваемся с этим.

Мы развертываем Ubuntu 16.04 на vagrant, поэтому, если вы не используете vagrant, мой комментарий не имеет смысла.

Мы установили следующие бродячие плагины (trigger, shell-commander), и мы установили на машину python 2.7.6 (который был не без этих плагинов) и после того, как ansible смог развернуться

Это был наш последний тест, иначе мы собирались включить эту установку в команду оболочки в файле Vagrant

Надеюсь, что это может помочь кому-то


2
Если вы используете Ansible, ниже приведено правильное решение Ansible. Надежда на то, что Vagrant случайно установит его для вас, поскольку побочный эффект некоторых плагинов, похоже, вызывает проблемы.
Пол Бекотт

Извините, но как вы можете запустить заданную предварительную задачу, если в ней нет python ??? Я попробовал решение, и оно не сработало при настройке задачи, поэтому событие до предварительной задачи. Команда оболочки vagrant в файле vagrant - это лучший способ сделать это (для случая vagrant, конечно), но я просто замечаю, что плагин vagrant, который я установил в своем dev, выполняет свою работу. Я не полагаюсь на плагин, а на файл vagrant, я просто указал, что он работает и с плагином, но файл vagrant - лучший выбор (также для автоматизации), потому что вам не нужно ничего делать с каждым уничтожить / обеспечить
ваду

1
Я скопировал этот блок кода в точности так, как он был, и он работал точно так, как описано, прежде чем вы опубликовали свой ответ. Я полагаю, что вы, вероятно, не вставили gather_facts: noстроку, которая требует Python. Другая возможность заключается в том, что вам также нужен python на хост-машине, но я думаю, это вызвало бы ваши ошибки еще раньше.
Пол Бекотт

Я тоже скопировал пасту, но на работе была пятница. Я не могу честно вспомнить, принял ли я участие Во всяком случае, сегодня утром на другом компьютере, если я снова поместил его в очередь, и я только что поместил команду в vagrantfile, мне достаточно, пока мы не перейдем к производству на реальном сервере. Я
проверю
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.