Python中如何使用Ansible自动化安装pyenv和pyenv-virtualenv,支持OS X和Debian系统

不知大家是如何安装 pyenv,以及 pyenv-virtualenv 的。

昨天看到 说说我对 Python 装饰器的理解 - V2EX 后,打算重新搭建下 Python 开发环境。之前工作中用 virtualenv + virtualenvwrapper 较多,自从 Ruby 环境管理工具从 rvm 更换到 rbenv 后,想一想也是时候使用 pyenv 了。

现在 DevOps 已全面往 ansible 迁移,对 rbenv 也熟悉,所以想着直接用 Ansible 来安装初始化;意外的是,遇到的问题还挺多(相反,使用 ansible-rbenv 就没有遇到什么问题)。特此发贴,希望对大家有所帮助。

使用 ansible-pyenv

GitHub 上搜索到 https://github.com/dirn/ansible-pyenv 这个项目,最近更新是 2 年以前,问题多到不可用,现在做了修复,Travis-CI 也跑通了(只是慢得无法仍受)。

目前暂未合并,要使用可以按以下步骤:

$ # 1. clone ansible-pyenv into your roles, and name dirn.pyenv
$ git clone https://github.com/dylanninin/ansible-pyenv /path/to/your/ansible/roles/dirn.pyenv
$
$ # 2. add python playbook, see python.yml
$ cat python.yml
#!/usr/bin/env ansible-playbook
---
- name: deploy python env
  hosts: all
  roles:
    # https://github.com/dirn/ansible-pyenv
    - role: dirn.pyenv
      pyenv_runcom: ~/.bashrc
      pyenv_versions:
        - 2.7.11
        - 3.5.3
      pyenv_default_versions:
        - 3.5.3
      pyenv_project_versions:
        - 3.5.3
$
$ # 3. edit your inventory, see inventory
$ cat inventory
[vagrant]
vagrant-1404
vagrant-1604

[local] localhost ansible_connection=local $ $ # 4. layout of current directory $ tree -L 2 . ├── inventory ├── python.yml └── roles └── dirn.pyenv

2 directories, 2 files $ # 5. just play it with specified host, localhost as example $ ansible-playbook python.yml -l localhost

这样就可以自动化安装 pyenv、pyenv-virtualenv 了。当然,事先需要安装 Ansible

另外,dirn.pyenv 中可能有一些不合理的地方,欢迎大家提建议。

题外话

https://github.com/pyenv/pyenv 上安装 pyenv 已经足够简单,似乎不足以使用 Ansible 等自动化工具,但 Ansible 带来的变化其实非常大,主要是:

  • 自动化。这可能是最明显、最可感知的收效,一两个服务器配置无所谓,一旦多起来了就会重复操作。现在可以自动化,还可以多台机器并行执行。
  • 标准化。『每一片雪花都独一无二』,同样适用于服务器、开发人员;人工操作总会有差异性,规模化之后会很难维护,但『雪崩后没有一片雪花觉得自己有责任』。现在可以做到『标准化』,避免此类问题。
  • 思维变化。ansible 帮助重新理解 provisioning/configuring 等,以前 手工操作、使用 shell script、使用 Dash 的 snippets 等,中间可能会遇到各类问题和中断,都不能保证服务器抵达某一种『状态』。现在可以做到了,而且是『一致性状态』。

有机会专门介绍下 Ansible。

参考


Python中如何使用Ansible自动化安装pyenv和pyenv-virtualenv,支持OS X和Debian系统

5 回复

不错不错!!


#!/usr/bin/env python3
"""
Ansible Playbook自动化安装pyenv和pyenv-virtualenv
支持OS X (macOS) 和 Debian/Ubuntu系统
"""

# playbook.yml
---
- name: 自动化安装pyenv和pyenv-virtualenv
  hosts: all
  become: yes
  vars:
    pyenv_root: "{{ ansible_user_dir }}/.pyenv"
    pyenv_repo: "https://github.com/pyenv/pyenv.git"
    virtualenv_repo: "https://github.com/pyenv/pyenv-virtualenv.git"
    
  tasks:
    - name: 检测操作系统
      ansible.builtin.set_fact:
        is_macos: "{{ ansible_os_family == 'Darwin' }}"
        is_debian: "{{ ansible_os_family == 'Debian' }}"
    
    - name: 安装系统依赖 (macOS)
      when: is_macos
      homebrew:
        name:
          - openssl
          - readline
          - sqlite3
          - xz
          - zlib
        state: present
    
    - name: 安装系统依赖 (Debian/Ubuntu)
      when: is_debian
      apt:
        name:
          - make
          - build-essential
          - libssl-dev
          - zlib1g-dev
          - libbz2-dev
          - libreadline-dev
          - libsqlite3-dev
          - wget
          - curl
          - llvm
          - libncurses5-dev
          - libncursesw5-dev
          - xz-utils
          - tk-dev
          - libffi-dev
          - liblzma-dev
          - python3-openssl
        state: present
        update_cache: yes
    
    - name: 克隆pyenv仓库
      git:
        repo: "{{ pyenv_repo }}"
        dest: "{{ pyenv_root }}"
        version: master
        update: yes
    
    - name: 克隆pyenv-virtualenv插件
      git:
        repo: "{{ virtualenv_repo }}"
        dest: "{{ pyenv_root }}/plugins/pyenv-virtualenv"
        version: master
        update: yes
    
    - name: 配置shell环境 (bash)
      when: ansible_shell_type == 'bash'
      blockinfile:
        path: "{{ ansible_user_dir }}/.bashrc"
        block: |
          export PYENV_ROOT="$HOME/.pyenv"
          export PATH="$PYENV_ROOT/bin:$PATH"
          eval "$(pyenv init --path)"
          eval "$(pyenv init -)"
          eval "$(pyenv virtualenv-init -)"
        marker: "# {mark} ANSIBLE MANAGED BLOCK - pyenv"
    
    - name: 配置shell环境 (zsh)
      when: ansible_shell_type == 'zsh'
      blockinfile:
        path: "{{ ansible_user_dir }}/.zshrc"
        block: |
          export PYENV_ROOT="$HOME/.pyenv"
          export PATH="$PYENV_ROOT/bin:$PATH"
          eval "$(pyenv init --path)"
          eval "$(pyenv init -)"
          eval "$(pyenv virtualenv-init -)"
        marker: "# {mark} ANSIBLE MANAGED BLOCK - pyenv"
    
    - name: 验证安装
      shell: |
        source {{ ansible_user_dir }}/.{{ ansible_shell_type }}rc 2>/dev/null || true
        pyenv --version
        pyenv virtualenv --version
      register: pyenv_check
      changed_when: false
    
    - name: 显示安装结果
      debug:
        msg: "pyenv安装成功: {{ pyenv_check.stdout_lines }}"
# inventory.ini - 主机清单配置示例
[local]
localhost ansible_connection=local

[mac_servers]
mac1 ansible_host=192.168.1.100 ansible_user=youruser
mac2 ansible_host=192.168.1.101 ansible_user=youruser

[debian_servers]
debian1 ansible_host=192.168.1.200 ansible_user=root
debian2 ansible_host=192.168.1.201 ansible_user=ubuntu
# 执行命令
# 1. 安装Ansible (macOS)
brew install ansible

# 2. 安装Ansible (Debian/Ubuntu)
sudo apt update
sudo apt install ansible -y

# 3. 运行playbook
ansible-playbook -i inventory.ini playbook.yml

# 4. 针对特定主机组运行
ansible-playbook -i inventory.ini playbook.yml --limit mac_servers
ansible-playbook -i inventory.ini playbook.yml --limit debian_servers

# 5. 测试单个主机
ansible-playbook -i inventory.ini playbook.yml --limit localhost

核心要点:

  1. 操作系统检测:自动识别macOS和Debian系统,安装对应依赖
  2. Git安装:直接从官方仓库克隆最新版本
  3. Shell配置:自动配置bash和zsh的环境变量
  4. 幂等性:重复运行不会重复安装

使用方法:

  1. 保存为playbook.yml
  2. 配置inventory.ini指定目标主机
  3. 运行ansible-playbook命令

一句话建议: 用这个playbook可以一键搞定所有环境的pyenv安装。

不过我现在用 docker

有机会专门介绍下 redmine

是啊是啊,我也想看看这方面的介绍

回到顶部