Puma 工作人员无法在 Ubuntu 20.04 VM 上的 Rails 5.2 中启动

问题描述 投票:0回答:1

我正在学习使用

Capistrano
部署演示 Rails 应用程序,并使用 Puma 作为应用程序服务器和相应的 Nginx Web 服务器。我已在名为
_stage.rb
的文件中设置了必要的 puma 设置配置,并将
puma
设置为
systemd
服务,这是我符号链接为
/etc/init.d/puma_myarticles_staging
的可执行文件。可执行文件名为
puma_init.sh.erb
,后来被写入远程服务器作为
puma_init.sh
,看起来像,

#!/usr/bin/env bash

PATH=/usr/local/bin:/usr/local/sbin/:/sbin:/usr/sbin:/bin:/usr/bin
DESC="Puma rack web server"
NAME=puma_<%=fetch(:full_app_name)%>
SCRIPT_NAME=/etc/init.d/${NAME}
APP_ROOT=<%=current_path%>
PIDFILE=<%= fetch(:puma_pid) %>
STATE_FILE=<%= fetch(:puma_state) %>

log_daemon_msg() { echo "$@"; }
log_end_msg() { [ $1 -eq 0 ] && RES=OK; logger ${RES:=FAIL}; }

run_pumactl(){
  [ $# -lt 1 ] && echo "$# params were given, Expected 1" && exit 1
  cd ${APP_ROOT} && <%= fetch(:rbenv_prefix) %> bundle exec pumactl -F <%=fetch(:puma_conf)%> $1
}

# Function that starts the puma
#
start_task() {
  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_task
    else
      restart_task
    fi
  else
    do_start_task
  fi
}
do_start_task() {
  log_daemon_msg "--> Woke up puma ${APP_ROOT}"
  run_pumactl start
}

# Function that stops the daemon/service
#
stop_task() {
  log_daemon_msg "--> Stopping puma in path: ${APP_ROOT} ..."
  if [ -e ${PIDFILE} ]; then
    PID=`cat ${PIDFILE}`
    if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
      log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
    else
      log_daemon_msg "--> About to kill puma with PID: `cat $PIDFILE` ..."
      if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
        log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
        return 0
      else
        run_pumactl stop
        log_daemon_msg "--> Waiting for status ..."
        sleep 5
        if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
          log_daemon_msg "--> Puma with pid ${PID} stopped successfully."
          rm -f ${PIDFILE} ${STATE_FILE}
        else
          log_daemon_msg "--> Unable to stop puma with pid ${PID}."
        fi
      fi
    fi
  else
    log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
  fi
  return 0
}

# Function that sends a SIGUSR2 to the daemon/service
#
restart_task() {
  if [ -e ${PIDFILE} ]; then
    log_daemon_msg "--> About to restart puma in path: ${APP_ROOT} ..."
    run_pumactl restart
  else
    log_daemon_msg "--> Your puma was never playing... Let's get it out there first ..."
    start_task
  fi
  return 0
}

#
# Function that sends a SIGUSR2 to the daemon/service
#
status_task() {
  if [ -e ${PIDFILE} ]; then
    log_daemon_msg "--> About to status puma ${APP_ROOT} ..."
    run_pumactl status
  else
    log_daemon_msg "---> Puma isn't running in path: ${APP_ROOT}."
  fi
  return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting ${DESC}" "${NAME} ..."
    start_task
    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} ..."
    stop_task
    case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  status)
    log_daemon_msg "Status ${DESC}" "${NAME} ..."
    status_task
    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} ..."
    restart_task
    case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  *)
    echo "Usage:" >&2
    echo "  ${SCRIPT_NAME} {start|stop|status|restart}" >&2
    exit 3
    ;;
esac
:

然而,由于未知的原因,Puma 工作人员并未作为一个进程启动。我的

puma.rb.erb
后来写成
puma.rb
是,

#!/usr/bin/env puma

directory '<%= current_path %>'
environment '<%= fetch(:rails_env) %>'

pidfile '<%= fetch(:puma_pid) %>'
state_path '<%= fetch(:puma_state) %>'
stdout_redirect '<%= fetch(:puma_access_log) %>', '<%= fetch(:puma_error_log) %>', true

daemonize

threads <%= fetch(:puma_threads).join(', ') %>

bind '<%= fetch(:puma_bind) %>'

activate_control_app '<%= fetch(:puma_default_control_app) %>'

workers '<%= fetch(:puma_workers) %>'

preload_app!

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
end

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

我从名为

_stage.rb
的文件中获取所有美洲狮配置,看起来像,

set :stage, :staging
set :branch, :staging

set :server_port, 80

set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}"
set :rails_env, :staging

set :deploy_to, "/home/#{fetch(:deploy_user)}/#{fetch(:full_app_name)}"

set :puma_user, fetch(:deploy_user)
set :puma_state, "#{shared_path}/tmp/states/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_rackup, -> { File.join(current_path, 'config.ru')}
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.#{fetch(:full_app_name)}.sock"
set :puma_default_control_app, "unix://#{shared_path}/tmp/sockets/pumactl.#{fetch(:full_app_name)}.sock"
set :puma_conf, "#{shared_path}/config/puma.rb"
set :puma_workers, 4
set :puma_threads, [4, 8]
set :puma_role, :app
set :puma_env, :staging
set :puma_preload_app, true

set :puma_enable_socket_service, true
set :puma_access_log, "#{shared_path}/log/puma_access.log"
set :puma_error_log, "#{shared_path}/log/puma_error.log"

set :nginx_access_log, "#{shared_path}/log/nginx_access.log"
set :nginx_error_log, "#{shared_path}/log/nginx_error.log"

当我以

/etc/init.d/puma_myarticles_staging start
启动 puma 服务时,它输出,

Starting Puma rack web server puma_myarticles_staging ...
--> Woke up puma /home/deployer/myarticles_staging/current
[1484] Puma starting in cluster mode...
[1484] * Version 3.12.6 (ruby 2.7.0-p0), codename: Llamas in Pajamas
[1484] * Min threads: 4, max threads: 8
[1484] * Environment: staging
[1484] * Process workers: 4
[1484] * Preloading application
/home/deployer/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-5.2.8.1/lib/active_record/type.rb:27: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/home/deployer/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-5.2.8.1/lib/active_record/type/adapter_specific_registry.rb:9: warning: The called method `add_modifier' is defined here
[1484] * Listening on unix:///home/deployer/myarticles_staging/shared/tmp/sockets/puma.myarticles_staging.sock
[1484] ! WARNING: Detected 1 Thread(s) started in app boot:
[1484] ! #<Thread:0x0000561adf6c0228 /home/deployer/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-5.2.8.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:299 sleep> - /home/deployer/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-5.2.8.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:301:in `sleep'
[1484] * Daemonizing...

不留下新的 puma pid 或状态文件。最终,当我检查

puma.pid
puma.state
没有文件被写入时,puma 服务人员没有启动。当我运行
rbenv exec bundle exec rails s
current_path
上手动测试时,它起作用了。

我使用它输出的

systemd
检查了被妖魔化为
ps ax | grep puma
服务的 puma 进程,

1516 pts/0    S+     0:00 grep --color=auto puma

对我可能做错的事情有什么建议吗? TIA

ruby-on-rails ruby bash ubuntu puma
1个回答
1
投票

也许问题在于 puma 的启动方式。我很确定这里没有 Puma bug。 您还没有发布有关 systemctl 设置的任何详细信息,但最佳实践是使用用户服务文件,这样 puma 将始终在启动时启动,并且不需要密码

我使用的标准 puma 配置是这样的

# Puma can serve each request in a thread from an internal thread pool.
# The `threads` 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.
#
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

# Change to match your CPU core count
workers 0

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }

# Specifies the `environment` that Puma will run in.
#

rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

app_dir = File.expand_path("../..", __FILE__)
#shared_dir = "#{app_dir}/shared"
shared_dir = "/home/project/apps/comtech/shared" # Use your projects path

# Specifies the `pidfile` that Puma will use.
#pidfile ENV.fetch("PIDFILE") { "pids/server.pid" }

pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

# Set up socket location
bind "unix://#{shared_dir}/sockets/comtech_puma.sock"

on_worker_boot do
  require "active_record"
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

# Use the `preload_app!` method when specifying a `workers` 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.
#
# preload_app!

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

显然,您需要将

ENVIRONMENT
变量设置为在服务器上暂存

相应调整 pids 文件夹以使用 tmp。

如果没有更多信息,真的无法提供更多帮助

© www.soinside.com 2019 - 2024. All rights reserved.