seane seane - 1 year ago 50
PHP Question

PHP won't recognize my RVM Ruby installation

Background: I'm building a website with PHP, and I need to have the website call a script that's written in Ruby 1.9. I'm using a CentOS 5.10 server that already had Ruby 1.8 installed on it, and I used RVM to upgrade to Ruby 1.9. When I type

ruby --version
from the command-line, it says I have Ruby 1.9 installed (as expected). However, when I use PHP to call
exec('ruby --version');
, it says I have Ruby 1.8 installed. In addition, when I use PHP to call
exec('which rvm');
, it does not return anything, even though I know RVM is installed.

Question: How can I allow PHP to use an RVM installation of Ruby 1.9 instead of the system installation of Ruby 1.8?

Answer Source

It's important to keep in mind that the user that runs the web server process which executes your PHP script is different from you, the user, when using the command line. To verify this, you can create a php script like the following:


print exec('whoami');

Run that script as yourself from the command line, and you'll see your username. Put that script in a web accessible folder, and run it through your web browser (for example: http://localhost/whoami.php), and you'll probably see a username like apache or www-data.

You can also compare which ruby is running between you at the command line and your web browser. Use the following php script:


print exec('which ruby');

Run that from the command line and then also run that in your web browser. Those should be two different locations - and, of course, that's your core problem.

When you installed rvm, it's likely that a line of code was appended to your .bash_profile or .profile file in your home folder. Look near the end of either of those files to see if there is a line that looks similar to this:

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

This line initializes your shell environment every time you login or open a terminal so that rvm is accessible. To verify this, you can create a php file with the following:


print exec('env | grep rvm');

Running this as yourself, from the command line, you should see lines related to rvm_bin_path and rvm_path and others. But, put this script in a web accessible folder and run it from your browser - you'll notice that none of those lines are outputted to your browser. That's because the shell that the PHP process spawns, when running as www-data user (or whatever user your web server runs as) doesn't have the same rvm initialization lines that your `.bash_profile script has.

One possible way to solve this problem is to set the correct environment variables in PHP so that, when exec is called, it is called within an environment that is already properly initialized to run rvm related things (like setting the ruby version). But, most likely, there are certain safe_mode protections on PHP which prevent you from setting those environment variables in your PHP script.

The other solution, which is a bit of a hack, is to have your PHP script in the browser run the same ruby interpreter that you would run in the command line. That is, instead of exec('ruby some_ruby_file.rb'), you would do exec('/home/my_username/.rvm/rubies/ruby-1.9/bin/ruby some_ruby_file.rb') - I just made up that path to your ruby interpreter. From the command line, run which ruby to find out the exact path to your ruby interpreter. BUT you have to make sure that www-data has permission to run this ruby interpreter in your folder. To avoid this hassle, though this is even more of a hack, is simply to make a copy of that ruby interpreter and place it in a bin folder owned by www-data, and have your PHP script exec that ruby interpreter.