How can I know a file's content with chef - bash

I'm trying to change the gem source using execute resource but I need to do this just one time.
remove_rubygems = 'gem sources -r http://rubygems.org/'
execute 'change sources to our gem server' do
command "#{remove_rubygems} && gem sources -a http://mygemserver"
creates "~/.gemrc"
end
All this because when I execute this resource many times the .gemrc file look like it.
vagrant#leibniz-app:~$ gem source
*** CURRENT SOURCES ***
http://mygemserver/
http://mygemserver/
http://mygemserver/
http://mygemserver/
...
Then, I want mygemserver one time in the .gemrc file.
How can I do it?
Is there any way to know the content of .gemrc before the execute my resource.?

Don't use ~/ in your path; this is why the creates line was not working to prevent the execute resource from being run when the file already existed.
execute 'change sources to our gem server' do
command "#{remove_rubygems} && gem sources -a http://mygemserver"
creates "/root/.gemrc"
end
Alternately, if you want to check whether the file contains a specific line:
execute 'change sources to our gem server' do
command "#{remove_rubygems} && gem sources -a http://mygemserver"
not_if "grep -F -q -e http://mygemserver/ ~/.gemrc" # this uses a shell, so the
# tilde should work here.
end

Related

Understanding rubygems 'require' in sudo vs rvmsudo

I'm using Ubuntu 12.04.4 TLS
I wrote a simple shell script in /home/abdo/sample_serv.sh that executes a Ruby file:
#!/bin/bash
/home/abdo/.rvm/rubies/ruby-2.1.0/bin/ruby /home/abdo/sample_serv.rb
and /home/abdo/sample_serv.rb containing the code below:
puts $:
require 'sinatra'
set :port, 8084
get '/' do
%{ <html><body>Hello from Abdo</body></html> }
end
Executing rvmsudo ./home/abdo/sample_serv.sh works just fine but I would like to get sudo ./home/abdo/sample_serv.sh to work by passing the necessary environment variables because I am having issues with upstart.
The issue arises in my /etc/init/foo.conf
description "webserver test"
start on runlevel [23]
stop on shutdown
pre-start script
exec >> /var/log/unicorn_test.log 2>&1
echo starting
end script
script
exec >> /var/log/unicorn_test.log 2>&1
/bin/bash /home/abdo/.rvm/bin/rvmsudo /home/abdo/sample_serv.sh
echo started
end script
When the line /bin/bash /home/abdo/.rvm/bin/rvmsudo /home/abdo/sample_serv.sh is reached, I get
/home/abdo/.rvm/rubies/ruby-2.1.0/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in
`require': cannot load such file -- sinatra (LoadError)
I was able to get the same ruby -v as that of my user but it looks like the GEM_PATH (even if I set it inside the upstart config file), is not helping.
Basically, if I can understand how (and where -- gem env is not helping since gem is not a command when I do sudo) rubygems looks for a file being required, I should be able to move forward.
When you run under sudo you run in a different environment, where gem is not installed, the $PATH is different, so things may not run smoothly.
You may want to try this:
Changing sudo's strict defaults
There are 3 things needed to mitigate this situation if you encounter
it:
the user that is invoking sudo must have export rvmsudo_secure_path=0 set on his shell environment (think .bashrc,
.bash_profile or .zshrc)
comment out Defaults secure_path=... on /etc/sudoers
add Defaults env_keep +="rvm_bin_path GEM_HOME IRBRC MY_RUBY_HOME rvm_path rvm_prefix rvm_version GEM_PATH rvmsudo_secure_path
RUBY_VERSION rvm_ruby_string rvm_delete_flag" to /etc/sudoers in
rare cases it is required to add more variables - they should be
reported by first run of rvmsudo.
After these changes, you should be able to use rvmsudo preserving
the same password/no-password directives as "normal" sudo calls.
Edit
If you don't want to change the defaults, you can try to synchronize the values of the environment values stated above (rvm_bin_path GEM_HOME IRBRC MY_RUBY_HOME rvm_path rvm_prefix rvm_version GEM_PATH rvmsudo_secure_path RUBY_VERSION rvm_ruby_string rvm_delete_flag) to your root user.
If that doesn't work, you can try installing rvm as root, and using that environment (instead of /home/abdo/.rvm/bin/rvm) to run your code.

Update of blog site via cron does not work

Currently i have blog site which works with Octopress in relationship with Git but currently facing a problm that i can't update the site automatically via a cron triggered script. I'm using a script (update.sh) with the following contents:
#!/bin/bash -x
export PATH=/usr/local/rvm/gems/ruby-2.0.0-p247#global/bin/:/usr/local/rvm/bin/rvm:$PATH
cd /usr/local/repositories
cd supose.git
git fetch -q --all
cd /usr/local/vhost/octopress
git pull
rake generate
/usr/local/rvm/gems/ruby-2.0.0-p247/bin/jekyll generate
But i alway get the following error message:
+ rake generate
## Generating Site with Jekyll
+ /usr/local/rvm/gems/ruby-2.0.0-p247/bin/jekyll generate
invalid command. Use --help for more information
I know there must be a relationship with the environment, but i can't get the point to get it running.
If i login into the machine and cd into the folder and do rake generat it works like a charm.
Check the PATH you have when you login against the one crontab gives you. It may be quite different. rvm does other things as well as set the path. You'll need to make sure our PATH is correct, and run the script that rvm puts in your login profile [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm". You could try running . ~/.bash_profile ; (path_to_script)/update.sh as the crontab command.
instead of changing PATH use a wrapper - this will provide environment for your ruby:
rvm wrapper ruby-2.0.0-p247 --no-links rake jekyll
and then use it like this:
/usr/local/rvm/wrappers/ruby-2.0.0-p247/rake generate
/usr/local/rvm/wrappers/ruby-2.0.0-p247/jekyll generate

rbenv: is it safe to embed a "bundle exec" call in the shims?

rbenv requires you to manually run "bundle exec" if you're running an executable from a gem, to avoid loading a different version of that gem compared with your Gemfile.
Are there any downsides to having the rbenv shims run "bundle exec" when a Gemfile is present in the current directory? It's a somewhat naive approach, because it doesn't handle Gemfile's that are further up the directory tree, but I don't need that behavior. The change would also make sure the current shim isn't named "bundle" or there could be an infinite recursion.
Patch:
diff --git a/libexec/rbenv-rehash b/libexec/rbenv-rehash
index eebc4d3..00f4ec0 100755
--- a/libexec/rbenv-rehash
+++ b/libexec/rbenv-rehash
## -38,7 +38,14 ## create_prototype_shim() {
#!/usr/bin/env bash
set -e
export RBENV_ROOT="$RBENV_ROOT"
-exec rbenv exec "\${0##*/}" "\$#"
+# This only handles Gemfile in current dir
+if [[ \$RBENV_AUTO_BUNDLE = '1' && -e Gemfile && \`basename \$0\` != 'bundle' ]]; then
+ exec 3>/dev/tty
+ echo "rbenv: Using Gemfile" >&3
+ exec rbenv exec bundle exec "\${0##*/}" "\$#"
+else
+ exec rbenv exec "\${0##*/}" "\$#"
+fi
SH
chmod +x "$PROTOTYPE_SHIM_PATH"
}
You must set environment variable RBENV_AUTO_BUNDLE=1 to enable the auto "bundle exec" behavior.
If there's enough demand I might submit a patch.
To apply the patch, just put the patch file in your .rbenv dir, and run
git apply PATCHFILE
To test the patch, you'll have to delete your shims and run "rbenv rehash".
To undo:
git apply -R PATCHFILE
or
git checkout -- libexec/rbenv-rehash
then recreate the shims again.
It does seem that vim will run some ruby when you load a ruby file, and bundle exec will be used with that too. You could disable the auto behavior via let $RBENV_AUTO_BUNDLE=0.
rbenv requires you to manually run "bundle exec" if you're running an
executable from a gem, to avoid loading a different version of that
gem compared with your Gemfile.
Unless you use the rbenv-bundler plugin, which IMHO is a saner approach than trying to reimplemented that behavior yourself. If there's anything missing from that plugin, rather contribute it there.

Setting path for whenever in cron so it can find ruby

My ruby is in /usr/local/bin. whenever can't find it, and setting PATH at the top of my cron file doesn't work either, I think because whenever is running the command inside of a new bash instance.
# this does not work
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin
# Begin Whenever generated tasks for: foo
0 * * * * /bin/bash -l -c 'cd /srv/foo/releases/20110429110637 && script/rails runner -e production '\''ActiveRecord::SessionStore::Session.destroy_recent(15)'\'''
# End Whenever generated tasks for: foo
How can I tell whenever where my ruby binary is? Making a symbolic link from /usr/bin seems messy to me, but I guess that might be the only option.
This question offers env :PATH, "..." in schedule.rb as a solution, but (a) I can't find any documentation of that feature anywhere in the docs (b) it doesn't seem to have solved the asker's problem (unfortunately it takes non-trivial turnaround time for me to just try it).
update actually it is in the bottom of this page, i'll try it now.
more info
I can't modify the cron command because it's generated by whenever
i verified that if I make a new bash shell with bash -l, /usr/bin/env finds ruby just fine
I just tried the exact command in cron, starting with /bin/bash, from the command line of that user, and it worked.
so, this is very mysterious...
The solution is to put this in schedule.rb:
env :PATH, ENV['PATH']
Here's a little guide I put together on the topic.
rewrite your crontab as
0 * * * * { PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin ; export PATH ;/bin/bash -l -c 'cd /srv/foo/releases/20110429110637 && script/rails runner -e production '\''ActiveRecord::SessionStore::Session.destroy_recent(15)'\''' ; }
Or you should try to figure out why your BASH shell is not picking the PATH=... that is almost certainly in your .profile or .bash_profile.
I hope this helps.
As John Bachir pointed out, you can do it via env. But let me add more input. I am deploying on AWS Opsworks. Unfortunately they do not have a ruby manager (RVM, Rbenv, etc) installed by default.
The first thing I needed to do was SSH into the instance and figure out which ruby I was using. This was easy enough by executing the which ruby command in a terminal.
$ which ruby
/usr/local/bin/ruby
Cron was using ruby located at /usr/bin/ruby. This needed to be changed.
In schedule.rb, I have:
set :env_path, ''
env :PATH, #env_path if #env_path.present?
In local, env_path doesn't need to be set. For most users, the only thing to do is execute whenever as such:
bundle exec whenever --set 'environment=development' --update-crontab
On a staging / production environment, ruby may be installed elsewhere. So running this may be more appropriate:
bundle exec whenever --set 'environment=staging&env_path=/usr/bin/local' --update-crontab
You will need to replace /usr/bin/local with the output of echo $PATH.
In Opsworks, however, I needed to create a custom Chef recipe that looked like:
node[:deploy].each do |application, deploy|
execute 'whenever' do
user 'deploy'
group 'nginx'
cwd "#{deploy[:deploy_to]}/current"
command "bundle exec whenever --set 'environment=#{deploy[:environment_variables][:RAILS_ENV]}&env_path=#{ENV['PATH']}' --update-crontab"
end
end
I hope the information here is clear enough.

Problem deploying Ruby+RVM and daemontools

I am using daemontools in production to keep the services alive and want to run a Ruby server, not Rails, and without RVM it works well but with RVM I have some issues.
My goal is to start a process by root, make it drop root rights to get another user rights and then spawn a Ruby process with RVM and a specified Ruby version.
Here is the run script I was using until now:
#!/bin/sh
exec 2>&1
cd /app/src
. /usr/local/rvm/scripts/rvm
rvm use 1.9.1-p378
exec setuidgid app_user ruby main.rb
This script works but setuidgid has a major problem: the application will be run by user <x> and group <x> and only this group. If the user is in other groups the process will not have their rights.
So it led me to another approach:
#!/bin/sh
exec 2>&1
cd /app
exec sudo -u app_user rvm 1.9.1-p378 exec ruby main.rb
This one works fine except it is the RVM process which is spawned by daemontools and it does not react when it receives a SIGTERM which is not really nice. Basically it means the service cannot be restarted by hand, which is not good.
I found the answer but looking at the rvmsudo script installed with rvm, here is a working run script:
#!/bin/sh
# redirect stderr to stdout
exec 2>&1
cd /app
# load rvm
. /usr/local/rvm/scripts/rvm
# select ruby version for this application
rvm use 1.9.1
# # depending on your configuration you may need to provide the absolute path to rvm, like that:
# /usr/local/bin/rvm use 1.9.1
# build the exec command line preserving the rvm environment
command="exec sudo -u app_user /usr/bin/env PATH='$PATH'"
[[ -n "${GEM_HOME:-}" ]] && command="${command} GEM_HOME='$GEM_HOME' "
[[ -n "${GEM_PATH:-}" ]] && command="${command} GEM_PATH='$GEM_PATH' "
# this is where your real command line goes
command="${command} ruby main.rb"
# run the application
eval "${command}"

Resources