morgangraphics.ansible-role-nvm

Ansible角色:NVM

在Debian/Ubuntu、RHEL/CentOS系统和其他*nix系统上安装NVM和Node.js

Ansible跟SSH和(非)交互式Shell的奇怪组合使得用NVM和Ansible一起工作变得有点困难。可以参考这篇Stack Overflow帖子,了解一些人如何解决这个问题。

其他角色的不足之处

其他安装NVM和/或Node.js的Ansible角色存在一些不足。

  1. 他们使用apt-get或yum包管理器来安装Node.js。这通常意味着Node.js包的版本比Node.js仓库中可用的版本要旧。在某些情况下,这些包可能不是LTS版本,如果你需要在同一主机上运行多个Node.js版本,那就麻烦了。

  2. 他们通常以root用户安装NVM和Node.js(sudo subecome: true)。这可能增加与NPM插件管理相关的权限头痛,以及Node与nvm的功能,此外,还存在不必要的权限提升安全风险。

  3. 你无法运行临时的nvm、npm、node、bash或Shell命令。

此角色与其他角色的不同之处

  1. 你可以通过wget、curl或git安装NVM。
  2. 你可以在自己的Ansible任务和剧本中像使用命令行一样使用NVM。
  3. 你可以安装任何版本多个版本的Node.js。
  4. 不以root身份安装NVM或Node.js。
  5. 可以运行任意nvm、npm、node、bash或Shell命令,这可能消除需要单独的Node Ansible角色的需求。

要求

Ansible版本(ansible-core)2.16.0及以上。

:triangular_flag_on_post: 如果你需要支持较旧版本的Ansible,请参见legacy 1.5.X分支

请参见Ansible版本下文

安装

  1. 将该仓库克隆到你的角色文件夹。
  2. 在你的ansible.cfg文件中将roles_path变量指向角色文件夹,例如roles_path = ../ansible-roles/
  3. 在你的剧本中包含该角色。

:warning: 警告!

请勿以root身份运行此角色!(例如become: true|yes|1

原因有几点:

  1. 这是一个不必要的权限提升安全风险,你很可能不需要以root_user身份运行每个角色中的每个任务。如果出于某种原因,你确实需要以root_user身份运行所有内容,请重新考虑该角色的功能以及它为什么需要所有内容的root访问权限。

  2. 此角色在你运行NodeJS的相同上下文/ Shell/会话中安装nvm。你并不以root身份运行NodeJS。

  3. Ansible会将登录Shell的上下文更改为root,nvm将安装在root_user的主目录中,例如/root/.bashrc。这意味着如果你的主用户是vagrantec2-userubuntu等,该角色将无法正常工作!

错误示例 :thumbsdown:

- hosts: all
  become: true           # 这将以root_user身份运行所有任务,对于所有主机
  become_method: sudo    # 这将以root_user身份运行所有任务,对于所有主机

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"

    - role: some-other-role
      ...

更好的示例 :thumbsup:

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"

    - role: some-other-role
      ...
      become: true            # 这仅在some-other-role中以root_user身份运行所有任务
      become_method: sudo     # 这仅在some-other-role中以root_user身份运行所有任务

最佳示例 :metal:

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"
      become: true            # 这将更改登录上下文以使用下面的用户
      become_user: ec2-user   # 这将在EC2用户/默认用户的上下文中安装NVM。此用户必须存在于系统中!

    - role: some-other-role
      ...
      become: true            # 这仅在some-other-role中以root_user身份运行所有任务
      become_method: sudo     # 这仅在some-other-role中以root_user身份运行所有任务

有关详细信息,请参见问题部分。

示例剧本

超简洁

按原样包含该角色,它将安装最新的LTS版本Node.js。

- hosts: all

  roles:
    - role: ansible-role-nvm

简单

包含该角色并指定要安装的Node.js的具体版本。

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"

更复杂

此示例展示了如何设置多个环境(开发/生产),每个环境具有不同的选项。生产设置利用nvm_commands选项安装、构建和运行应用程序。该角色支持并利用Ansible变量语法,例如{{ variable_name }}

- hosts: dev

  vars_files:
    - vars/dev.yml

  roles:
    - role: ansible-role-nvm
      nodejs_version: "{{ config.dev.nodejs.version }}"

- hosts: prod
  vars_files:
    - vars/prod.yml

  roles:
    - role: ansible-role-nvm
      nvm_install: "curl"
      nvm_dir: "/usr/local/nvm"
      nvm_commands:
       - "nvm install {{ config.prod.client-1.nodejs.version }}"
       - "nvm alias default {{ config.prod.client-1.nodejs.version }}"
       - "nvm exec default npm install"
       - "nvm exec default npm run prod"

在同一主机上安装/运行/维护或升级多个版本的Node.js

默认情况下,Playbook中声明的第一个 Node.js版本将在第一次运行时自动别名为“默认”版本,无论之后安装的版本或运行角色的次数。对于在单台机器上安装多个Node.js版本,明确声明期望的“默认”版本非常重要。

存在两个预先存在的NVM别名default(当前“活动”的Node.js版本)和system(基础OS版本的Node.js)。

别名是NVM非常强大的功能,它是推荐的最佳实践来管理你的环境。

多重安装

- hosts: host-1

  roles:
    # 服务
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    # <= 这将是Node.js的“默认”版本

    # 应用程序
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"

多重安装带默认

- hosts: host-2

  roles:
    # 服务
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    

    # 应用程序
    - role: ansible-role-nvm
      default: true
      nodejs_version: "10.15.0" # <= 这现在是Node.js的“默认”版本

关于NVM命令的说明

NVM命令是此角色的一个非常强大的功能,它利用了NVM建立的基础。利用nvm_commands可能完全消除需要单独的Node角色来管理你的Node应用程序的需求。

nvm runnvm exec命令之间有区别。nvm run功能上等同于node server.jsnode server,用于调用JavaScript文件。

nvm exec在子进程上下文中执行,功能上等同于npm run server,其中server是在package.json文件的scripts部分中的键名称。

{
  "name": "my_application",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "preserver": "npm run dbService &",
    "server": "nodemon ./bin/www",
    "build": "node build/build.js",
    "dbService": "nodemon ./data-service/server.js --ignore node_modules/"
  },
  "dependencies": {
    "..."
  }
}

nvm exec可以执行一些任意脚本文件,例如nvm exec hello-world.py

例如hello-world.py:

#!/usr/bin/env python
print('hello-world')

:warning: 必须包括脚本头,以便其正常工作

运行一些任意bash命令。

ls -al >> output.txt

nvm_commands使得在同一主机上使用不同版本的Node.js设置Node应用程序和Node API层变得非常容易。

- hosts: host-1
  roles:
    # 服务
    # 发生了什么?
    # 1. 使用Node版本8.15.0运行服务JavaScript文件
    # 警告:此时将其别名为Node.js的默认版本!!
    # 因此我们需要明确指定正在使用的版本,因为
    # 应用程序部分下面的默认Node.js版本会发生变化
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm exec 8.15.0 npm run services"

    # 应用程序
    # 发生了什么?
    # 1. 将Node.js的默认版本设置为10.15.0版本
    # 2. 使用npm安装包依赖
    # 3. 将环境设置为生产,运行构建JavaScript文件
    # 4. 然后运行生产部署脚本
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias webapp {{ nodejs_version }}" # <= 更改默认NVM版本(支持Ansible变量语法)
       - "nvm exec webapp npm install" # 安装应用程序依赖
       - "NODE_ENV=production nvm run webapp build" # 直接调用Node.js运行生产构建脚本
       - "nvm exec webapp npm run prod" # 调用npm运行package.json文件中的生产脚本

另一个示例

- hosts: host-2
  roles:
    # 服务
    # 发生了什么?
    # 1. 创建一个版本8.15.0的别名,命名为service-default(支持Ansible变量语法)
    # 2. 运行服务脚本
    #
    # ** 建议你给Node.js版本命名并相应引用 **
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm alias service-default {{ nodejs_version }}" # <= (支持Ansible变量语法)
        - "nvm exec service-default npm run services" # 在package.json文件中运行服务脚本

    # 应用程序 - 不需要单独的Node.js Ansible角色
    # 发生了什么?
    # 1. 安装版本10.15.0的Node.js
    # 2. 将Node.js的默认版本设置为10.15.0版本
    # 3. 运行test.js脚本文件,直接调用Node.js
    # 4. 然后运行生产部署bash脚本
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias default 10.15.0" # <= 更改默认NVM版本
       - "nvm exec default node test.js" # 直接调用Node.js运行测试脚本
       - "nvm exec ./deploy.sh" # 运行任意bash脚本

你用来启动应用程序的命令行参数或在package.json文件中声明的命令脚本可以放入此角色的nvm_commands: []部分中。

- hosts: host1

  pre_tasks:

    # test-user需要在系统上是一个真实用户,才能在其配置文件中安装nvm
    - name: add new user
      user:
        name: "test-user"
      become: true

  roles:

    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_profile: "/home/test-user/.bashrc"
      nvm_commands:
        - "whoami"
        - "node --version"
        - "nvm --version"
        - "npm --version"
        - "python3 -m hello"
      become_user: test-user
      become: true

注意事项

  1. 默认情况下,Playbook中列出的第一个版本将在第一次运行时自动别名为“默认”版本,无论之后安装的版本或运行角色的次数。第一个输入/安装的版本始终是默认的。 因此,如果你期望在剧本中后面声明的Node.js版本被设置为默认版本,请使用default: true或在nvm_commands列表中明确设置,例如- "nvm alias default <YOUR_VERSION>"

  2. 如果你明确声明了default: true作为角色变量以及- "nvm alias default <SOME_OTHER_VERSION>"作为你的nvm_commands的一部分,具有default: true的版本将始终首先执行。这是因为我们需要Node.js在做其他事情之前可用。

  3. NVM是无状态的,如果你在一台机器上安装了多个版本的Node.js,你可能需要在脚本中运行nvm use <VERSION>来运行你希望/期待的Node.js版本。然而,强烈建议你根据需要命名你的版本并以此方式引用它们。请参见上面的示例。

问题

"nvm: command not found" 错误

这通常是由于在与nvmnode用户上下文不同的用户上下文中运行该角色。如果你在剧本中的所有角色上添加become: true来解决由于权限问题引发的错误,那么该角色将以ROOT_USER身份安装nvm(通常在/root/.bashrc中)。你很可能希望以默认用户,例如vagrant、ec2-user、ubuntu等身份运行nvm和node。 如果出于某种原因,你无法删除所有内容的become: true,你只需为此角色指定become: true become_user: ec2-user,就可以解决become: true问题。有关详细说明,请参见bash: nvm command not found

"cannot find /usr/bin/python" 错误

这是由于默认运行Python 3的操作系统(例如Fedora)导致的。你需要在清单文件中或通过命令行指定Ansible python解释器变量:

[fedora1]
192.168.0.1 ansible_python_interpreter=/usr/bin/python3

[fedora2]
192.168.0.2

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

ansible-playbook my-playbook.yml -e "ansible_python_interpreter=/usr/bin/python3"

glibc_2.28' not found (required by node)

你尝试在不支持安装的Node.js版本的操作系统上运行Node.js的一个版本。这不是NVM问题,也不是角色的问题。你需要升级操作系统或降级你试图安装的Node.js版本。


Ansible版本支持

ansible-core 2.16 +

Ansible在管理includes/imports方面发生了根本性变化。Ansible已从ansible-core中删除ansible.builtin.include并用ansible.builtin.include_tasks替换。不幸的是,Ansible无法将ansible.builtin.include作用域设置为忽略旧版本等,因此我将此角色升级到完全支持ansible-core 2.16+。

如果你需要支持ansible-core 2.15及以下版本,请使用ansible-role-nvm-legacy分支。

ansible-core 2.15及以下版本

请使用legacy 1.5.X分支

角色变量

可用变量列在下面,并附有默认值,请参见defaults/main.yml

要安装的Node.js版本。最新的"LTS"版本是默认值,适用于大多数受支持的操作系统。

nodejs_version: "lts"

为了在用户手动维护服务器或工作站时安装NVM Bash自动完成(nvm <TAB>)的便利方法。

autocomplete: false

从头开始安装NVM,删除所有.nvm(目录)有关的现有或先前引用,以及所有与系统中的配置文件条目相关的现有或先前引用,例如.bashrc

clean_install: false

clean_install: true会grep查找/home/root/etc自定义安装目录中的所有文件以查找参考,以及查找系统中的任何.nvm文件夹。这相当于新机器设置,使用时请谨慎

default: false

在维护/安装多个Node版本时设置默认Node版本。

NVM会自动将首个运行/安装的版本别名为“default”,这很可能是人们使用此角色的理由,但是这将允许在现有机器上安装/升级多个版本。

要运行的NVM命令列表。默认是空列表。

nvm_commands: []

NVM安装类型。选项包括wget、curl和git。

nvm_install: "wget"

NVM安装目录。

nvm_dir: ""

NVM将默认情况下在用户的主目录中安装.nvm目录,例如/home/vagrant/.nvm。如果你希望将其放置到全局空间(不与特定用户帐户绑定),你可以通过更改此变量,例如将其更改为/opt/nvm。此变量将尊重Ansible替换变量,例如{{ansible_env.HOME}}

NVM配置文件位置选项为.bashrc、.cshrc、.tcshrc、.zshrc。

nvm_profile: ".bashrc"

将从中获取nvm命令的登录SHELL配置文件的位置。需要考虑两个潜在的上下文:

全局,即每个登录用户都将访问nvm(这可能是你真正想要的)

例如/etc/bash.bashrc/etc/profile等。

按用户的基础上与特定用户帐户绑定

例如/home/vagrant/.bashrc。*

如果配置文件不存在,此角色将创建适当的配置文件。

如果你明确指定nvm_profile: "/home/node-user/.bashrc",而node-user不是系统上的真实用户,则nvm将无法如你所预期那样工作。become、become_user和nvm_profile路径是相辅相成的。

:warning: 请注意在Ubuntu系统上明确声明.profile或.bash_profile文件的局限性

https://askubuntu.com/a/969923详细说明。

https://kb.iu.edu/d/abdy展示每种Shell类型的选项。

NVM配置文件位置选项有:

BASH: .bashrc

CSH: /etc/csh.cshrc、.cshrc

TSCH: /etc/csh.cshrc、.tcshrc、.cshrc

ZSH: .zshrc

NVM源位置,即你自己托管的NVM的分支。

nvm_source: ""

要安装的NVM版本。

nvm_version: "0.39.7"

卸载NVM,将删除.nvm目录并清理位于{{ nvm_profile }}变量路径(通常为$HOME/.bashrc)中的文件。

uninstall: False

依赖关系

无。

变更日志


2.0.0 请参见发布说明

许可

MIT / BSD

作者信息

dm00000来自MORGANGRAPHICS, INC

此角色大量借鉴了Jeff Geerling的Node.js角色,后者是Ansible for DevOps的作者。

安装
ansible-galaxy install morgangraphics.ansible-role-nvm
许可证
mit
下载
476
拥有者