【问题标题】:Ansible fails with /bin/sh: 1: /usr/bin/python: not foundAnsible 失败并显示 /bin/sh: 1: /usr/bin/python: not found
【发布时间】:2015-12-02 10:53:49
【问题描述】:

我遇到了以前从未见过的错误。这是命令和错误:

$ 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

这里是主机文件:

[api]
104.55.47.224

我可以删除角色部分,但它不会进入第一个任务,而是只会进入/bin/sh: 1: /usr/bin/python: not found 行。这里会发生什么?


注意:如果有人 ping IP 地址但没有得到响应,您应该知道我在粘贴代码后更改了 IP 地址。

编辑 python是本地安装的,问题是它没有安装在运行Ubuntu 15.04的远程机器上

【问题讨论】:

    标签: ansible ansible-playbook


    【解决方案1】:

    我在 Ubuntu 15.10 服务器上运行 ansible 时偶然发现了这个错误,因为它附带 Python 3.4.3ansible requires 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
    
    • 不要忘记 apt-get 的 -y(对所有问题都说是)选项(否则原始模块会默默卡住)

    • gather_facts: no 行也很关键(因为没有python我们无法收集事实)

    【讨论】:

    • 那么后续的角色就不能使用事实了……有没有办法再次收集事实呢?啊哈,stackoverflow.com/questions/31054453/…
    • 请注意,'gather_facts: no' 行很关键。
    • @surfer190 很棒的发现!我还发现添加action: setup 作为最终的 pre_task 也很有效:)
    • @surfer190 在这里查看我的答案如果您使用 EC2 和 ansible,您可以使用 CloudInit 安装 python2,以便您可以像往常一样使用收集事实。
    • 如果有人也想知道,运行raw 任务在pre_tasks 中安装Python 2 不是必要;常规 tasks 也可以正常工作。但是将它放在 pre_tasks 中,以及另一个调用 Ansible setup 模块的任务,将确保分配给主机的任何角色都可以使用事实。
    【解决方案2】:

    Ansible 2.2 具有 Python 3 支持的技术预览。 To take advantage of this(因此您不必在 Ubuntu 16.04 上安装 Python 2),只需将 ansible_python_interpreter 配置选项设置为 /usr/bin/python3。这可以在您的清单文件中针对每个主机完成:

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

    【讨论】:

    • 我尝试将 /usr/bin/python 添加到此变量,但没有成功。添加 python3 代替工作,这个问题得到了修复
    【解决方案3】:

    解决方案 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 &lt;2.2.0,那么您可以将这些pre_tasks 添加到您的剧本中:

    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 不会收集事实。
    • 我有ansible 2.3.0.0,但它不能开箱即用。与 OP 发布的错误相同。
    • 如果没有明确说明,您必须将其添加到主机清单文件中,而不是添加到包含的变量中,即,它与主机地址/名称位于同一清单文件中。
    • 在将 ansible 从 2.5 更新到最新版本后为我工作,感谢更新
    • 我有 ansible 2.9.18 和 debian 11,即使安装了 python2.7 和 python3.9,也不起作用......总是......找不到 python" :'(
    【解决方案4】:

    您可以使用raw module 在远程主机上安装 Python:

    - raw: sudo apt-get install python-simplejson
    

    【讨论】:

    • 为了确保在你的角色中的任务之前以及在你的元文件中的任何依赖项之前调用它,像这样将它添加到你的剧本中:pre_tasks: - raw: sudo apt-get install python-simplejson
    • 请注意,在剧本中,您必须禁用gather_facts,否则在运行原始命令之前这将失败。 (gather_facts: no)
    • @rcreswick 那是我的问题,你的解决方案对我有用。非常感谢。我在主 .yml 文件 (setup-ansible.yml) 中放入“gather_facts: no”行并使用以下命令执行剧本:“ansible-playbook -i hosts setup-ansible.yml --flush-cache -vvvvvv -kK ”。我在 ansible-playbook 中使用了“-kk”选项,因为默认的 ubuntu 安装需要密码才能执行“sudo”。
    • 你为什么要安装simplejson而不是pytghon却要说安装python?
    • @Henning python-simplejson 是用 Python 编写的,因此需要 Python。 simplejson 也是大多数 Ansible 核心模块的要求。通过安装 python-simplejsonapt-get/yum,您还安装了 Python,因此涵盖了所有基本的 Ansible 依赖项...
    【解决方案5】:

    总结其他人的答案,以下是对我有用的组合设置:

     - 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
    

    【讨论】:

      【解决方案6】:

      我个人发现了 3 种可能的解决方案,它们在不同的情况下效果很好:

      选项 1 - 为默认安装了 python3 的主机设置 ansible_python_interpreter: /usr/bin/python3

      如果您有办法根据主机是否默认安装python3 来对主机进行分组,我认为这是解决问题的最佳方法。据我所知,python3 适用于所有 Ubuntu 16.04 及更高版本。

      • 如果您的所有主机都肯定有python3,您可以将变量添加到您的group_vars/all.yml(或等效项):
      # group_vars/all.yml
      
      ansible_python_interpreter: /usr/bin/python3
      
      • 如果您的某些主机没有python3,并且您有办法在使用动态清单时标记它们(例如,ec2.py 的 AWS 标记),您可以像这样将变量应用于某些主机:李>
      # 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 - 使用 raw 安装 Python 2

      此选项需要在每个使用raw 安装python 的剧本的顶部放置一个带有gather_facts: false 的剧本:

      - 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
      

      如果您打算在未安装 apt-get 的主机上运行该游戏(例如任何基于 RHEL 的主机),则需要ignore_errors: true,否则它们将在第一次运行时出错。

      此解决方案有效,但由于以下几个原因,它在我的列表中是最低的:

      1. 需要在每个剧本的顶部(而不是选项 1)
      2. 假设 apt 在系统上并忽略错误(与选项 3 不同)
      3. apt-get 命令很慢(相对于选项 3)

      选项 3 - 符号链接 /usr/bin/python -&gt; /usr/bin/python3 使用 raw

      我还没有看到其他人提出的这个解决方案。这并不理想,但我认为它在很多方面都优于选项 2。我的建议是使用raw 运行一个shell 命令来符号链接/usr/bin/python -&gt; /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 相比,速度超快

      显然,如果您需要/usr/bin/python 安装 Python 2,则此解决方案不可行,选项 2 更好。

      结论

      • 如果可以的话,我建议在所有情况下都使用选项 1
      • 我建议使用选项 3,如果您的广告资源非常大/复杂,并且您无法轻松地将主机分组到 python3,这使得 选项 1 更加困难并且容易出错。
      • 如果您需要在/usr/bin/python 安装 Python 2,我只建议使用 选项 2 而不是 选项 3

      来源

      【讨论】:

        【解决方案7】:

        您需要 python 2.7 来运行 Ansible。 在 Ubuntu 16.04 上,您可以通过以下命令安装它:

        sudo apt-get install python-minimal

        之后,我可以运行

        ansible-playbook -i inventories/staging playbook.yml

        请在Using ansible on Ubuntu 16.04查看更多信息

        【讨论】:

          【解决方案8】:

          我曾经在 ubuntu 15.10 上使用新的 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
          

          对于全新 OVH SSD 上的 ubuntu 16.04,我必须在 python2 包可用之前进行 apt-get 升级。

          【讨论】:

            【解决方案9】:

            我发现实际上可以在一个 playbook 中进行多个播放,因此我的设置现在包含一个在所有主机上运行的“依赖项配置”播放,以及针对特定主机的其他播放。所以没有更多的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
              # ....
            

            【讨论】:

              【解决方案10】:

              正如其他人所说,这是由于缺少 python2。此处的其他答案提供了使用pre_tasksgather_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 在启动过程中执行得相当晚,所以在 ssh 可用后仍然可能无法安装 python2。所以我添加了一个暂停,以防实例刚刚创建:

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

              这将完美地完成这项工作,并且作为一个优势,您无需在每次运行时都检查 python2,并且您不必在以后采取任何变通方法来收集事实。

              我确信其他云提供商提供了类似的 CloudInit 功能,因此请根据您的用例进行调整。

              【讨论】:

                【解决方案11】:

                那些使用 Packer 的人可能会发现以下解决方案很有帮助

                假设您使用的是打包器的 ansible provisioner,您的配置可能如下所示

                您可以先使用 shell 配置器安装 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"
                      ]
                    },
                

                【讨论】:

                  【解决方案12】:

                  默认情况下,Ansible requires Python 2,但是,Ansible 2.2+ can work with Python 3 也是如此。

                  所以要么使用raw module 安装 Python 2,例如

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

                  或在库存文件中设置ansible_python_interpreter variable,例如:

                  [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
                  

                  【讨论】:

                    【解决方案13】:

                    根据this Gist你可以在Ubuntu 16.04上安装Python2,如下:

                    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.
                    

                    【讨论】:

                      【解决方案14】:

                      很多答案.. 感谢您发布,因为我也是从这个页面开始的!

                      我做了一些挖掘,发现 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,请随意剥离它。

                      来源:

                      【讨论】:

                        【解决方案15】:

                        我可以通过在目标机器上安装 Python 来解决同样的问题,即我们想要通过 SSH 连接的机器。我使用了以下命令:

                        sudo apt-get install python-minimal
                        

                        【讨论】:

                          【解决方案16】:

                          @Miroslav,感谢您为我指明了正确的方向。我也在ec2_instance 模块中使用了user_data,它就像一种享受。

                          - 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     
                          

                          【讨论】:

                            【解决方案17】:

                            你可以向 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
                            

                            【讨论】:

                              【解决方案18】:

                              如果您针对 localhost 运行 ansible(换句话说,尝试配置自己的机器),您可以执行以下操作。

                              获取路径 python3

                              $ which python3
                              /usr/bin/python3
                              

                              更新 ansible.cfg 文件 interpreter_python 设置为 python3 路径

                              # ansible.cfg
                              [defaults]
                              interpreter_python  = /usr/bin/python3
                              transport           = local
                              

                              【讨论】:

                                【解决方案19】:

                                我遇到了同样的问题,直到我意识到您还需要在远程主机以及您自己的本地计算机上安装 python。现在可以了!

                                【讨论】:

                                  【解决方案20】:

                                  我们只是遇到了这个。

                                  我们在 vagrant 上部署 ubuntu 16.04,所以如果您不使用 vagrant,我的评论毫无意义。

                                  我们安装了以下 vagrant 插件(触发器、shell-commander)并在机器上安装了 python 2.7.6(不是没有 thioose 插件),并且在 ansible 之后可以部署

                                  这是我们最后一次测试,否则我们将把这个安装包含在 Vagrant 文件的 shell 命令中

                                  希望对大家有所帮助

                                  【讨论】:

                                  • 如果您使用 Ansible,下面的 Ansible 解决方案是正确的解决方案。希望 Vagrant 会因为某些插件的副作用而意外为您安装它,这似乎是自找麻烦。
                                  • 对不起,如果没有 python,你怎么能运行 ansible 预任务?我尝试了解决方案,但它在任务设置之前失败,所以在预任务之前发生事件。 vagrant 文件中的 vagrant shell 命令是最好的方法(当然对于 vagrant 的情况),但我只是注意到我在我的开发人员上安装的 vagrant 插件可以完成这项工作。我不依赖插件,而是依赖 vagrant 文件,我只是指出它也可以与插件一起使用,但 vagrant 文件是更好的选择(也适用于自动化),因为您无需手动对每个文件执行任何操作销毁/提供
                                  • 我完全按照原样复制了该代码块,并且它的工作方式与您发布答案之前的描述完全相同。我相信您可能没有放入需要 python 的gather_facts: no 行。另一种可能性是您还需要在主机上使用 python,但我猜这会在此过程的早期导致您出错。
                                  • 我也复制了粘贴,但那是星期五晚上上班。我不记得我是否参加了gather_fact 部分。无论如何,今天早上在另一台计算机上再次遇到它,我刚刚将命令放在 vagrantfile 中,这对我来说已经足够了,直到我们在真实服务器上进行生产。我会以全新的思维再次测试(所以不是星期五晚上)答案;)
                                  猜你喜欢
                                  • 1970-01-01
                                  • 2021-01-09
                                  • 2015-12-18
                                  • 2020-08-11
                                  • 2013-08-10
                                  • 2018-06-06
                                  • 2021-10-20
                                  • 2019-09-11
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多