I am trying to get an init script running for unicorn (on Ubuntu) with unicorn installed as a gem:
/home/tim/.rvm/gems/ruby-1.9.2-p180#polco/bin/unicorn
My init script is:
#! /bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn web server
# Description: starts unicorn
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/home/tim/.rvm/gems/ruby-1.9.2-p180#polco/bin/unicorn
DAEMON_OPTS="-c /home/deployer/shop/current/unicorn.rb -E production -D"
NAME=unicorn_rails
DESC=unicorn_rails
PID=/home/deployer/shop/shared/pids/unicorn.pid
case "$1" in
start)
echo -n "Starting $DESC: "
$DAEMON $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
kill -QUIT `cat $PID`
echo "$NAME."
;;
restart)
echo -n "Restarting $DESC: "
kill -QUIT `cat $PID`
sleep 1
$DAEMON $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
kill -HUP `cat $PID`
echo "$NAME."
;;
*)
echo "Usage: $NAME {start|stop|restart|reload}" >&2
exit 1
;;
esac
exit 0
The whole operation seems fragile to me with the rvm executable. Does rvm have something like $CURRENT_RVM_PATH?
O.k. i solved this for me. I stopped caring if I was root or not and decided to run this as, ironically, the user 'passenger' and I needed to run unicorn_rails.
here is my startup script:
#! /bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn web server
# Description: starts unicorn
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#DAEMON=/home/tim/.rvm/gems/ruby-1.9.2-p180#polco/bin/unicorn
DAEMON=/home/passenger/.rvm/gems/ruby-1.9.2-p180/bin/unicorn_rails
DAEMON_OPTS="-c /home/passenger/polco/current/config/unicorn_tacitus.rb -E production -D"
NAME=unicorn_rails
DESC=unicorn_rails
PID=/home/passenger/polco/shared/pids/unicorn.pid
case "$1" in
start)
echo -n "Starting $DESC: "
$DAEMON $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
kill -QUIT `cat $PID`
echo "$NAME."
;;
restart)
echo -n "Restarting $DESC: "
kill -QUIT `cat $PID`
sleep 1
$DAEMON $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
kill -HUP `cat $PID`
echo "$NAME."
;;
*)
echo "Usage: $NAME {start|stop|restart|reload}" >&2
exit 1
;;
esac
exit 0
To execute this -- I now have the simple capistrano task:
desc "restart unicorn"
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{current_path}/unicorn_exec restart"
end
after "deploy:restart","unicorn:restart"
The last question I is why I have to restart unicorn_rails. I thought I could reload via: kill -HUP cat $PID, but everything only works if I restart.
Since google might find this question for other people, here is my unicorn restart script I'm using on 3 different servers. I just need to add USR2 The repo is called eunic and i may hack on this later.
All that to say, here is another way to do it.
Related
I have a RubyOnRails 3 project and I'm using rvm. I want to switch from a sysvinit script to supervisord. The sysvinit script can only start the software in case of an error it it gets killed and restarted by $something. Mostly me.
In the project folder there is a .ruby-version and a .ruby-gemset file so that the correct ruby version and gemset gets loaded automatically. Then the app is startet with a shell script which looks like this:
#!/bin/bash
RAILS_ENV="production" rails server -d
My init script looks like this and works besides restarting and stopping:
#!/bin/sh
### BEGIN INIT INFO
# Provides: myapp
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts myapp
# Description: starts the myapp software
### END INIT INFO
USER=myuser
PATH=$PATH
DAEMON=go.sh
DAEMON_OPTS=""
NAME=myapp
DESC="myapp for $USER"
PID=/home/$USER/myapp/tmp/pids/server.pid
case "$1" in
start)
CD_TO_APP_DIR="cd /home/$USER/myapp"
START_DAEMON_PROCESS="$DAEMON $DAEMON_OPTS"
echo -n "Starting $DESC: "
if [ $(whoami) = root ]; then
su - $USER -c "$CD_TO_APP_DIR > /dev/null 2>&1 && ./$START_DAEMON_PROCESS &"
else
$CD_TO_APP_DIR > /dev/null 2>&1 && ./$START_DAEMON_PROCESS &
fi
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
kill -QUIT `cat $PID`
echo "$NAME."
;;
restart)
echo -n "Restarting $DESC: "
kill -USR2 `cat $PID`
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
kill -HUP `cat $PID`
echo "$NAME."
;;
*)
echo "Usage: $NAME {start|stop|restart|reload}" >&2
exit 1
;;
esac
exit 0
My supervisor config looks like this:
[program:myapp]
directory=/home/myuser/myapp/
command=/home/myuser/.rvm/wrappers/ruby-2.1.5#myapp/rails server -d
environment=RAILS_ENV="production"
autostart=true
autorestart=true
Problem is that there is no rails binary in the wrapper. so that the command fails. What is the correct way to do this? I'm out of ideas and would start putting some really ugly bash script together that does the job in a very wrong and bad way but does it. Btw I found rails in the gems folder.
$ ls /home/myuser/.rvm/wrappers/ruby-2.1.5#myapp/
bundle bundler erb executable-hooks-uninstaller gem irb rake rdoc ri ruby testrb
$ which rails
/home/ffwi/.rvm/gems/ruby-2.1.5#ffwi-extern/bin/rails
Try to source rvm in your script (this link describes usecases like yours).
You have to load RVM into the shell of your script manually:
source "$HOME/.rvm/scripts/rvm"
It is only enabled for interactive login shells automatically.
From this point on, you can cd into directories and rvm should do its business.
I'm trying to deploy with Ruby 2.2.2, Rails 4, Capistrano 3, Unicorn and Nginx. When I run cap production deploy I get an error sating that Unicon can't find or access a directory for the "restart" command, stemming (I believe) from this line in my deploy.rb:
execute "/etc/init.d/unicorn_#{fetch(:application)}/unicorn_init.sh/#{command}"
The error:
SSHKit::Runner::ExecuteError: Exception while executing as deploy#0.0.0.0: /etc/init.d/unicorn_app/restart exit status: 126
/etc/init.d/unicorn_app/restart stdout: Nothing written
/etc/init.d/unicorn_app/restart stderr: /usr/bin/env: /etc/init.d/unicorn_app/restart: Permission denied
Deploy.rb
set :application, 'app'
set :repo_url, 'https://github.com/user/app.git'
set :deploy_to, '/opt/www/app'
set :user, 'deploy'
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets}
set :ssh_options, {
forward_agent: true,
port: 7822
}
namespace :deploy do
%w[start stop restart].each do |command|
desc 'Manage Unicorn'
task command do
on roles(:app), in: :sequence, wait: 1 do
execute "/etc/init.d/unicorn_#{fetch(:application)}/unicorn_init.sh/#{command}"
end
end
end
after :publishing, :restart
end
set :rvm_ruby_version, '2.2.2'
set :default_env, { rvm_bin_path: '/usr/local/rvm/bin' }
SSHKit.config.command_map[:rake] = "#{fetch(:default_env)[:rvm_bin_path]}/rvm ruby-#{fetch(:rvm_ruby_version)} do bundle exec rake"
Can anyone help me out here? I'll gladly post any missing info.
EDIT: unicorn_init.sh: I know 'testapp' is referenced in this file, but app is referenced elsewhere in this post. Please know that i'm consistent across all files with the name, I just changed them for the post.
#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Manage unicorn server
# Description: Start, stop, restart unicorn server for a specific application.
### END INIT INFO
set -e
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/opt/www/testapp/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
AS_USER=deploy
set -u
OLD_PIN="$PID.oldbin"
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
}
run () {
if [ "$(id -un)" = "$AS_USER" ]; then
eval $1
else
su -c "$1" - $AS_USER
fi
}
case "$1" in
start)
sig 0 && echo >&2 "Already running" && exit 0
run "$CMD"
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
run "$CMD"
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $OLD_PIN && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $OLD_PIN
then
echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
run "$CMD"
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 "
exit 1
;;
esac
I am trying to setup Unicorn in Amazon EC2. I am following this blog.
But when I start Unicorn using:
sudo service unicorn_firstapp start
I am getting the following error:
/home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 2: syntax error near unexpected token `('
/home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 2: `app_dir = File.expand_path("../..", __FILE__)'
What is my mistake? If any one has any idea about this issue, please share it with me.
unicorn.rb:
# 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 true
timeout 30
# 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"
/etc/init.d/unicorn_firstapp:
#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn app server
# Description: starts unicorn using start-stop-daemon
### END INIT INFO
set -e
USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"
# app settings
USER="ec2-user"
APP_NAME="firstapp"
APP_ROOT="/home/$USER/rails_projects/$APP_NAME"
ENV="production"
# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"
#setting for RVM
RAILS_ENV=production
PID=$APP_ROOT/shared/pids/unicorn.pid
DESC="Unicorn app - $RAILS_ENV"
UNICORN="$APP_ROOT/config/unicorn.rb"
UNICORN_OPTS="-c $APP_ROOT/config/unicorn.rb -E $RAILS_ENV -D"
CMD="RAILS_ENV=$RAILS_ENV $UNICORN $UNICORN_OPTS"
TIMEOUT=60
# make sure the app exists
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}
case $1 in
start)
sig 0 && echo >&2 "Already running" && exit 0
echo "Starting $APP_NAME"
su - $USER -c "$CMD"
;;
stop)
echo "Stopping $APP_NAME"
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
echo "Force stopping $APP_NAME"
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload|upgrade)
sig USR2 && echo "reloaded $APP_NAME" && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
$CMD
;;
rotate)
sig USR1 && echo rotated logs OK && exit 0
echo >&2 "Couldn't rotate logs" && exit 1
;;
*)
echo >&2 $USAGE
exit 1
;;
esac
Try including the correct hash-bang header, otherwise your code will be executed using your shell:
#!/usr/bin/env ruby
app_dir = File.expand_path("../..", __FILE__)
...
Hope that helps.
How do I set up unicorn shell file to use ruby-2.1.2#my_gemset so that it can run as sudo service unicorn start. My Rails Application config folder contain unicorn.sh file which has the following content.
#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Manage unicorn server
# Description: Start, stop, restart unicorn server for a specific application.
### END INIT INFO
set -e
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-90}
APP_ROOT=/home/user/Documents/workspace/MyApp
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT;bundle exec bin/unicorn -c $APP_ROOT/config/unicorn.rb -E development"
AS_USER="www-data"
action="$1"
set -u
OLD_BIN="$PID.oldbin"
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_BIN && kill -$1 `cat $OLD_BIN`
}
run () {
if [ "$(id -un)" = "$AS_USER" ]; then
eval $1
else
su -c "$1" - $AS_USER
fi
}
case "$1" in
start)
sig 0 && echo >&2 "Already running" && exit 0
run "$CMD"
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
run "$CMD"
;;
upgrade)
if sig USR2 && sleep 3
then
n=$TIMEOUT
while test -s $OLD_BIN && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $OLD_BIN
then
echo >&2 "$OLD_BIN still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
run "$CMD"
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
exit 1
;;
esac
but when i run sudo service unicorn start I got this error
/var/lib/gems/1.8/gems/bundler-1.5.3/lib/bundler/runtime.rb:220: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777
Could not find rake-10.4.2 in any of the sources
Run `bundle install` to install missing gems.
But actually i am using ruby-2.1.2#my_gemset. How do I tell shell script to use this gemset using rvm.
My bin/unicorn file has this content
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'unicorn' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require 'rubygems'
require 'bundler/setup'
load Gem.bin_path('unicorn', 'unicorn')
I know i have to change the path of /usr/bin/env ruby to my ruby but don't know how to do this. Also please let me know how can I set up unicorn shell script to use specific gemset with specific ruby.Thanks
I'm using rvm in my remote server to manage my gems. I've committed the .ruby-gemset, and .ruby-version so that it's uniform. In my deployment script, I added the snippet below to make sure I'm running the command in the right folder with the correct set of gems. So execute:
source ~/.rvm/scripts/rvm; cd #{current_path}; /etc/init.d/unicorn #{command}"
I'm pretty sure this can be refactored further but I haven't gotten around to updating my script for a while. But so far, it's been working. I'm using Capistrano 3.
I haven't done this before but i think this will work -
Add this line -
CMD_TO_USE_GEMSET="cd $APP_ROOT; rvm use ruby-2.1.2#my_gemset"
after
CMD="cd $APP_ROOT;bundle exec bin/unicorn -c $APP_ROOT/config/unicorn.rb -E development"
in your unicorn.sh.
And write this in "start" and "restart|reload" section of your unicorn.sh after run "$CMD" -
run "$CMD_TO_USE_GEMSET"
and now run the command to restart unicorn -
sudo service unicorn start
have to do passenger stop then start
or I can still do this by touching tmp/restart.txt?
Yes you can restart it by touching tmp/restart.txt.
create a script in /etc/init.d:
$ sudo nano /etc/init.d/YOUR_SERVICE_NAME
Then, Change the parameters according your needs.
#!/bin/sh
### BEGIN INIT INFO
# Provides: <NAME>
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: <DESCRIPTION>
### END INIT INFO
start() {
echo 'Starting serviceā¦' >&2
/bin/bash -l -c 'cd /var/www/myapp/current && passenger start --daemonize -e [staging | production | development ] --ruby path/to/your/bin/ruby'
echo 'Service started' >&2
}
stop() {
echo 'Stopping serviceā¦' >&2
passenger stop /var/www/myapp/current
echo 'Service stopped' >&2
}
status() {
passenger status /var/www/myapp/current
}
case "$1" in
start)
start
exit 0
;;
stop)
stop
exit 0
;;
status)
status
exit 0
;;
restart)
stop
start
exit 0
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
esac
Make this file executable:
$ sudo chmod +x /etc/init.d/YOUR_SERVICE_NAME
Then test it:
/etc/init.d/YOUR_SERVICE_NAME start
You can set the to reboot with the system:
$ sudo update-rc.d YOUR_SERVICE_NAME defaults