bundle command not found on bash script - ruby-on-rails

I'm wrote a script to automatically run when reboot on crontab
this is my configuration in crontab -e
#reboot /home/deploy/startup_script >> /home/deploy/startup_script.log 2>$1
This start the script and create logs in /home/deploy
Then this is the startup_script
#!/bin/bash
echo "Changing directory"
cd /home/deploy/source/myapp
echo $PWD
echo "Pulling Dev Branch..."
git pull origin dev_branch
echo "Running Bundle Install"
sudo gem install bundler
bundle install
echo "Deploying to Staging..."
bundle exec cap staging deploy
when I run this script manually using ./startup_script it runs properly but when I run it automatically in crontab it shoes bundle command not found even I install the bundler already.
Here's the logs from startup_script.log
Changing directory
/home/deploy/source/myapp
Pulling Dev Branch...
From ssh://1.xx.xx.xx.io:20194/xx/myapp
* branch dev_branch -> FETCH_HEAD
Already up-to-date.
Running Bundle Install
Successfully installed bundler-2.0.2
Parsing documentation for bundler-2.0.2
Done installing documentation for bundler after 5 seconds
1 gem installed
/home/deploy/startup_script: line 12: bundle: command not found
Deploying to Staging...
/home/deploy/startup_script: line 15: bundle: command not found

The cron often clears the whole environment, including this $PATH variable. Therefore, the script may behave differently in your cron compared to the behavior in the shell. To avoid having to type the absolute path to a command, shells introduced the $PATH environment variable, each directory is separated by a : and searches are done from left to right.
Option I: You can use absolute path:
Run which bundle as sudoer to get the full path for the bundle command. If the output is /usr/bin/bundle, your bundle command in the script would look like:
/usr/bin/bundle install
Option II: Set the PATH variable:
Run echo "$PATH" as user who runs this script to get the $PATH variable and make sure this variable is available in your cron script too. For example, if the output was /usr/local/bin:/usr/bin:/bin, you would put the below line in the top of your shell script:
export PATH="/usr/local/bin:/usr/bin:/bin"

The environment that your crontab uses is going to be different than your regular login shell.
Now, I might be wrong about this, but I think when the crontab executes, it's not a login shell, so it doesn't have anything you've added to your path in your .bashrc or .bash_profile.
The best practice here would be to use the full path of the executable for bundle.

Redirecting stderr to stdout, there should be 2>&1
Is the path where the gem packages are installed is added to the $PATH variable? Try to provide the full path to this script
I suggest you make an entry to see what environment variables you have for crontab:
* * * * * printenv > ~/printenv.log

Related

How to deploy my Webpackered Rails app with Capistrano and Yarn

Problem with capistrano and Yarn
I tried to deploy my webpackered rails app to AWS with this capistrano script,
namespace :webpacker do
task :install do
on roles(:web) do
within release_path do
execute "bin/yarn"
end
end
end
end
after 'bundler:install', 'webpacker:install'
however I got the following log and deploy was failed.
INFO [74b2160e] Running /usr/bin/env bin/yarn as webmaster#example.com
DEBUG [74b2160e] Command: cd /data/example/releases/20170324031517 && ( export PATH="/usr/local/bin:$PATH" RBENV_ROOT="/usr/local/rbenv" RBENV_VERSION="2.4.0" NODENV_ROOT="/usr/local/nodenv" NODENV_VERSION="7.0.0" ; /usr/bin/env bin/yarn )
DEBUG [74b2160e] Node version 0.10.48 is not supported, please use Node.js 4.0 or higher.
So, I did ssh as webmaster to confirm that env was correct by following shell command.
which node
/usr/local/nodenv/shims/node
node --version
v7.0.0
which yarn
/usr/bin/yarn
yarn --version
0.21.3
I assume env variables is incorrect but don't know why env variable is incorrect.
Would you teach me how to fix this?
Node version 0.10.48 is not supported, please use Node.js 4.0 or higher
added
When added append :nodenv_map_bins, 'bin/yarn', another issue appear.
INFO [aab774c8] Running NODENV_ROOT=/usr/local/nodenv NODENV_VERSION=7.0.0 /usr/local/nodenv/bin/nodenv exec bin/yarn as webmaster#example.com
DEBUG [aab774c8] Command: cd /data/example/releases/20170324175015 && ( export PATH="/usr/local/bin:$PATH" RBENV_ROOT="/usr/local/rbenv" RBENV_VERSION="2.4.0" NODENV_ROOT="/usr/local/nodenv" NODENV_VERSION="7.0.0" RAILS_ENV="staging" ; NODENV_ROOT=/usr/local/nodenv NODENV_VERSION=7.0.0 /usr/local/nodenv/bin/nodenv exec bin/yarn )
DEBUG [aab774c8] nodenv: bin/yarn: command not found
The issue appears to be that you are using Nodenv. Capistrano runs in a Non-login, Non-interactive shell: http://capistranorb.com/documentation/advanced-features/ptys/ As a result, Capistrano is using system Node, not the overridden version in your .bash_profile.
This means that you probably need to evaluate the Nodenv script as part of running commands. Thankfully, it looks like there is a Gem for that: https://github.com/platanus/capistrano-nodenv
You will probably need to add bin/yarn to the :nodenv_map_bins. Something like:
append :nodenv_map_bins, 'bin/yarn'
You need to add yarn to your path or create an alias.
There's a gem for this as well: https://github.com/ManifoldScholar/capistrano-yarn

How do I run bundle remotely when RVM is involved

I am trying to create a tiny shell script that will deploy a Rails app by first rsync'ing, then running the bundle command remotely via ssh. My shell script looks like this:
#!/bin/bash
REMOTE_SERVER="myserver.com"
REMOTE_USER="me"
REMOTE_PATH="/home/me/"
BUNDLE_PATH="/usr/local/rvm/gems/ruby-2.0.0-p353/bin/bundle"
# Step 1: Rsync
rsync -ave ssh --exclude-from '.ignore' ./ $REMOTE_USER#$REMOTE_SERVER:$REMOTE_PATH
# Step 2: Bundle
ssh $REMOTE_USER#$REMOTE_SERVER "cd $REMOTE_PATH && $BUNDLE_PATH install"
Rsync'ing works fine but when RVM is involved, the bundle line throws the following error:
/usr/bin/env: ruby_executable_hooks: No such file or directory
So, I'm wondering ... Is it possible to run the bundle (and other commands like rake) as part of a single ssh command?
If it matters, the remote server is running Ubuntu 14.
This problem has already been solved by the community. It's called Capistrano.
http://capistranorb.com/

Run rake outside of rails_root/Incron doesn't run rake or bundle commands for rails

I have a rails application in /home/myuser/watchDir/myapp and an incron job set to watch the ../watchDir for modification. Once triggered, incron will run a script, /usr/local/bin/myscript.sh. This is the only place I could get incron to run a script from. In that script I have calls to run rake and bundle commands in my root app. I The script IS being run (I have a test for that) but the bundle and rake commands both fail silently. I am fairly new to linux and internet research has given some solutions. I have all absolute paths in my scripts. I tried adding my bash_profile to the scripts/incron commands. I tried having the incron script run another script located in my home directory. All the scripts are executable. I tried using the --gemfile option for bundle but that doesn't wokr. Does anyone know what I have to do here? Basically, I want to run the bundle and rake commands outside of RAILS_ROOT. I also would like to know if incron complicates the use of the rails commands. Thanks.
EDIT:
Here are the relevant files:
Incrontab:
/home/myuser/watchDir/ IN_MODIFY,IN_CLOSE_WRITE,IN_CLOSE_NOWRITE /bin/bash /usr/local/bin/runT.sh $#/$#
I also tried this:
/home/myuser/watchDir/ IN_MODIFY,IN_CLOSE,IN_CLOSE_WRITE,IN_CLOSE_NOWRITE source '/home/myuser/.bash_profile && /bin/sh /usr/local/bin/runT.sh' $#/$#
And here's the script it's calling:
#!/bin/bash
mkdir /home/myuser/worked #This is to ensure that that incron is running and executing this script
cd /home/myuser/watchDir/myapp
/home/myuser/.rvm/gems/ruby-1.9.3-p545/bin/bundle install --gemfile /home/myuser/watchDir/myApp/Gemfile
/home/myuser/.rvm/gems/ruby-1.9.3-p545/bin/rake -f /home/myUser/watchDir/myApp
My .bash_profile file:
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
source ~/.profile
To sum up my last comments ... change your icrontab entry to be:
/home/myuser/watchDir/ IN_MODIFY,IN_CLOSE_WRITE,IN_CLOSE_NOWRITE /bin/bash /usr/local/bin/runT.sh $#/$#
And the script to be:
#!/bin/bash
source /home/myuser/.bash_profile
mkdir /home/myuser/worked #This is to ensure that that incron is running and executing this script
cd /home/myuser/watchDir/myapp
/home/myuser/.rvm/gems/ruby-1.9.3-p545/bin/bundle install --gemfile /home/myuser/watchDir/myApp/Gemfile
#/home/myuser/.rvm/gems/ruby-1.9.3-p545/bin/rake -f /home/myUser/watchDir/myApp

bundle exec not working with crontab

I'm trying to execute the following shell script using crontab:
#!/bin/sh
cd /mnt/voylla-production/current
bundle exec rake maintenance:last_2_days_orders
bundle exec rake maintenance:send_last_2_days_payment_dropouts
The crontab entry is
0 16 * * * /mnt/voylla-production/releases/20131031003111/voylla_scripts/cj_4pm.sh
I'm getting the following error message in the mail:
/mnt/voylla-staging/current/voylla_scripts/cj_4pm.sh: line 3: bundle: command not found
/mnt/voylla-staging/current/voylla_scripts/cj_4pm.sh: line 4: bundle: command not found
I dont get the error when I run the commands manually. Not sure what's going on here. Could someone please point out.
Thanks
A nice trick to get all environment properly set up in crontab is to use /bin/bash -l :
0 16 * * * /bin/bash -l -c '/mnt/voylla-production/releases/20131031003111/voylla_scripts/cj_4pm.sh'
The -l option will invoke a full login shell, thus reading your bashrc file and any path / rvm setting it performs.
If you want to simplify your crontab management and use this trick - as well as others - without having to think about them, you can use the Whenever gem. It also play very nice with capistrano, if you use it, regenerating crontab on deploy.
The user used by cron does not have the correct environment.
You can tell cron which user to use. For a bash script, you can so something like:
#!/bin/bash --login
source /home/user/.bashrc
rvm use 2.0.0#gemset #if you use rvm
cd /path/to/project && bundle exec xyz
We need set right path to our bundle:
#!/bin/sh
cd /mnt/voylla-production/current
/home/youruser/.rbenv/shims/bundle exec rake maintenance:last_2_days_orders

RVM isnt setting environment with cron

I'm having a rough time executing script/runner with a cron and RVM. I believe the issues lie with the rvm environment not being set before the runner is executed.
currently im throwing the error
/bin/sh: 1.sql: command not found
which is more than i've gotten earlier, so i guess that's good.
I've read this thread Need to set up rvm environment prior to every cron job but im still not really getting it. Part of the problem i think is the error reporting.
this is my runner thus far.
*/1 * * * * * /bin/bash -l -c 'rvm use 1.8.7-p352#2310; cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"'
as per the above link, i tried making a rvm_cron_runner.
i created a file and placed this in it:
#!/bin/sh
source "/Users/dude/.rvm/scripts/rvm"
exec $1
then i updated my crontab to this.
*/1 * * * * * /bin/bash -l -c '/Users/dude/development/app/my_app2310/rvm_cron_runner; rvm use 1.8.7-p352#2310; cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"'
This also has made no difference. i get no error. nothing.
Can anyone see what i'm doing incorrectly?
P.S i hope my code formatting worked.
Could you try to place the code you want to run in a separate script, and then use the rvm_cron_runner ?
So place your actions in a file called /path/cron_job
rvm use 1.8.7-p352#2310
cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"
and then in your crontab write
1 2 * * * /path/rvm_cron_runner /path/cron_job
The differences:
this does not start a separate shell
use the parameter of the rvm_cron_runner
If you would use an .rvmrc file, you could even drop the rvm use ... line, I think.
You don't need to write a second cron runner (following that logic, you might as well write a third cron runner runner). Please keep things simple. All you need to do is configure your cron job to launch a bash shell, and make that bash shell load your environment.
The shebang line in your script should not refer directly to a ruby executable, but to rvm's ruby:
#!/usr/bin/env ruby
This instructs the script to load the environment and run ruby as we would on the command line with rvm loaded.
On many UNIX derived systems, crontabs can have a configuration section before the actual lines that define the jobs to be run. If this is the case, you would then specify:
SHELL=/path/to/bash
This will ensure that the cron job will be spawned from bash. Still, your environment is missing, so to instruct bash to load your environment, you will want to add to the configuration section the following:
BASH_ENV=/path/to/environment (typically .bash_profile or .bashrc)
HOME is automatically derived from the /etc/passwd line of the crontab owner, but you can override it.
HOME=/path/to/home
After this, a cron job might look like this:
15 14 1 * * $HOME/rvm_script.rb
What if your crontab doesn't support the configuration section. Well, you will have to give all the environment directives in one line, with the job itself. For example,
15 14 1 * * export BASH_ENV=/path/to/environment && /full/path/to/bash -c '/full/path/to/rvm_script.rb'
Full blog post on the subject
You can use rvm wrappers:
/home/deploy/.rvm/wrappers/ruby-2.2.4/ruby
Source: https://rvm.io/deployment/cron#direct

Resources