Skip to content

Instantly share code, notes, and snippets.

@damncabbage
Last active September 16, 2016 23:53
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damncabbage/8aac0b375bdd6d1c702c to your computer and use it in GitHub Desktop.
Save damncabbage/8aac0b375bdd6d1c702c to your computer and use it in GitHub Desktop.
I have the most terrible Upstart config for Unicorn. Support start, stop, restart and reload (rolling restart).
# /etc/init/unicorn.conf
description "App: Unicorn"
start on (net-device-up
and local-filesystems
and runlevel [2345])
stop on runlevel ![2345]
# Respawning is disabled. It will never work. It will never be able to track
# Unicorn like you think it should. Stop trying.
#respawn
chdir /path/to/app
reload signal USR2
env RAILS_ENV="production"
env UNICORN_PID_PATH="/path/to/app/pids/unicorn.pid"
# Run this as a user other than root.
setuid app
setgid app
# This block does nothing except start Unicorn, leave it alone, and then
# catch signals sent by Upstart when "service <app> reload" is run.
#
# We can't sensibly track Unicorn in here at all; after it's initially daemonized, the best thing
# you can do is use an external monitoring tool to test if it's still alive; any other
# approach is race-condition pid-file mangling horror that you don't want to burn a week on like I have.
#
# Required reading for Bash's "trap" and "wait":
# http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html#sect_12_02_02
script
# Trap any USR2 (reload) signals sent to this script (a bash process in its
# own right), and pass them on to Unicorn.
trap 'kill -USR2 $(cat "$UNICORN_PID_PATH")' USR2
# Kick off Unicorn; we will not try to keep track of it beyond this point.
bundle exec unicorn -c /etc/unicorn.conf.rb -E "$RAILS_ENV" --daemonize
# Now wait until this process receives a signal.
# NOTE: This entire bash script is killed outright by a "service <app> stop",
# which will break the loop.
while true; do
# Sleep forever. The backgrounding (&) + wait is so that "trap" can
# interrupt at any time. A plain "sleep infinity" wouldn't allow this.
sleep infinity & BLOCKING_PID=$!
# When interrupted by a trap, wait dies with exit code 128; ignore this, keep going.
wait "$BLOCKING_PID" || true
done
end script
post-stop script
exec kill $(cat "${UNICORN_PID_PATH}") || true # YOLO
end script
# /etc/init/unicorn.conf
description "App: Unicorn"
start on (net-device-up
and local-filesystems
and runlevel [2345])
stop on runlevel ![2345]
# Respawning is disabled. It will never work. It will never be able to track
# Unicorn like you think it should. Stop trying.
#respawn
chdir /path/to/app
reload signal USR2
env RAILS_ENV="production"
env UNICORN_PID_PATH="/path/to/app/pids/unicorn.pid"
env CGROUPS="cpu memory"
env CGROUP_NAME="myapp"
# Run this as a user other than root.
setuid myapp
setgid myapp
# This block does nothing except start Unicorn, leave it alone, and then
# catch signals sent by Upstart when "service <app> reload" is run.
#
# We can't sensibly track Unicorn in here at all; after it's initially daemonized, the best thing
# you can do is use an external monitoring tool to test if it's still alive; any other
# approach is race-condition pid-file mangling horror that you don't want to burn a week on like I have.
#
# Required reading for Bash's "trap" and "wait":
# http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html#sect_12_02_02
script
# Trap any USR2 (reload) signals sent to this script (a bash process in its
# own right), and pass them on to Unicorn.
trap 'kill -USR2 $(cat "$UNICORN_PID_PATH")' USR2
# Kick off Unicorn; we will not try to keep track of it beyond this point.
# We capture the /initial/ PID it's using, but that'll be gone after the first time
# anyone runs "service <app> reload".
bundle exec unicorn -c /etc/unicorn.conf.rb -E "$RAILS_ENV" & STARTING_UNICORN_PID=$!
# Put Unicorn into a cgroup box.
for CGROUP in $CGROUPS; do
echo $STARTING_UNICORN_PID > "/sys/fs/cgroup/${CGROUP}/${CGROUP_NAME}/tasks"
done
# Now wait until this process receives a signal.
# NOTE: This entire bash script is killed outright by a "service <app> stop",
# which will break the loop.
while true; do
# Sleep forever. The backgrounding (&) + wait is so that "trap" can
# interrupt at any time. A plain "sleep infinity" wouldn't allow this.
sleep infinity & BLOCKING_PID=$!
# When interrupted by a trap, wait dies with exit code 128; ignore this, keep going.
wait "$BLOCKING_PID" || true
done
end script
post-stop script
# Throw away the aforementioned cgroup box.
for CGROUP in $CGROUPS ; do
for TASK in $(cat "/sys/fs/cgroup/${CGROUP}/${CGROUP_NAME}/tasks") ; do
kill "$TASK" || true
done
done
end script
#!/bin/bash -e
# A shitty script to set up cgroups for mucking around with.
CGROUPS="cpu memory"
CGROUP_NAME="myapp"
OWNER="myapp"
mount -t tmpfs cgroup_root /sys/fs/cgroup
for CGROUP in $CGROUPS; do
mkdir "/sys/fs/cgroup/${CGROUP}"
mount -t cgroup -o${CGROUP} "$CGROUP" "/sys/fs/cgroup/$CGROUP"
mkdir /sys/fs/cgroup/${CGROUP}/${CGROUP_NAME}
chown "${OWNER}:${OWNER}" "/sys/fs/cgroup/${CGROUP}/${CGROUP_NAME}"
done
@damncabbage
Copy link
Author

@jbielick
Copy link

Respawning is disabled. It will never work. It will never be able to track Unicorn like you think it should. Stop trying.

maybe expect fork is what you're looking for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment