如何让 Chef 客户端使用与 NVM 一起安装的用户特定的 nodejs 版本?

How to make Chef client use user specific nodejs version installed with NVM?

我使用 nvm cookbook 来安装 nvm 和 4.3.1 版本 Node.js。

include_recipe 'nvm'

nvm_install node['analyzer_agent']['nodejs']['version'] do
  user node['analyzer_agent']['user']['name']
  group node['analyzer_agent']['user']['group']
  from_source false
  alias_as_default true
  action :create
end

当我通过 SSH 与用户(在本例中为 analyzer_agent)连接到服务器时,一切都按预期进行。我的默认 nodej.js 版本是 4.3.1,当我手动尝试使用 npm install pm2 -g 安装 pm2 时,它运行良好。

但是,当我尝试从我的配方全局安装 pm2 模块时:

execute "Install PM2" do
    cwd "/home/#{node['analyzer_agent']['user']['name']}"
    user node['analyzer_agent']['user']['name']
    group node['analyzer_agent']['group']
    environment "HOME"=> "/home/#{node['analyzer_agent']['user']['name']}", "USER"=>node['analyzer_agent']['user']['name']
    command "npm install pm2 -g"
    not_if { File.exists?("pm2") }
end

我收到以下错误:

================================================================================
Error executing action `run` on resource 'execute[Install PM2]'
================================================================================

Mixlib::ShellOut::ShellCommandFailed
------------------------------------
Expected process to exit with [0], but received '243'
---- Begin output of npm install pm2 -g ----
STDOUT: 
STDERR: npm ERR! tar.unpack untar error /home/analyzer_agent/.npm/pm2/1.0.2/package.tgz
npm ERR! Linux 3.13.0-79-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "pm2" "-g"
npm ERR! node v0.12.5
npm ERR! npm  v2.11.2
npm ERR! path /usr/local/lib/node_modules/pm2
npm ERR! code EACCES
npm ERR! errno -13

npm ERR! Error: EACCES, mkdir '/usr/local/lib/node_modules/pm2'
npm ERR!     at Error (native)
npm ERR!  { [Error: EACCES, mkdir '/usr/local/lib/node_modules/pm2']
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/usr/local/lib/node_modules/pm2',
npm ERR!   fstream_type: 'Directory',
npm ERR!   fstream_path: '/usr/local/lib/node_modules/pm2',
npm ERR!   fstream_class: 'DirWriter',
npm ERR!   fstream_stack: 
npm ERR!    [ '/usr/local/lib/node_modules/npm/node_modules/fstream/lib/dir-writer.js:35:25',
npm ERR!      '/usr/local/lib/node_modules/npm/node_modules/mkdirp/index.js:47:53',
npm ERR!      'FSReqWrap.oncomplete (fs.js:95:15)' ] }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/analyzer_agent/npm-debug.log
---- End output of npm install pm2 -g ----
Ran npm install pm2 -g returned 243

Resource Declaration:
---------------------
# In /var/chef/runs/f3450c3b-d2cc-4f04-a504-436cee5c488b/local-mode-cache/cache/cookbooks/analyzer_agent/recipes/nvm_nodejs.rb

13: execute "Install PM2" do
14:    cwd "/home/#{node['analyzer_agent']['user']['name']}"
15:    user node['analyzer_agent']['user']['name']
16:    group node['analyzer_agent']['group']
17:    environment "HOME"=> "/home/#{node['analyzer_agent']['user']['name']}", "USER"=>node['analyzer_agent']['user']['name']
18:    command "npm install pm2 -g"
19:    not_if { File.exists?("pm2") }
20: end

Compiled Resource:
------------------
# Declared in /var/chef/runs/f3450c3b-d2cc-4f04-a504-436cee5c488b/local-mode-cache/cache/cookbooks/analyzer_agent/recipes/nvm_nodejs.rb:13:in `from_file'

execute("Install PM2") do
action [:run]
retries 0
retry_delay 2
default_guard_interpreter :execute
command "npm install pm2 -g"
backup 5
cwd "/home/analyzer_agent"
environment {"HOME"=>"/home/analyzer_agent", "USER"=>"analyzer_agent"}
returns 0
user "analyzer_agent"
declared_type :execute
cookbook_name "analyzer_agent"
recipe_name "nvm_nodejs"
not_if { #code block }
end

据我所知,在 execute 中使用 environment 设置 HOME 和 USER 应该可以解决问题。但我没有任何机会。 Chef 客户端仅使用已编译的 nodejs。不是nvm安装的那个。

可能出了什么问题?

(顺便说一句,在同一台服务器上但与另一个用户一起,我从源代码编译了 node.js 并全局安装了 pm2。我认为它可能与我的问题有关,但是,如果它是这样的,为什么我在新用户帐户中手动安装 pm2 时它不会造成任何伤害?)

npm install -g 是全局安装,这意味着您需要权限才能写入安装了 Node/NPM 的全局文件夹(在本例中为 /usr/local/bin)。您可能不想使用 -g,因为它仅适用于人类,不适用于工具。

我相信在 OpsWorks 中,您还可以通过在应用的说明书中创建一个新文件来覆盖安装的 Node 版本:attributes/customize.rb。那么:

normal[:opsworks_nodejs][:version] = '4.4.0'

这应该下载正确版本的节点,而不是使用节点 0.10...因此内置的 OpsWorks 应用程序 runner/monitor (monit) 应该可以工作,而不必安装 PM2。