I want to use god to monitor my redis server. The problem is that they are in different locations locally and on my server. I tried doing something like this but this causes god to fail.
%w{6379}.each do |port|
God.watch do |w|
w.name = "redis"
w.interval = 30.seconds
if RAILS_ENV == 'development'
w.start = "/usr/local/bin/redis-server /usr/local/bin"
w.stop = "/usr/local/bin/redis-cli -p 6379 shutdown"
else # in production
w.start = "/usr/local/etc/redis-server /usr/local/etc"
w.stop = "/usr/local/etc/redis-cli -p 6379 shutdown"
end
end
end
Use
if ENV["RAILS_ENV"] == 'development'
And then call your script using
RAILS_ENV=development sudo god ...
in your dev environment.
and in production:
sudo god ...
Related
I have a sinatra app that works great when i start it from the project directory using bundle exec unicorn -c config/unicorn.rb -D. However when i use god to start it, I get error stating unicorn is not part of the bundle. Add it to Gemfile. (Gem::LoadError). I do have unicorn in my gemfile. I have been struggling with it for some time now, without much help. Any clues?
The exact error I get is
/Users/pranav/.rvm/gems/ruby-2.1.5#global/gems/bundler-1.11.2/lib/bundler/rubygems_integration.rb:304:in `block in replace_gem': unicorn is not part of the bundle. Add it to Gemfile. (Gem::LoadError)
from /Users/pranav/.rvm/gems/ruby-2.1.5/bin/unicorn:22:in `<main>'
from /Users/pranav/.rvm/gems/ruby-2.1.5/bin/ruby_executable_hooks:15:in `eval'
from /Users/pranav/.rvm/gems/ruby-2.1.5/bin/ruby_executable_hooks:15:in `<main>'
Here is the god config I use
proj_dir = ENV['DIR_API_HANDLER']
script_name = 'api_handler'
pid_file = File.join(proj_dir, 'shared', 'pids', 'unicorn.pid')
log_file = File.join(proj_dir, 'shared', 'log', 'unicorn.stderr.log')
God.watch do |w|
w.name = script_name
w.group = 'apihandler'
w.log = log_file
w.dir = proj_dir
w.env = ENV
w.start = "cd #{ proj_dir } && bundle exec unicorn -c config/unicorn.rb -D"
# QUIT gracefully shuts down workers
w.stop = "cd #{ proj_dir} && kill -QUIT `cat #{ pid_file }`"
# USR2 causes the master to re-create itself and spawn a new worker pool
w.restart = "kill -USR2 `cat #{ pid_file }`"
w.start_grace = 10.seconds
w.restart_grace = 15.seconds
w.interval = 30.minutes
w.pid_file = pid_file
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
end
end
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 300.megabytes
c.times = [3, 5] # 3 out of 5 intervals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
# lifecycle
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 10.minutes
c.retry_times = 5
c.retry_within = 2.hours
end
end
end
My Gemfile looks like
source 'https://rubygems.org'
ruby '2.1.5'
gem 'sinatra'
gem 'sinatra-contrib'
gem 'json'
gem 'unicorn', '~>5.1.0'
gem 'ruby-kafka', '~>0.3.2'
gem 'dotenv'
gem 'curb'
The config/unicorn.rb looks like below
# set path to application
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
working_directory app_dir
# Set unicorn options
worker_processes 2
preload_app false
timeout 30
listen 9001
# Set up socket location
#listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64
# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"
# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"
The log from god -c config.god -D is below
I [2016-04-22 18:42:37] INFO: Loading octo.god
I [2016-04-22 18:42:37] INFO: Syslog enabled.
I [2016-04-22 18:42:37] INFO: Using pid file directory: /Users/pranav/.god/pids
I [2016-04-22 18:42:37] INFO: Started on drbunix:///tmp/god.17165.sock
I [2016-04-22 18:42:37] INFO: api_handler move 'unmonitored' to 'up'
I [2016-04-22 18:42:37] INFO: api_handler moved 'unmonitored' to 'up'
I [2016-04-22 18:42:37] INFO: api_handler [trigger] process is not running (ProcessRunning)
I [2016-04-22 18:42:37] INFO: api_handler move 'up' to 'start'
I [2016-04-22 18:42:37] INFO: api_handler before_start: no pid file to delete (CleanPidFile)
I [2016-04-22 18:42:37] INFO: api_handler start: cd /Users/pranav/workspace/apihandler && bundle exec unicorn -c config/unicorn.rb -D
W [2016-04-22 18:42:38] WARN: api_handler start command exited with non-zero code = 1
It looks like God is using default location for PID file, while the location is explicitly specified. Could it be because of this?
ok
I don't know how to change rvm version over ssh under os x server.
What I do:
Login on server over ssh
run script (below) and catch error
Error: 'rvm is not a funciton, many-many-words'
What I have as script:
use File::Spec;
my $server_directory = File::Spec->catfile($ENV{HOME},'MyProject');
my $exec_file = File::Spec->catfile($server_directory,'run_script.rb');
my $run_ruby_script = qq'bundle exec ruby $exec_file'.' '.join(' ',#ARGV);
# reload bash profile
print qx(source $ENV{HOME}/.bash_profile);
print qx(source $ENV{HOME}/.bashrc);
# reload ruby
print qx(source $ENV{HOME}/.rvm/scripts/rvm);
my $ruby_setup = qq([[ -s "$ENV{HOME}/.rvm/scripts/rvm" ]] && source "$ENV{HOME}/.rvm/scripts/rvm");
print $ruby_setup. "\n";
# change directory
chdir($server_directory);
# configure gemset name
my $version = qx(cat .ruby-version);
chomp($version);
my $gemset = qx(cat .ruby-gemset);
chomp($gemset);
my $change_rvm_gemset = qq(rvm use $version\#$gemset);
print qx($ruby_setup && $change_rvm_gemset);
print qx(rvm current);
Ok, after all.
def exec_via_bash(line)
puts %Q(#{line})
exec = 'bash -c "#{line}"'
puts `#{exec}`
end
def RubySetup
# reload bash profile
homedir = ENV['HOME']
exec_via_bash %Q(source #{homedir}/.bash_profile);
exec_via_bash %Q(source #{homedir}/.bashrc);
# reload ruby
exec_via_bash %Q(source #{homedir}/.rvm/scripts/rvm);
ruby_setup = %Q([[ -s "#{homedir}/.rvm/scripts/rvm" ]] && source "#{homedir}/.rvm/scripts/rvm")
puts ruby_setup
ruby_setup
end
if ARGV.empty?
puts "there is not enough arguments passed. maybe you forget ruby file to exec?"
exit(1)
end
ruby_script_path = ARGV.shift;
exec_file_absolute_path = File.expand_path(ruby_script_path)
unless File.exists? exec_file_absolute_path
puts "file #{exec_file_absolute_path} doesn't exists!"
exit(1)
end
exec_file_directory = File.dirname(exec_file_absolute_path)
exec_bundle = %Q'bundle exec ruby #{exec_file_absolute_path}' + ' ' + ARGV.join(' ')
# change directory
Dir.chdir(exec_file_directory);
# print %x(ls);
# configure gemset name
version = %x(cat .ruby-version).strip;
gemset = %x(cat .ruby-gemset).strip;
change_rvm_gemset = %Q(rvm use #{version}\##{gemset});
ruby_setup = RubySetup()
exec_bash_login_line = [ruby_setup, change_rvm_gemset, exec_bundle].join ' && ';
puts 'exec bash login line: ' + exec_bash_login_line
forced = %Q(bash --login -c '#{exec_bash_login_line}');
puts forced, "\n";
puts %x(#{forced});
ok, this script is not a kind of beauty, but it works well.
Example of usage?
ruby script.rb ~/bla/bla/bla/run_your_program.rb --first_argument --second_argument a,b,c --etc
As I said before:
I've already on the server via ssh.
So, I need to run scripts via launchd.
And I should do it with
# part of launchd worker
<string>bash</string>
<string>-c</string>
<string>ruby ~/PathToCharmScript.rb -r a</string>
P.S:
Please, help me with improvements of this script for others!
Here is a gist: wow_this_works
I have two apps on my machine.
Each app (server) has it's own gemset and works on a different ruby version.
I will manage those apps with god which is installed in it's own gemset.
My god config file config.god looks like this:
God.watch do |w|
current_path = "/home/vagrant/server-1"
w.name = "server 1"
w.start = "ruby #{current_path}/simple-server.rb"
w.keepalive
end
God.watch do |w|
current_path = "/home/vagrant/server-2"
w.name = "server 2"
w.start = "ruby #{current_path}/simple-server.rb"
w.keepalive
end
My servers are simply writing the ruby version to a file (/home/vagrant/server-2/simple-server.rb):
require "date"
loop do
# simple console output
puts "Hello on #{RUBY_VERSION}, #{RUBY_PATCHLEVEL}, #{RUBY_PLATFORM}, #{RUBY_RELEASE_DATE}"
# Specify the name of the log file
log_file = File.join File.expand_path( File.dirname(__FILE__) ), "testfile.txt"
# Write the log into the file
File.open( log_file, 'a') do |f|
date = DateTime.now
date = date.strftime("%H:%M:%S")
f.puts "#{date} on #{RUBY_VERSION}, #{RUBY_PATCHLEVEL}, #{RUBY_PLATFORM}, #{RUBY_RELEASE_DATE}"
end
sleep 2
end
I run god with god -c config.god.
The problem is that my apps are not running with the ruby versions which is specified in the .rvmrc.
I have also tried:
~/.rvm/bin/wrapped_god -d config.god -D
rvmsudo ~/.rvm/bin/wrapped_god -d config.god -D
rvmsudo god -d config.god -D
Is there a solution for this case?
EDIT 2012.08.27:
I have changed my god config as follows:
w.start="~/.rvm/bin/rvm in #{current_path} do ruby simple-server.rb"
And it worked.
try:
start="~/.rvm/bin/rvm in #{current_path} do ruby simple-server.rb"
I have this file
rails_env = ENV['RAILS_ENV'] || 'development'
rails_root = ENV['RAILS_ROOT'] || "/home/luiz/rails_dev/api"
God.watch do |w|
w.name = "unicorn"
w.interval = 30.seconds # default
# unicorn needs to be run from the rails root
w.start = "cd #{rails_root} && unicorn_rails -c config/unicorn.rb -E #{rails_env}"
# QUIT gracefully shuts down workers
w.stop = "kill -QUIT `cat #{rails_root}/tmp/pids/unicorn.pid`"
# USR2 causes the master to re-create itself and spawn a new worker pool
w.restart = "kill -USR2 `cat #{rails_root}/tmp/pids/unicorn.pid`"
w.start_grace = 10.seconds
w.restart_grace = 10.seconds
w.pid_file = "#{rails_root}/tmp/pids/unicorn.pid"
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
end
end
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 300.megabytes
c.times = [3, 5] # 3 out of 5 intervals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
# lifecycle
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 10.minutes
c.retry_times = 5
c.retry_within = 2.hours
end
end
end
I start unicorn with god -c unicorn.god -D -p 8081 and my workers are setup fine. but, sometimes I need do stop unicorn (god stop unicorn -p 8081 in another console) but the server keep up and running.
what am I missing?
Edit
We're moving from unicorn to puma (not because this question, it's a performance thing), and not going to use god anymore...thanks everybody for your help
Now we are using foreman and puma right now...this is our initializer:
web: bundle exec puma -q -d -e production -b 'unix:///home/api/shared/web.socket' -S /home/api/shared/web.state --control 'unix:///home/api/shared/web.ctl'
and deploying with capistrano, so that we can stop and restart the server like this
config/deploy.rb
# Puma commands
_cset(:puma_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec puma" }
_cset(:pumactl_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec pumactl" }
_cset(:puma_state) { "#{shared_path}/puma.state" }
_cset(:puma_role) { :app }
# Puma
namespace :puma do
desc 'Start puma'
task :start do
run "cd #{current_path} ; bundle exec foreman start web"
end
desc 'Stop puma'
task :stop, :roles => lambda { fetch(:puma_role) }, :on_no_matching_servers => :continue do
run "cd #{current_path} && #{fetch(:pumactl_cmd)} -S #{fetch(:puma_state)} stop"
end
desc 'Restart puma'
task :restart, :roles => lambda { fetch(:puma_role) }, :on_no_matching_servers => :continue do
run "cd #{current_path} && #{fetch(:pumactl_cmd)} -S #{fetch(:puma_state)} restart"
end
end
I am looking to execute a password change over Net-ssh and this code seems to hang:
Net::SSH.start(server_ip, "user", :verbose => :debug ) do |session|
session.process.popen3("ls") do |input, output, error|
["old_pass","test", "test"].each do |x|
input.puts x
end
end
end
I know the connection works because using a simple exec I can get the output from ls on the remote server, but this hangs.
Any ideas?
The last message from debug is that the public key succeeded.
This one will solve your issue ,, note this script to change password for a list of servers list in file
#~~~~~~~~~~~~~~~~~~~~~~~
# Change Password is a simple script to change the password for a list of servers
# Coded by : Sabry Saleh
# License : GPL2
#~~~~~~~~~~~~~~~~~~~~~~~
#=-Notes-=
# You have to install ruby + net-ssh gems
# sudo gem install net-ssh
#~~~~~~~~~~~~~~~~~~~~~~~
require 'net/ssh'
host = IO.readlines('test1.txt') # full path of servers' list
port = 22 # SSH port
user = 'username' # username
i = 0
while i < host.length
Net::SSH.start(host[i], user , :password => "User pass" , :port=> port) do |ssh|
ssh.open_channel do |channel|
channel.on_request "exit-status" do |channel, data|
$exit_status = data.read_long
end
channel.request_pty do |channel, success|
channel.exec("sudo passwd UserName") # Logged user shuold be root or sudoers memeber
if success
channel.on_data do |channel, data|
puts data.inspect.chomp("\r\n")
channel.send_data("New pass\n") # put the New password you need to set
sleep 0.1
end
else
puts "FAILED!!"
end
end
channel.wait
puts "SUCCESS!!" if $exit_status == 0
end
end
i += 1
end