Puma workers无法在Ubuntu 20.04 VM上的Rails 5.2中启动

wgeznvg7  于 2023-10-17  发布在  其他
关注(0)|答案(1)|浏览(203)

我正在学习使用Capistrano部署一个演示rails应用程序,其中Puma作为应用服务器,Nginx作为web服务器。我在一个文件_stage.rb中设置了必要的puma配置,然后将puma设置为/etc/init.d/puma_myarticles_staging服务。可执行文件puma_init.sh.erb后来作为puma_init.sh写入远程服务器,看起来像,

  1. #!/usr/bin/env bash
  2. PATH=/usr/local/bin:/usr/local/sbin/:/sbin:/usr/sbin:/bin:/usr/bin
  3. DESC="Puma rack web server"
  4. NAME=puma_<%=fetch(:full_app_name)%>
  5. SCRIPT_NAME=/etc/init.d/${NAME}
  6. APP_ROOT=<%=current_path%>
  7. PIDFILE=<%= fetch(:puma_pid) %>
  8. STATE_FILE=<%= fetch(:puma_state) %>
  9. log_daemon_msg() { echo "$@"; }
  10. log_end_msg() { [ $1 -eq 0 ] && RES=OK; logger ${RES:=FAIL}; }
  11. run_pumactl(){
  12. [ $# -lt 1 ] && echo "$# params were given, Expected 1" && exit 1
  13. cd ${APP_ROOT} && <%= fetch(:rbenv_prefix) %> bundle exec pumactl -F <%=fetch(:puma_conf)%> $1
  14. }
  15. # Function that starts the puma
  16. #
  17. start_task() {
  18. if [ -e ${PIDFILE} ]; then
  19. PID=`cat ${PIDFILE}`
  20. # If the puma isn't running, run it, otherwise restart it.
  21. if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
  22. do_start_task
  23. else
  24. restart_task
  25. fi
  26. else
  27. do_start_task
  28. fi
  29. }
  30. do_start_task() {
  31. log_daemon_msg "--> Woke up puma ${APP_ROOT}"
  32. run_pumactl start
  33. }
  34. # Function that stops the daemon/service
  35. #
  36. stop_task() {
  37. log_daemon_msg "--> Stopping puma in path: ${APP_ROOT} ..."
  38. if [ -e ${PIDFILE} ]; then
  39. PID=`cat ${PIDFILE}`
  40. if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
  41. log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
  42. else
  43. log_daemon_msg "--> About to kill puma with PID: `cat $PIDFILE` ..."
  44. if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
  45. log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
  46. return 0
  47. else
  48. run_pumactl stop
  49. log_daemon_msg "--> Waiting for status ..."
  50. sleep 5
  51. if [ "`ps -A -o pid= | grep -c ${PID}`" -eq 0 ]; then
  52. log_daemon_msg "--> Puma with pid ${PID} stopped successfully."
  53. rm -f ${PIDFILE} ${STATE_FILE}
  54. else
  55. log_daemon_msg "--> Unable to stop puma with pid ${PID}."
  56. fi
  57. fi
  58. fi
  59. else
  60. log_daemon_msg "--> Puma isn't running in path: ${APP_ROOT}."
  61. fi
  62. return 0
  63. }
  64. # Function that sends a SIGUSR2 to the daemon/service
  65. #
  66. restart_task() {
  67. if [ -e ${PIDFILE} ]; then
  68. log_daemon_msg "--> About to restart puma in path: ${APP_ROOT} ..."
  69. run_pumactl restart
  70. else
  71. log_daemon_msg "--> Your puma was never playing... Let's get it out there first ..."
  72. start_task
  73. fi
  74. return 0
  75. }
  76. # Function that sends a SIGUSR2 to the daemon/service
  77. #
  78. status_task() {
  79. if [ -e ${PIDFILE} ]; then
  80. log_daemon_msg "--> About to status puma ${APP_ROOT} ..."
  81. run_pumactl status
  82. else
  83. log_daemon_msg "---> Puma isn't running in path: ${APP_ROOT}."
  84. fi
  85. return 0
  86. }
  87. case "$1" in
  88. start)
  89. [ "$VERBOSE" != no ] && log_daemon_msg "Starting ${DESC}" "${NAME} ..."
  90. start_task
  91. case "$?" in
  92. 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  93. 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  94. esac
  95. ;;
  96. stop)
  97. [ "$VERBOSE" != no ] && log_daemon_msg "Stopping ${DESC}" "${NAME} ..."
  98. stop_task
  99. case "$?" in
  100. 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  101. 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  102. esac
  103. ;;
  104. status)
  105. log_daemon_msg "Status ${DESC}" "${NAME} ..."
  106. status_task
  107. case "$?" in
  108. 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  109. 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  110. esac
  111. ;;
  112. restart)
  113. log_daemon_msg "Restarting ${DESC}" "${NAME} ..."
  114. restart_task
  115. case "$?" in
  116. 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  117. 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  118. esac
  119. ;;
  120. *)
  121. echo "Usage:" >&2
  122. echo " ${SCRIPT_NAME} {start|stop|status|restart}" >&2
  123. exit 3
  124. ;;
  125. esac
  126. :

puma.rb是,

  1. #!/usr/bin/env puma
  2. directory '/app/myarticles_staging/current'
  3. environment 'staging'
  4. pidfile '/app/myarticles_staging/shared/tmp/pids/puma.pid'
  5. state_path '/app/myarticles_staging/shared/tmp/states/puma.state'
  6. stdout_redirect '/app/myarticles_staging/shared/log/puma_access.log', '/app/myarticles_staging/shared/log/puma_error.log', true
  7. daemonize
  8. threads 4, 8
  9. bind 'unix:///app/myarticles_staging/shared/tmp/sockets/puma.myarticles_staging.sock'
  10. activate_control_app 'unix:///app/myarticles_staging/shared/tmp/sockets/pumactl.myarticles_staging.sock'
  11. workers '4'
  12. preload_app!
  13. on_worker_boot do
  14. require "active_record"
  15. ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  16. ActiveRecord::Base.establish_connection(YAML.load_file('/app/myarticles_staging/shared/config/database.yml')['staging'])
  17. end
  18. # Allow puma to be restarted by the `rails restart` command.
  19. plugin :tmp_restart

我从一个名为_stage.rb的文件中获取所有的puma配置,

  1. set :stage, :staging
  2. set :branch, :staging
  3. set :server_port, 80
  4. set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}"
  5. set :rails_env, :staging
  6. set :deploy_to, "/app/#{fetch(:full_app_name)}"
  7. set :puma_user, fetch(:deploy_user)
  8. set :puma_state, "#{shared_path}/tmp/states/puma.state"
  9. set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
  10. set :puma_rackup, -> { File.join(current_path, 'config.ru')}
  11. set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.#{fetch(:full_app_name)}.sock"
  12. set :puma_default_control_app, "unix://#{shared_path}/tmp/sockets/pumactl.#{fetch(:full_app_name)}.sock"
  13. set :puma_conf, "#{shared_path}/config/puma.rb"
  14. set :puma_workers, 4
  15. set :puma_threads, [4, 8]
  16. set :puma_role, :app
  17. set :puma_env, :staging
  18. set :puma_preload_app, true
  19. set :puma_enable_socket_service, true
  20. set :puma_access_log, "#{shared_path}/log/puma_access.log"
  21. set :puma_error_log, "#{shared_path}/log/puma_error.log"
  22. set :nginx_access_log, "#{shared_path}/log/nginx_access.log"
  23. set :nginx_error_log, "#{shared_path}/log/nginx_error.log"

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

  1. Starting Puma rack web server puma_myarticles_staging ...
  2. --> Woke up puma /app/myarticles_staging/current
  3. [3955] Puma starting in cluster mode...
  4. [3955] * Version 4.3.12 (ruby 2.7.0-p0), codename: Mysterious Traveller
  5. [3955] * Min threads: 4, max threads: 8
  6. [3955] * Environment: staging
  7. [3955] * Process workers: 1
  8. [3955] * Preloading application
  9. [3955] * Listening on unix:///app/myarticles_staging/shared/tmp/sockets/puma.myarticles_staging.sock
  10. [3955] ! WARNING: Detected 1 Thread(s) started in app boot:
  11. [3955] ! #<Thread:0x000055c692868bf8 /app/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-6.1.7.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:323 sleep> - /app/myarticles_staging/shared/bundle/ruby/2.7.0/gems/activerecord-6.1.7.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:329:in `sleep'
  12. [3955] * Daemonizing...

没有留下新的美洲狮或国家档案。最终,puma服务工作人员没有 Boot ,因为我检查了puma.pidpuma.state没有文件正在写入。当我运行rbenv exec bundle exec rails scurrent_path上手动测试时,它工作正常。
我使用ps ax | grep puma检查了被妖魔化的puma进程,但没有找到实际的puma工作人员,

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

有什么建议我可能做错了吗?先谢了。

r1zk6ea1

r1zk6ea11#

也许问题出在美洲狮开始的方式上。我很确定这里没有美洲狮。您还没有发布有关systemctl设置的任何详细信息,但最佳做法是使用用户服务文件,这样puma将始终在 Boot 时启动,并且不需要密码
我使用的标准puma配置是这样的

  1. # Puma can serve each request in a thread from an internal thread pool.
  2. # The `threads` method setting takes two numbers: a minimum and maximum.
  3. # Any libraries that use thread pools should be configured to match
  4. # the maximum value specified for Puma. Default is set to 5 threads for minimum
  5. # and maximum; this matches the default thread size of Active Record.
  6. #
  7. max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
  8. min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
  9. threads min_threads_count, max_threads_count
  10. # Change to match your CPU core count
  11. workers 0
  12. # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
  13. #
  14. port ENV.fetch("PORT") { 3000 }
  15. # Specifies the `environment` that Puma will run in.
  16. #
  17. rails_env = ENV['RAILS_ENV'] || "production"
  18. environment rails_env
  19. app_dir = File.expand_path("../..", __FILE__)
  20. #shared_dir = "#{app_dir}/shared"
  21. shared_dir = "/home/project/apps/comtech/shared" # Use your projects path
  22. # Specifies the `pidfile` that Puma will use.
  23. #pidfile ENV.fetch("PIDFILE") { "pids/server.pid" }
  24. pidfile "#{shared_dir}/pids/puma.pid"
  25. state_path "#{shared_dir}/pids/puma.state"
  26. activate_control_app
  27. # Set up socket location
  28. bind "unix://#{shared_dir}/sockets/comtech_puma.sock"
  29. on_worker_boot do
  30. require "active_record"
  31. ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  32. ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
  33. end
  34. # Specifies the number of `workers` to boot in clustered mode.
  35. # Workers are forked web server processes. If using threads and workers together
  36. # the concurrency of the application would be max `threads` * `workers`.
  37. # Workers do not work on JRuby or Windows (both of which do not support
  38. # processes).
  39. #
  40. # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
  41. # Use the `preload_app!` method when specifying a `workers` number.
  42. # This directive tells Puma to first boot the application and load code
  43. # before forking the application. This takes advantage of Copy On Write
  44. # process behavior so workers use less memory.
  45. #
  46. # preload_app!
  47. # Allow puma to be restarted by `rails restart` command.
  48. plugin :tmp_restart

显然,您需要在服务器上将ENVIRONMENT变量设置为staging
相应地调整pids文件夹以使用tmp。
要使用用户服务而不是系统服务,请查看以下内容
cd ~/.config/systemd/user创建不存在的文件夹
nano name_of_your_puma.service并相应地粘贴以下内容调整路径。

  1. [Unit]
  2. Description=Puma Rack Server
  3. # Puma supports systemd's `Type=notify` and watchdog service
  4. # monitoring, if the [sd_notify](https://github.com/agis/ruby-sdnotify) gem is installed,
  5. # as of Puma 5.1 or later.
  6. # On earlier versions of Puma or JRuby, change this to `Type=simple` and remove
  7. # the `WatchdogSec` line.
  8. [Service]
  9. Type=simple
  10. # If your Puma process locks up, systemd's watchdog will restart it within seconds.
  11. #WatchdogSec=10
  12. RestartSec=10
  13. WorkingDirectory=/home/comtech/apps/comtech/current
  14. #PIDFile=/home/comtech/apps/comtech/shared/pids/puma.pid
  15. #User=comtech
  16. ExecStart=/home/comtech/.rvm/bin/rvm 3.1.3@comtech_cms_app do bundle exec puma -C /home/comtech/apps/comtech/current/config/puma_production.rb
  17. ExecStop=/home/comtech/.rvm/bin/rvm 3.1.3@comtech_cms_app do bundle exec pumactl -S /home/comtech/apps/comtech/shared/pids/puma.state stop
  18. ExecReload=/home/comtech/.rvm/bin/rvm [email protected]@comtech_cms_app do bundle exec pumactl -S /home/comtech/apps/comtech/shared/pids/puma.state restart
  19. Restart=always
  20. [Install]
  21. WantedBy=multi-user.target

然后运行

  1. $ systemctl --user enable name_of_your_puma.service

来检查服务

  1. $ systemctl --user status

停止服务

  1. $ systemctl --user stop

启动服务

  1. $ systemctl --user start

该服务将在 Boot 时自动启动,并在puma失败时重新启动puma。还要注意我使用的是RVM,因此需要相应地调整start命令

展开查看全部

相关问题