12

I'm trying to run the following chef command:

# install zombiejs, q (promises), should, coffee-script & mocha                 
execute "install q and zombiejs" do                                             
  cwd "/home/vagrant"                                                           
  user "vagrant"                                                                
  action :run                                                                   
  command "npm install -g q zombie should mocha coffee-script"                  
end

But it keeps failing because it can't find npm:

execute[install q and zombiejs] (chef-redtail::default line 205) had an error: Errno::ENOENT: No such file or directory - npm install -g q zombie should mocha coffee-script

Logging in to vagrant via vagrant ssh and running the command manually works perfectly fine. Logging in as root, via sudo -i and running the command fails for the same reason the chef recipe fails (npm is installed locally only for the vagrant user, not for root: this is what I want).

So... how can I specify this chef execute block to run as the vagrant user and not root?


UPDATE: I think this sums up my problem:

(ssh) /vagrant git:backbone ❯ whoami
vagrant

(ssh) /vagrant git:backbone ❯ which npm
/home/vagrant/.local/bin/npm

(ssh) /vagrant git:backbone ❯ echo $PATH
/home/vagrant/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

(ssh) /vagrant git:backbone ❯ sudo -H -u vagrant -i echo $PATH
/home/vagrant/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

(ssh) /vagrant git:backbone ❯ sudo -H -u vagrant -i which npm
npm not found

via http://tickets.opscode.com/browse/CHEF-2517


ANOTHER UPDATE: So I just noticed this discrepancy:

(ssh) /vagrant git:backbone ❯ sudo -H -u vagrant -i echo $PATH
/home/vagrant/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

(ssh) /vagrant git:backbone ❯ sudo -H -u vagrant -i export
HOME=/home/vagrant
LANG=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LOGNAME=vagrant
MAIL=/var/mail/vagrant
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
SHELL=/bin/zsh
SSH_AUTH_SOCK=/tmp/ssh-uJUopA4146/agent.4146
SUDO_COMMAND='/bin/zsh -c export'
SUDO_GID=1001
SUDO_UID=1000
SUDO_USER=vagrant
TERM=xterm
USER=vagrant

Notice the difference in PATH? The export doesn't have the /home/vagrant/.local/bin directory listed in it... why would the first echo return PATH with it and the second export return PATH without it? Is this the issue?

3 Answers 3

13

To execute a script or a command as a user, you need to combine su -l and bash -i:

 execute "npm_install" do
    command "su vagrant -l -c 'cd /shared-with-host/helperScripts/ && bash -i npm install -g q zombie should mocha coffee-script'" 
    action :run
  end

Because of some bugs, chef does not set properly the environment for the specified user in execute. The narced133's solution will not work.

7

You can use environment to set the HOME and USER environment variables in your execute block.

execute "install q and zombiejs" do                                             
    cwd "/home/vagrant"                                                           
    user "vagrant"                                                                
    action :run   
    environment ({'HOME' => '/home/vagrant', 'USER' => 'vagrant'})                                                             
    command "npm install -g q zombie should mocha coffee-script"                  
end

I use this frequently to install vagrant plugins as the vagrant user inside my VMs. You could also set other environment variables if needed by whatever command you are trying to execute.

1
  • This is a very clean answer IMHO. Apr 18, 2017 at 0:04
2

It sounds like Chef is executing as the vagrant user but not searching the same PATH as your shell. Login using vagrant ssh and run which npm. It will return something like /path/to/bin/npm. Replace /path/to/bin/ below to force Chef to search the appropriate directory.

execute "install q and zombiejs" do                                             
    cwd "/home/vagrant"                                                           
    user "vagrant"                                                                
    action :run   
    path ["/path/to/bin/"]                                                               
    command "npm install -g q zombie should mocha coffee-script"                  
end
3
  • Just tried that; no dice. Still fails with the same error in the post. Any other suggestions?
    – neezer
    Jun 28, 2012 at 4:54
  • Could try pointing the command directly at the npm symlink rather than trying to get the path right. command "/home/vagrant/.local/bin/npm install -g q zombie should mocha coffee-script
    – narced133
    Jun 28, 2012 at 21:39
  • I can confirm that "path" does nothing, but pointing the command directly to the binary does the trick. This seems like a bug in Chef.
    – FRKT
    Nov 16, 2012 at 10:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .