2016-06-09 20 views
1

Ich bin neu im Einsatz, also ist das wahrscheinlich ein Anfängerfehler, aber hier geht es.Unicorn nimmt Änderungen nicht mit neuer Bereitstellung der Rails-App auf (Capistrano, Nginx)

Ich habe eine Rails 4 App, die ich auf einem Linux-Server mit einer Kombination aus Capistrano, Unicorn und Nginx bereitstellen. Das Deploy-Skript läuft gut und die App ist nun auf die gewünschte IP-Adresse erreichbar, das ist großartig. Die Sache ist, a) Unicorn startet bei der Bereitstellung nicht neu (zumindest ändern sich die PIDs nicht) und b) nicht überraschend, die neuen Änderungen werden nicht in der verfügbaren App wiedergegeben. Ich kann anscheinend nichts anderes tun als das Einhorn komplett anzuhalten und neu zu starten, um es aufzufrischen. Wenn ich das tue, dann werden die Änderungen übernommen, aber dieser Prozess ist offensichtlich nicht ideal.

Manuell, wenn ich kill -s HUP $UNICORN_PID ausführen, dann ändern sich die PIDs der Arbeiter, aber nicht der Master, und Änderungen werden nicht aufgehoben (was anscheinend sie sein sollen); Die Verwendung von USR2 scheint keine Auswirkungen auf die aktuellen Prozesse zu haben.

Hier ist das Einhorn Init-Skript Ich verwende, basierend auf Vorschläge von anderen Stack-Überlauf Fragen mit ähnlichen Problemen:

set -e 

USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>" 

# app settings 
USER="deploy" 
APP_NAME="app_name" 
APP_ROOT="/path/to/$APP_NAME" 
ENV="production" 

# environment settings 
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH" 
CMD="cd $APP_ROOT/current && bundle exec unicorn -c config/unicorn.rb -E $ENV -D" 
PID="$APP_ROOT/shared/pids/unicorn.pid" 
OLD_PID="$PID.oldbin" 
TIMEOUT=${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) 
    sig HUP && echo "reloaded $APP_NAME" && 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_PID && test $n -ge 0 
     do 
     printf '.' && sleep 1 && n=$(($n - 1)) 
     done 
     echo 

    if test $n -lt 0 && test -s $OLD_PID 
    then 
     echo >&2 "$OLD_PID still exists after $TIMEOUT seconds" 
     exit 1 
    fi 
    exit 0 
    fi 
    echo >&2 "Couldn't upgrade, starting '$CMD' instead" 
    su - $USER -c "$CMD" 
    ;; 
    rotate) 
    sig USR1 && echo rotated logs OK && exit 0 
    echo >&2 "Couldn't rotate logs" && exit 1 
    ;; 
    *) 
    echo >&2 $USAGE 
    exit 1 
    ;; 
esac 

dieses Skript verwenden, start und stop Arbeit wie erwartet, aber reload/restart nichts tun (Sie drucken die erwartete Ausgabe, ändern aber nicht die laufenden PIDs) und upgrade schlägt fehl. Laut dem Fehlerprotokoll liegt das daran, dass der erste Master noch läuft (ArgumentError: Already running on PID: $PID).

Und hier ist mein unicorn.rb:

app_path = File.expand_path("../..", __FILE__) 
working_directory "#{app_path}" 
pid    "#{app_path}/../../shared/pids/unicorn.pid" 

# listen 
listen "#{app_path}/../../shared/sockets/unicorn.sock", :backlog => 64 

# logging 
stderr_path "#{app_path}/../../shared/log/unicorn.stderr.log" 
stdout_path "#{app_path}/../../shared/log/unicorn.stdout.log" 

# workers 
worker_processes 3 

# use correct Gemfile on restarts 
before_exec do |server| 
    ENV['BUNDLE_GEMFILE'] = "#{working_directory}/Gemfile" 
end 

# preload 
preload_app false 

before_fork do |server, worker| 
    old_pid = "#{app_path}/shared/pids/unicorn.pid.oldbin" 
    if File.exists?(old_pid) && server.pid != old_pid 
    begin 
     Process.kill("QUIT", File.read(old_pid).to_i) 
    rescue Errno::ENOENT, Errno::ESRCH 
     # someone else did our job for us 
    end 
    end 
end 

after_fork do |server, worker| 
    if defined?(ActiveRecord::Base) 
    ActiveRecord::Base.establish_connection 
    end 
end 

Jede Hilfe wird sehr geschätzt, Dank!

Antwort

1

Es ist schwer, sicher zu sagen, da ich vor diesem speziellen Problem nicht aufgetreten sind, aber meine Vermutung ist, dass dies Ihr Problem ist:

app_path = File.expand_path("../..", __FILE__) 
working_directory "#{app_path}" 

Sie Jedes Mal bereitstellen, erstellt Capistrano ein neues Verzeichnis für Ihre App am Standort releases/<timestamp>. Es aktualisiert dann einen current Symlink, um auf dieses neueste Release-Verzeichnis zu zeigen.

In Ihrem Fall können Sie fälschlicherweise Unicorn sagen, releases/<timestamp> als sein working_directory zu verwenden. (SSH an den Server und überprüfen Sie den Inhalt von unicorn.rb, um sicher zu sein.) Stattdessen sollten Sie auf current zeigen. Auf diese Weise müssen Sie nicht anhalten und ein Einhorn kalt starten, um das neue Arbeitsverzeichnis zu sehen.

Ich schlage vor, Ihre unicorn.rb neu zu schreiben, so dass Sie keine relativen Pfade verwenden. Stattdessen codieren Sie die absoluten Pfade zu current und shared. Es ist in Ordnung, dies zu tun, da diese Pfade für jedes Release gleich bleiben.

+0

Yup, kann nicht glauben, dass ich das verpasst habe! Vielen Dank :) – lbar

0

Die Linie

ENV="production" 

sieht mir sehr verdächtig. Ich vermute, dass es sein möchte

RAILS_ENV="production". 

ohne diese wird nicht Schienen wachen nicht wissen, welche Umgebung es ist?