linux - How can a runit' service restart return instantly? -
i have runit
service use run rails
app using unicorn
.
its restart command uses signal (usr2) handle zero-downtime restart. basically, waits until new process ready before old ones die.
this causes long (40 seconds) restart time, in service myservice restart
doesn't return until end.
while can give runit longer timeout (which do), want make restart fire-and-forget kind of action it'll return instantly (or after usr2 signal fired, without waiting complete.
the entire logic taken multiple blog posts zero-downtime rails
deployments unicorn
restarts:
- https://gist.github.com/czarneckid/4639793
- https://gist.github.com/jeanmertz/8996796
- https://nulogy.com/who-we-are/company-blog/articles/zero-downtime-deployments-with-chef-nginx-and-unicorn/
this runit
script (generated chef):
#!/bin/bash # # file managed chef, using <%= node.name %> cookbook. # editing file hand highly discouraged! # exec 2>&1 # # since unicorn creates new pid on restart/reload, needs little # love manage runit. instead of managing unicorn directly, # trap signal calls service , redirect them unicorn directly. # runit_pid=$$ application_name=<%= @options[:application_name] %> application_path=<%= file.join(@options[:path], 'current') %> bundle_cmd="<%= @options[:bundle_command] ? "#{@options[:bundle_command]} exec" : '' %>" unicorn_cmd=<%= @options[:unicorn_command] ? @options[:unicorn_command] : 'unicorn' %> unicorn_conf=<%= @options[:unicorn_config_path] ? @options[:unicorn_config_path] : file.join(@options[:path], 'current', 'config', 'unicorn.rb') %> rails_env=<%= @options[:rails_env] %> cur_pid_file=<%= @options['pid'] ? @options['pid'] : file.join(@options[:path], 'current', 'shared', 'pids', "#{@options[:application_name]}.pid") %> env_path=<%= @options[:env_dir] %> old_pid_file=$cur_pid_file.oldbin echo "runit service restarted (pid: $runit_pid)" function is_unicorn_alive { set +e if [ -n $1 ] && kill -0 $1 >/dev/null 2>&1; echo "yes" fi set -e } if [ -e $old_pid_file ]; old_pid=$(cat $old_pid_file) echo "old master detected (pid: $old_pid), waiting quit" while [ -n "$(is_unicorn_alive $old_pid)" ]; sleep 5 done fi if [ -e $cur_pid_file ]; cur_pid=$(cat $cur_pid_file) if [ -n "$(is_unicorn_alive $cur_pid)" ]; echo "detected running unicorn instance (pid: $cur_pid)" running=true fi fi function start { unset action if [ $running ]; restart else echo 'starting new unicorn instance' cd $application_path exec chpst -e $env_path $bundle_cmd $unicorn_cmd -c $unicorn_conf -e $rails_env sleep 3 cur_pid=$(cat $cur_pid_file) fi } function stop { unset action echo 'initializing graceful shutdown' kill -quit $cur_pid while [ -n "$(is_unicorn_alive $cur_pid)" ]; echo '.' sleep 2 done echo 'unicorn stopped, exiting runit process' kill -9 $runit_pid } function restart { unset action echo "restart request captured, swapping old master (pid: $cur_pid) new master usr2" kill -usr2 $cur_pid sleep 2 echo 'restarting runit service capture new master pid' exit } function alarm { unset action echo 'unicorn process interrupted' } trap 'action=stop' stop term kill trap 'action=restart' quit usr2 int trap 'action=alarm' alrm [ $running ] || action=start if [ $action ]; echo "performing \"$action\" action , going sleep mode until new signal captured" elif [ $running ]; echo "going sleep mode until new signal captured" fi if [ $action ] || [ $running ]; while true; [ "$action" == 'start' ] && start [ "$action" == 'stop' ] && stop [ "$action" == 'restart' ] && restart [ "$action" == 'alarm' ] && alarm sleep 2 done fi
this super weird way use runit, move reload logic control/h
script , use sv hup
(or since doesn't seem more sending usr2 sv 2
). main run script shouldn't involved.
Comments
Post a Comment