【问题标题】:Starting background tasks with Capistrano使用 Capistrano 启动后台任务
【发布时间】:2009-07-10 12:38:09
【问题描述】:

对于我的 RubyOnRails-App,我必须在 Capistrano 部署结束时启动后台作业。为此,我在 deploy.rb 中尝试了以下操作:

run "nohup #{current_path}/script/runner -e production 'Scheduler.start' &", :pty => true

有时这可行,但大多数时候它不会启动进程(= 未在 ps -aux 中列出)。并且没有错误消息。而且没有nohup.out,不在home目录下也不在rails app目录下。

我尝试在 scheduler.rb 中使用 trap('SIGHUP', 'IGNORE') 代替 nohup,但结果是一样的。

让它工作的唯一方法是删除 ":pty => true" 并在 "cap deploy" 结束时手动执行 Ctrl-C。但我不喜欢这样……

还有其他机会调用这个 Scheduler.start 吗?或者获取更多错误信息?

我在服务器上使用 Rails 2.3.2、Capistrano 2.5.8、Ubuntu Hardy

【问题讨论】:

  • 有什么提示吗?仍在与在这里重新启动后台作业作斗争...

标签: ruby-on-rails background capistrano nohup


【解决方案1】:

如果 :pty => true,用户 shell 启动脚本(例如 bashrc 等)(通常)不会被加载。由于缺少依赖环境变量,我的 ruby​​ 程序在启动后立即退出。

如果没有 :pty => true,正如您在问题中所描述的,capistrano 会挂在那里等待进程退出。您需要重定向 stdout 和 stderr 以使其立即返回。

run 'nohup ruby -e "sleep 5" &' # hangs for 5 seconds
run 'nohup ruby -e "sleep 5" > /dev/null &' # hangs for 5 seconds
run 'nohup ruby -e "sleep 5" > /dev/null 2>&1 &' # returns immediately. good.

如果您的后台任务仍然没有运行。尝试将 stdout 和 stderr 重定向到日志文件,以便调查输出。

【讨论】:

  • 我为同样的问题苦苦挣扎了一整天。按照建议重定向输出解决了问题。
【解决方案2】:

我想分享我的解决方案,该解决方案在执行多个命令时也有效。我尝试了许多其他在网上找到的变体,包括“sleep N”hack。

run("nohup sh -c 'cd #{release_path} && bundle exec rake task_namespace:task_name RAILS_ENV=production > ~/shared/log/<rakelog>.log &' > /dev/null 2>&1", :pty => true)

这是一个 dup 回复 launching background process in capistrano task,但我想确保其他人和我自己可以通过谷歌搜索此解决方案。

【讨论】:

  • 这对我有帮助。谢谢。
【解决方案3】:

您是否希望调度程序作业在后台持续运行并在您运行 Capistrano 时重新启动?

如果是这样,那么我使用 runit http://smarden.sunsite.dk/runit/ 和 DelayedJob http://github.com/Shopify/delayed_job/tree/master

  1. 以不替换init的方式安装runit
  2. 将后台作业添加为 runit 服务,并从 runit 为其添加日志监视器。
  3. 让 Capistrano 调用 sudo sv kill job_name 来终止并重新启动作业。

我的后台作业是处理后台 Rails 任务的 Rails 插件 DelayedJob 的一个实例。我在每次 Capistrano 部署时都将其杀死,因此它将使用更新的代码库重新启动。

事实证明这是非常可靠的。

HTH,

拉里

【讨论】:

  • 是的,调度程序应该在后台持续运行,并且应该在每次部署时重新启动。我在调度程序中使用 DelayedJob - 以及一些自己的东西。因为通过脚本/运行程序启动有时与 Capistrano 一起工作(并且总是如果我通过 SSH 会话手动启动它)我认为 Capistrano 只有一个小问题 - 所以我不想转向 runit,如果它是不是真的需要...但是非常感谢你的回答,拉里!
  • 重启后自动重启怎么样?这是 runit 需要处理的其他事情。 - 如果它死了,Plus 会重新启动。问候。
  • 部署用户永远不应该拥有sudo 权限。在大多数部署中,部署用户与运行 rails 应用程序的用户相同。向该用户授予 sudo 权限是一个非常糟糕的主意,尤其是考虑到最近的 Rails 安全问题,攻击者可以执行任意代码。
【解决方案4】:

如果此任务调度程序有 -d 开关,它将起作用。例如,独立乘客有一个 -d 选项,可以将其作为恶魔化进程启动。

namespace :passenger_standalone do
  task :start do
    run "cd #{current_path} && passenger start -e #{rails_env} -d"
  end
  task :stop do
    run "cd #{current_path} && RAILS_ENV=#{rails_env} passenger stop"
  end
  task :restart do
    stop
    start
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 2015-11-20
    • 2020-01-10
    相关资源
    最近更新 更多