【问题标题】:When restarting delayed_job with capistrano it isn't always creating the pid file使用 capistrano 重新启动 delay_job 时,它并不总是创建 pid 文件
【发布时间】:2012-03-17 03:38:07
【问题描述】:

当 ssh 进入网络服务器时,我可以整天重新启动延迟作业,而不会出现问题。它会关闭现有的工作程序,启动一个新工作程序并使用其进程 ID 写入 tmp/pids/delayed_job.pid。 (我也在重新启动乘客以模仿我将要使用 capistrano 做的事情)

app@StagingServer:/app/current$ touch tmp/restart.txt; RAILS_ENV=staging script/delayed_job restart
delayed_job: trying to stop process with pid 22170...
delayed_job: process with pid 22170 successfully stopped.
delayed_job: process with pid 22284 started.
app@StagingServer:/app/current$ touch tmp/restart.txt; RAILS_ENV=staging script/delayed_job restart
delayed_job: trying to stop process with pid 22284...
delayed_job: process with pid 22284 successfully stopped.
delayed_job: process with pid 22355 started.
app@StagingServer:/app/current$ touch tmp/restart.txt; RAILS_ENV=staging script/delayed_job restart
delayed_job: trying to stop process with pid 22355...
delayed_job: process with pid 22355 successfully stopped.
delayed_job: process with pid 22427 started.
app@StagingServer:/app/current$

但是,当我使用 capistrano 进行部署时

dev@ubuntu:~/app-site$ cap passenger:restart
    triggering start callbacks for `passenger:restart'
  * executing `multistage:ensure'
*** Defaulting to `staging'
  * executing `staging'
  * executing `passenger:restart'
  * executing "touch /app/current/tmp/restart.txt"
    servers: ["staging.app.com"]
    [staging.app.com] executing command
    command finished in 242ms
  * executing "cd /app/current;RAILS_ENV=staging script/delayed_job restart"
    servers: ["staging.app.com"]
    [staging.app.com] executing command
 ** [out :: staging.app.com] delayed_job: trying to stop process with pid 21646...
 ** [out :: staging.app.com] delayed_job: process with pid 21646 successfully stopped.
    command finished in 11889ms

看起来不错?虽然没有打印延迟作业的最后一行(我认为由于它没有以换行符结尾),但这确实成功地创建了一个新进程。但是,它不会创建 .pid 文件,所以当我尝试重新启动时:

dev@ubuntu:~/app-site$ cap passenger:restart
    triggering start callbacks for `passenger:restart'
  * executing `multistage:ensure'
*** Defaulting to `staging'
  * executing `staging'
  * executing `passenger:restart'
  * executing "touch /app/current/tmp/restart.txt"
    servers: ["staging.app.com"]
    [staging.app.com] executing command
    command finished in 398ms
  * executing "cd /app/current;RAILS_ENV=staging script/delayed_job restart"
    servers: ["staging.app.com"]
    [staging.app.com] executing command
 ** [out :: staging.app.com] Warning: no instances running. Starting...
 ** [out :: staging.app.com] delayed_job: process with pid 21950 started.
    command finished in 6758ms

它不会停止现有的进程。奇怪的是,这一次它会创建一个新进程并且它是 .pid 文件。

这让我有 2 个 delay_jobs 进程在运行,而 .pid 文件中只有一个。我所做的每 2 个 cap 部署都会添加另一个 delay_job 进程。之前的进程使用的是旧版本的应用程序,本质上是破坏它。

配置/部署.rb:

namespace :passenger do
  desc "Restart Application"  
  task :restart do  
    run "touch #{current_path}/tmp/restart.txt"
    run "cd #{current_path};RAILS_ENV=#{deploy_env} script/delayed_job restart"
  end
end
after :deploy, "passenger:restart"
  • Ubuntu、nginx、乘客
  • 守护进程 (1.1.4)
  • delayed_job (2.1.4)
  • 导轨 (3.0.9)

在本地

  • capistrano (2.9.0)
  • capistrano-ext (1.2.1)

更新:

仔细阅读,这似乎与守护进程内部的竞争条件有关。但是,我有点困惑为什么它在使用 capistrano 时只(并且始终如一地)显示。我将尝试将命令更改为停止,睡眠然后启动。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 capistrano delayed-job


    【解决方案1】:

    通过使用停止和启动而不是重新启动来解决。由于可能由守护进程 gem 引起的竞争条件而工作。

    我仍然想知道是否有其他人有更好的解决方案。

    【讨论】:

      【解决方案2】:

      我遇到了这个问题,停止和启动对我不起作用,所以我想出了以下方法:

      namespace :delayed_job do
      desc 'Restart delayed_job worker'
        task :restart do
          on roles(:delayed_job) do
            within release_path do
              with rails_env: fetch(:rails_env) do
                execute :pkill , "-f", "'delayed_job'"
                execute :bundle, :exec, "bin/delayed_job", :start
              end
            end
          end
        end
      end
      ...
      after :restart,  "delayed_job:restart"
      

      不是 pkill 的忠实粉丝,但这对我来说始终有效。希望这会有所帮助

      【讨论】:

        【解决方案3】:

        Capistrano 会在每次部署期间对当前目录的符号链接进行洗牌,这对我来说是孤立的 PID。我们使用 capistrano3-delayed-job gem,它建议将这些修复之一应用于 deploy.rb:

        set :linked_dirs, %w(tmp/pids)
        
        # or
        
        set :delayed_job_pid_dir, '/tmp'
        

        第一个为我们解决了这个问题。它将 current/tmp/pids 移动到 shared/tmp/ 并将其符号链接到当前树中,以便它在部署中持续存在。

        【讨论】:

          猜你喜欢
          • 2012-11-09
          • 2016-08-19
          • 2012-10-26
          • 1970-01-01
          • 2011-03-06
          • 1970-01-01
          • 1970-01-01
          • 2022-11-03
          • 1970-01-01
          相关资源
          最近更新 更多