Skip to content

Instantly share code, notes, and snippets.

@penguinwokrs
Forked from niwo/puma
Last active June 19, 2017 07:27
Show Gist options
  • Save penguinwokrs/1a671cf920e6c0d72d8e4e8fabbb65ad to your computer and use it in GitHub Desktop.
Save penguinwokrs/1a671cf920e6c0d72d8e4e8fabbb65ad to your computer and use it in GitHub Desktop.
puma with rbenv on CentOS 6
#!/bin/sh
#
# puma - this script starts and stops the puma daemon
#
# chkconfig: - 85 15
# description: Description \
# goes here...
# processname: puma
# config: /etc/puma.conf
# pidfile: /home/stanislaw/apps/micro-apps/puma/puma.pid
# Author: Darío Javier Cravero <[email protected]>
#
# Do NOT "set -e"
# Original script https://github.com/puma/puma/blob/master/tools/jungle/puma
# It was modified here by Stanislaw Pankevich <[email protected]>
# to run on CentOS 5.5 boxes.
# Script works perfectly on CentOS 5: script uses its native daemon().
# Puma is being stopped/restarted by sending signals, control app is not used.
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/local/bin:/usr/local/sbin/:/sbin:/usr/sbin:/bin:/usr/bin
DESC="Puma rack web server"
NAME=puma
DAEMON=$NAME
SCRIPTNAME=/etc/init.d/$NAME
CONFIG=/etc/puma.conf
JUNGLE=`cat $CONFIG`
RUNPUMA=/usr/local/bin/run-puma
# Skipping the following non-CentOS string
# Load the VERBOSE setting and other rcS variables
# . /lib/init/vars.sh
# CentOS does not have these functions natively
log_daemon_msg() { echo "$@"; }
log_end_msg() { [ $1 -eq 0 ] && RES=OK; logger ${RES:=FAIL}; }
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
# Function that performs a clean up of puma.* files
#
cleanup() {
echo "Cleaning up puma temporary files..."
echo $1;
PIDFILE=$1/tmp/puma/puma.pid
STATEFILE=$1/tmp/puma/puma.state
SOCKFILE=$1/tmp/puma/puma.sock
rm -f $PIDFILE $STATEFILE $SOCKFILE
}
#
# Function that starts the jungle
#
do_start() {
log_daemon_msg "=> Running the jungle..."
for i in $JUNGLE; do
dir=`echo $i | cut -d , -f 1`
user=`echo $i | cut -d , -f 2`
config_file=`echo $i | cut -d , -f 3`
if [ "$config_file" = "" ]; then
config_file="$dir/puma/config.rb"
fi
log_file=`echo $i | cut -d , -f 4`
if [ "$log_file" = "" ]; then
log_file="$dir/puma/puma.log"
fi
do_start_one $dir $user $config_file $log_file
done
}
do_start_one() {
PIDFILE=$1/puma/puma.pid
if [ -e $PIDFILE ]; then
PID=`cat $PIDFILE`
# If the puma isn't running, run it, otherwise restart it.
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
do_start_one_do $1 $2 $3 $4
else
do_restart_one $1
fi
else
do_start_one_do $1 $2 $3 $4
fi
}
do_start_one_do() {
log_daemon_msg "--> Woke up puma $1"
log_daemon_msg "user $2"
log_daemon_msg "log to $4"
cleanup $1;
daemon --user $2 $RUNPUMA $1 $3 $4
}
#
# Function that stops the jungle
#
do_stop() {
log_daemon_msg "=> Putting all the beasts to bed..."
for i in $JUNGLE; do
dir=`echo $i | cut -d , -f 1`
do_stop_one $dir
done
}
#
# Function that stops the daemon/service
#
do_stop_one() {
log_daemon_msg "--> Stopping $1"
PIDFILE=$1/tmp/puma/puma.pid
STATEFILE=$1/tmp/puma/puma.state
echo $PIDFILE
if [ -e $PIDFILE ]; then
PID=`cat $PIDFILE`
echo "Pid:"
echo $PID
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
log_daemon_msg "---> Puma $1 isn't running."
else
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
# pumactl --state $STATEFILE stop
# Many daemons don't delete their pidfiles when they exit.
kill -9 $PID
fi
cleanup $1
else
log_daemon_msg "---> No puma here..."
fi
return 0
}
#
# Function that restarts the jungle
#
do_restart() {
for i in $JUNGLE; do
dir=`echo $i | cut -d , -f 1`
do_restart_one $dir
done
}
#
# Function that sends a SIGUSR2 to the daemon/service
#
do_restart_one() {
PIDFILE=$1/tmp/puma/puma.pid
i=`grep $1 $CONFIG`
dir=`echo $i | cut -d , -f 1`
if [ -e $PIDFILE ]; then
log_daemon_msg "--> About to restart puma $1"
# pumactl --state $dir/tmp/puma/state restart
kill -s USR2 `cat $PIDFILE`
# TODO Check if process exist
else
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
user=`echo $i | cut -d , -f 2`
config_file=`echo $i | cut -d , -f 3`
if [ "$config_file" = "" ]; then
config_file="$dir/config/puma.rb"
fi
log_file=`echo $i | cut -d , -f 4`
if [ "$log_file" = "" ]; then
log_file="$dir/log/puma.log"
fi
do_start_one $dir $user $config_file $log_file
fi
return 0
}
#
# Function that statuss then jungle
#
do_status() {
for i in $JUNGLE; do
dir=`echo $i | cut -d , -f 1`
do_status_one $dir
done
}
#
# Function that sends a SIGUSR2 to the daemon/service
#
do_status_one() {
PIDFILE=$1/tmp/puma/puma.pid
i=`grep $1 $CONFIG`
dir=`echo $i | cut -d , -f 1`
if [ -e $PIDFILE ]; then
log_daemon_msg "--> About to status puma $1"
# pumactl --state $dir/tmp/puma/state stats
# kill -s USR2 `cat $PIDFILE`
# TODO Check if process exist
else
log_daemon_msg "--> $1 isn't there :(..."
fi
return 0
}
do_add() {
str=""
# App's directory
if [ -d "$1" ]; then
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
str=$1
else
echo "The app is already being managed. Remove it if you want to update its config."
exit 1
fi
else
echo "The directory $1 doesn't exist."
exit 1
fi
# User to run it as
if [ "`grep -c "^$2:" /etc/passwd`" -eq 0 ]; then
echo "The user $2 doesn't exist."
exit 1
else
str="$str,$2"
fi
# Config file
if [ "$3" != "" ]; then
if [ -e $3 ]; then
str="$str,$3"
else
echo "The config file $3 doesn't exist."
exit 1
fi
fi
# Log file
if [ "$4" != "" ]; then
str="$str,$4"
fi
# Add it to the jungle
echo $str >> $CONFIG
log_daemon_msg "Added a Puma to the jungle: $str. You still have to start it though."
}
do_remove() {
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
echo "There's no app $1 to remove."
else
# Stop it first.
do_stop_one $1
# Remove it from the config.
sed -i "\\:^$1:d" $CONFIG
log_daemon_msg "Removed a Puma from the jungle: $1."
fi
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
if [ "$#" -eq 1 ]; then
do_start
else
i=`grep $2 $CONFIG`
dir=`echo $i | cut -d , -f 1`
user=`echo $i | cut -d , -f 2`
config_file=`echo $i | cut -d , -f 3`
if [ "$config_file" = "" ]; then
config_file="$dir/config/puma.rb"
fi
log_file=`echo $i | cut -d , -f 4`
if [ "$log_file" = "" ]; then
log_file="$dir/log/puma.log"
fi
do_start_one $dir $user $config_file $log_file
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
if [ "$#" -eq 1 ]; then
do_stop
else
i=`grep $2 $CONFIG`
dir=`echo $i | cut -d , -f 1`
do_stop_one $dir
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
# TODO Implement.
log_daemon_msg "Status $DESC" "$NAME"
if [ "$#" -eq 1 ]; then
do_status
else
i=`grep $2 $CONFIG`
dir=`echo $i | cut -d , -f 1`
do_status_one $dir
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
restart)
log_daemon_msg "Restarting $DESC" "$NAME"
if [ "$#" -eq 1 ]; then
do_restart
else
i=`grep $2 $CONFIG`
dir=`echo $i | cut -d , -f 1`
do_restart_one $dir
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
add)
if [ "$#" -lt 3 ]; then
echo "Please, specifiy the app's directory and the user that will run it at least."
echo " Usage: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
echo " config and log are optionals."
exit 1
else
do_add $2 $3 $4 $5
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
remove)
if [ "$#" -lt 2 ]; then
echo "Please, specifiy the app's directory to remove."
exit 1
else
do_remove $2
fi
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
*)
echo "Usage:" >&2
echo " Run the jungle: $SCRIPTNAME {start|stop|status|restart}" >&2
echo " Add a Puma: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
echo " config and log are optionals."
echo " Remove a Puma: $SCRIPTNAME remove /path/to/app"
echo " On a Puma: $SCRIPTNAME {start|stop|status|restart} PUMA-NAME" >&2
exit 3
;;
esac
:
# Puma can serve each request in a thread from an internal thread pool.
# The method setting takes two numbers a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum, this matches the default thread size of Active Record.
#
proj_path = File.expand_path('../../', __FILE__).to_s
sock_file = "#{proj_path}/tmp/puma/puma.sock"
pidfile "#{proj_path}/tmp/puma/puma.pid"
state_path "#{proj_path}/tmp/puma/puma.state"
daemonize
bind "unix://#{sock_file}"
directory proj_path
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
# Specifies the that Puma will listen on to receive requests, default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max * .
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the method when specifying a number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the
# block.
#
# preload_app!
# The code in the will be called if you are using
# clustered mode by specifying a number of . After each worker
# process is booted this block will be run, if you are using
# option you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
# Sentry
# in your puma.rb config
lowlevel_error_handler do |ex, env|
Raven.capture_exception(
ex,
message: ex.message,
extra: { puma: env },
culprit: "Puma"
)
# note the below is just a Rack response
# [500, {}, ["An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact [email protected]\n"]]
end
# Allow puma to be restarted by command.
plugin :tmp_restart
#!/bin/bash
app=$1; config=$2; log=$3;
# We are using local rbenv ruby environment. We need to load it:
RBENV_DIR="/usr/local/rbenv"
if [ -d "$RBENV_DIR" ]; then
export RBENV_ROOT="$RBENV_DIR"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
else
echo "error: rbenv directory does not exist: $RBENV_DIR" && exit 1
fi
NDENV_DIR="/usr/local/anyenv/envs/ndenv"
if [ -d "$NDENV_DIR" ]; then
export NDENV_ROOT="$NDENV_DIR"
export PATH="$NDENV_ROOT/bin:$PATH"
eval "$(ndenv init -)"
else
echo "error: ndenv directory does not exist: $NDENV_DIR" && exit 1
fi
ENV_FILE="/etc/environment"
if [ -r "$ENV_FILE" ]; then
source "$ENV_FILE"
fi
cd $app && exec bundle exec puma -C $config 2>&1 >> $log &
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment