Skip to content

Instantly share code, notes, and snippets.

@danp
Created June 18, 2013 22:27
Show Gist options
  • Save danp/5810055 to your computer and use it in GitHub Desktop.
Save danp/5810055 to your computer and use it in GitHub Desktop.
stop on (stopping <%= @name %> or <%= @name %>.stop TYPE=$TYPE)
respawn
respawn limit 10 5
kill timeout 20
<% if !@open_file_descriptor_limit.to_s.empty? %>
limit nofile <%= @open_file_descriptor_limit %> <%= @open_file_descriptor_limit %>
<% end %>
instance $INSTANCE
script
type_instance_index="$(echo "$INSTANCE" | cut -d. -f2)"
name="<%= @name %>-$TYPE-$type_instance_index"
logger -p local0.notice -t "$name[$$]" "Starting $INSTANCE"
PORT=$(/usr/bin/run-procfile port <%= @procfile_path %> <%= @port %> $TYPE $type_instance_index)
# This little dance pipes output into logger with three
# goals in mind:
# - Keep the process as a direct child of init (so upstart
# doesn't get confused).
# - Make sure logger isn't a child of the process (so it
# doesn't get confused).
# - Don't leave cruft sitting around in the filesystem.
# See `man 7 fifo` and `man 7 pipe` for more info.
mkdir -p /var/log/<%= @name %>
stdout_fifo="/var/log/<%= @name %>/$name-stdout-log.fifo"
stderr_fifo="/var/log/<%= @name %>/$name-stderr-log.fifo"
rm -f $stdout_fifo
rm -f $stderr_fifo
mkfifo $stdout_fifo
mkfifo $stderr_fifo
# Capture our pid so we can pass it to logger to record
# the pid of the actual job and not the pid of the logger
# background process.
job_pid=$$
# Start logger reading from the fifos, in the background.
# The parens cause the logger process to be reparented to
# init, rather than remaining a child of the current proc.
#
# `setsid` will cause loggers to be in a different session
# and process group. If we let the loggers be in the same
# process group as the main process, they would be killed
# by upstart together with the main process, and all output
# would be suppressed during termination.
( exec setsid logger -p local0.notice -t "$name[$job_pid]" <$stdout_fifo & )
( exec setsid logger -p local0.err -t "$name[$job_pid]" <$stderr_fifo & )
# Redirect the current shell's output to the fifos. Now that
# we have open fds for those fifos, we don't need the file
# system entries any more...
exec >$stdout_fifo 2>$stderr_fifo
# ...so we'll remove them.
rm $stdout_fifo
rm $stderr_fifo
# Run the service in the usual way. Our output is already
# going to the fifos; that won't change when the new
# program executes.
upcase_type="$(echo "$TYPE" | tr a-z- A-Z_)"
exec sudo -u <%= @name %> PORT=$PORT PS="$INSTANCE" -i exec /usr/bin/run-procfile command <%= @procfile_path %> $TYPE
end script
task
script
name="<%= @name %>-$TYPE"
upcase_type="$(echo "$TYPE" | tr a-z- A-Z_)"
SCALE=$(su - <%= @name %> -c "echo \$${upcase_type}_SCALE")
if [ -z "$SCALE" ]; then
if [ "$TYPE" = "web" ]; then
logger -p local0.err -t "$name[$$]" "${upcase_type}_SCALE not set, defaulting to 1"
SCALE=1
else
SCALE=0
fi
fi
if [ $SCALE -eq 0 ]; then
logger -p local0.err -t "$name[$$]" "${upcase_type}_SCALE=0, not starting"
else
i=1
while [ $i -le $SCALE ]; do
start <%= @name %>-instance INSTANCE=$TYPE.$i TYPE=$TYPE
i=$(( $i + 1 ))
done
fi
end script
description "<%= @name %> processes"
stop on runlevel [!234]
stop on starting rc RUNLEVEL=[016]
pre-start exec /usr/bin/run-procfile entries <%= @procfile_path %> <%= @name %>
#!/usr/bin/env ruby
command, $procfile, *rest = ARGV
def usage
$stderr.puts "Usage:"
$stderr.puts " #{$0} entries <path to Procfile> <base name> -- start jobs for everything in Procfile"
$stderr.puts " #{$0} command <path to Procfile> <type> -- exec process of type"
$stderr.puts " #{$0} port <path to Procfile> <base port> <type> <index> -- return port number for type and index"
exit 1
end
def procfile_entry_for_type(entries, type)
unless entry = entries.detect {|e| e[:type] == type }
$stderr.puts "Procfile `#{$procfile}` doesn't have an entry for `#{type}`"
exit 1
end
entry
end
usage unless command && $procfile
unless File.readable?($procfile)
$stderr.puts "Procfile `#{$procfile}` doesn't exist or isn't readable"
exit 1
end
procfile_entries = File.read($procfile).chomp.split("\n").grep(/^\w/).map do |line|
parts = line.split(/:\s+/, 2)
{ :type => parts[0], :command => parts[1] }
end
case command
when "entries"
usage unless process_base = rest.first
procfile_entries.each do |entry|
system("start", "#{process_base}-instances", "TYPE=#{entry[:type]}")
end
when "command"
usage unless type = rest.first
procfile_entry = procfile_entry_for_type(procfile_entries, type)
$stdout.sync = true
puts "Starting process with command `#{procfile_entry[:command]}`"
Dir.chdir(File.dirname($procfile))
exec ["bash", "bash"], "--login", "-c", procfile_entry[:command]
when "port"
base_port, type, index = rest
usage unless base_port && type && index
base_port = Integer(base_port)
index = Integer(index)
procfile_entry = procfile_entry_for_type(procfile_entries, type)
port = base_port + (procfile_entries.index(procfile_entry) * 100) + (index - 1)
puts port
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment