Shell commands fail in Rails in production mode - ruby-on-rails

I have deployed on a VPS a Rails 4 application that executes shell command depending on the tasks. The app runs on Nginx with Passenger.
The situation I am having is that none of the shell commands work. After a bit of debugging, I've noticed that every command returns a "not found" error message.
For example:
out = %x[date 2>&1] # outputs 'sh: 1: date: not found\n'
why is this happening? is there some configuration setting I should set to allow shell commands in production mode? I am quite new to rails so I'm not really sure what could be causing this.
UPDATE:
Here's a bit more information, when querying from rails whoami, i get www-data, if I print the $PATH I get /usr/local/lib/ruby/gems/2.1.0/bin but then if in the command line execute sudo -u www-data printenv PATH the result is /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin... Does this makes any sense?

Related

Google App Engine: Ruby on Rails - Execute migrations automatically

I was wondering if it was possible to run migrations automatically during deployment with Google App Engine. I have been using AWS Elasticbeanstalk for a while and they were ran automatically but now I am considering moving to the Google App Engine for my future projects.
Right now, I must run this command manually:
bundle exec rake appengine:exec -- bundle exec rake db:migrate GAE_CONFIG=app.yml
Thank you
WARNING: As discussed in comments, there is a race condition in migrations if deployment is done on multiple containers in parallel, because it will try to run migration on all containers. Solution is being discussed in comments, i will update this answer when we land on something.
Disclaimer: This answer is not exactly what was asked for, but it solves same problem and it works. And from what i can tell from question, doing it with some appengine config is not a requirement, rather he just want the migrations to run automatically.
I will expand on my comment on question, here is something i tried and it works. I am strong believer of KISS(keep it simple and stupid). So instead of trying to figure out appengine(which i have never used anyway) if i were you, i would take a generic approach. Which is, to plug into rails server booting process and trigger migrations. For this we have multiple approaches.
With my understanding of appengine and suggested by this official doc link appengine has a app.yaml file, this file has an entry something like:
entrypoint: rails server
So we will use this entry point to plug in our code to run migrations before starting server. For this i did this:
Make a new file in bin directory, i named it
rails_with_migrations.sh you can name it whatever you like.
Give it execute permissions with chmod +x bin/rails_with_migrations.sh
Put this code inside it:
#!/bin/bash
bundle exec rake db:migrate
bundle exec rails $#
Of course you can give whatever RAILS_ENV you want to give these.
Now in app.yaml on the entrypoint section, instead of rails server give it bin/rails_with_migrations.sh server and it should be it. It worked on local, should work everywhere.
NOTE: In entrypoint: i have bin/rails_with_migrations.sh server here, server is rails command parameter, you can pass as much parameters as you like these all will be passed to rails server command with $#'s magic. It is there to allow you to pass port and any other parameters you may need to provide for your environment. Also it allows you to run rails console locally with bin/rails_with_migrations.sh console which will also cause migrations to get triggered.
UPDATE1: As per comment, i checked what happens if migration fails, and it starts server even if migration fail. We can alter this behavior of-course in our sh file.
UPDATE2: The shell-script with migration error code handling will look something like:
#!/bin/bash
bundle exec rake db:migrate
if [ $? -eq 0 ]
then
bundle exec rails $#
else
echo "Failure: migrations failed, please check application logs for more details." >&2
exit 1
fi
This update will prevent server from starting and causing a non zero exit code from the script, which should indicate that this command failed.

how to auto start rails after maintenence?

i host my rails application on cloud server,
my server is using centos 6,
and what i am trying to achieve is,
i want everytime server is restarted, i need my rails app to do an auto start.
i tried crontab, but somehow i can't get it working,
here is my crontab content :
#reboot cd ~/UAAdmin/urbanacecode && /usr/local/rvm/gems/ruby-2.2.4/bin/bundle exec rails server -d >> deploy_log.log 2>&1 &
as you can see, i dump my crontab result to log file,
somehow it's not working?
here is my dump result :
/usr/bin/env: ruby_executable_hooks: No such file or directory
this is very strange, because when i tried to run my crontab commands manually, i can see the server running.
i ran this manually
cd ~/UAAdmin/urbanacecode
then
/usr/local/rvm/gems/ruby-2.2.4/bin/bundle exec rails server -d
what should i do to get it working? please advice,
oh btw i am pretty new with linux OS, so kindly give an example
how to do it properly.
many thanks..

Ruby system command fails Apache(Passenger)

Attempting to build statistics into a side project via Rserve- Everything works in testing and rails console but in production under:
apache(passenger), Rails 4, ruby-2.3.0.
the commands work in the rails console on the production box and I've confirmed that:
/bin/R is in the rails production (apache) path.
system "R CMD Rserve" works as expected in rails console on production host with production environment loaded
In production running Apache(Passenger):
system "R CMD Rserve" returns false
$?.inspect returns -> Process::Status: pid 11144 exit 2
The exit status 2 is throwing me off because it indicated a missing keyword or command, or permission problem.
Anybody run into this? I think the issue is in passenger but the limited output is making this hard to debug..

How to run initialization script on starting a Rails server?

I have a simple shell script (happy.sh) that I am currently running by hand (. ./happy.sh) every time I restart a rails server. It sets some environment variables that I need because of various APIs I'm using. However, I was wondering if there's some way of having rails run the script itself whenever I run "guard" or "rails s"
Thanks
If you use foreman, you can define all processes you needed started on application start into a Procfile. (including bbundle exec rails server -p $PORT)
By calling foreman start, all the process starts up.
More information can be gotten here on this cast
Proper way of setting ENV variables is putting them in bash_proflle or bashrc depending of linux distro.
vi ~/.bash_proflle
And then add something like
export MY_RAILS_VAR=123
Then you don't need to run any ENV initialization scripts on rails start.

Running Rails Task From Cron

I have a Rails runner task that I want to run from cron, but of course cron runs as root and so the environment is set up improperly to get RVM to work properly. I've tried a number of things and none have worked thus far. The crontab entry is:
* 0 * * * root cd /home/deploy/rails_apps/supercharger/current/ && /usr/local/rvm/wrappers/ruby-1.9.3-p484/ruby bundle exec rails runner -e production "Charger.start"
Apologies for the super long command line. Anyhow, the error I'm getting from this is:
ruby: No such file or directory -- bundle (LoadError)
So ruby is being found in the RVM directory, but again, the environment is wrong.
I tried rvm alias delete [alias_name] and it seemed to do something, but darn if I know where the wrapper it generated went. I looked in /usr/local/rvm/wrappers and didn't see one with the name I had specified.
This seems like a common problem -- common enough that the whenever gem exists. The runner command I'm using is so simple, it seemed like a slam dunk to just put this entry in the crontab and go, but not so much...
Any help with this is appreciated.
It sounds like you could use a third-party tool to tether your Rails app to cron: Whenever. You already know about it, but it seems you never tried it. This gem includes a simple DSL that could be applied in your case like:
every :day # Or specify another period, or something else, see README
runner "Charger.start"
end
Once you've defined your schedule, you'll need to write it into crontab with whenever command line utility. See README file and whenever --help for details.
It should not cause any performance impact at runtime since all it does is conversion into crontab format upon deployment or explicit command. It's not needed, once the server is running, everything is done by cron after that.
If you don't want an extra gem anyway, you might as well check what command does it issue for executing your task. Still, an automated way of adding a cron task is easier to maintain and to deploy. Sure, just tossing a line into the crontab is easier — just for you and just this once. Then it starts to get repetitive and tiring, not to mention confusion for other potential developers who will have to set up something similar on their own machines.
You can run cron as different user than root. Even in your example the task begins with
* 0 * * * root cd
root is the user that runs the command. You can edit it with crontab -e -u username.
If you insist on running cron task as root or running as other user does not work for some reason, you can switch user with su. For example:
su - username -c "bundle exec rails runner -e production "Charger.start"

Resources