Why do I have to source /etc/profile before command is found

I am fairly new to InSpec and just started testing a cookbook that installs a ruby using rvm. I first try to simply do:

describe command('ruby -v') do
  it { should exist }
  its('stdout') { should include ruby['ruby_version']}

This however failed. After some tinkering I discovered that I need to run the following for the test to succeed:

describe command('source /etc/profile && ruby -v') do
  it { should exist }
  its('stdout') { should include ruby['ruby_version']}

I wonder why this is needed? If this is indeed needed and not a erroneous assumption on my side: Is there any way to move that into a helper or even better run it once and have it persist?


This also seems to only work in the InSpec shell, but not when run using kitchen test. When run this way it throws:

sudo: source: command not found\n

in stderr.


InSpec is using a non-interactive shell. I am not 100% sure how you installed ruby and why it is not part of the default path. From my perspective you have two options:

  • you can circumvent the issue by using the absolute path of the ruby binary
  • use the bash InSpec resource. source is part of bash and requires you to have a bash shell available.

I hope that was helpful?

Thank you very much that did the trick.

The test is now succeeding if I use:

describe bash('source /etc/profile && ruby -v') do
  its('stdout') { should include node['ruby_version'] }

Ruby has been installed using rvm install ruby-#{node['ruby_version']} after rvm had been installed.

This is specifically needed because of how RVM works - it relies on profiles to load it’s special magic into the shell. This isn’t unique solely to RVM either but is fairly common with programming language version managers.