【问题标题】:How to automatically restart delayed_job when deploying a rails project on Amazon Elastic Beanstalk?在 Amazon Elastic Beanstalk 上部署 rails 项目时如何自动重启 delay_job?
【发布时间】:2013-01-02 07:09:08
【问题描述】:

我在Amazon Elastic Beanstalk 上托管一个rails 项目,我尝试配置container command 以在每次部署后自动重新启动服务器上的delayed_job 工作人员。

我试过这个:

container_commands:
  restartdelayedjob:
    command: "RAILS_ENV=production script/delayed_job --pid-dir=/home/ec2-user/pids start"
    cwd: /var/app/current

但是,推送的版本似乎是在worker重启后部署的,因此worker无法处理作业。

当我通过 ssh 连接到我的实例时,终止工作进程并从已部署的版本文件夹中重新启动一个新进程,一切正常。

您对我如何处理这个问题有任何想法吗?

谢谢

【问题讨论】:

    标签: ruby-on-rails deployment amazon-web-services delayed-job amazon-elastic-beanstalk


    【解决方案1】:

    根据Amazon documentation for container_commands

    它们在应用程序和网络服务器设置完毕并提取应用程序版本文件之后运行,但在应用程序版本部署之前

    (强调我的)

    这意味着此时您为命令设置为cwd/var/app/current 仍指向以前的版本。但是默认情况下,再次来自文档,cwd:

    是解压后的应用目录。

    这意味着如果您想从刚刚提取(但尚未部署)的应用程序的目录中运行delayed_job,请不要覆盖cwd,它应该为即将执行的应用程序启动delayed_job部署。

    参考:http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#customize-containers-format-container_commands

    更新:

    我现在自己进行了设置,发现通过标准 container_commands 执行此操作存在限制 - 基本上,delayed_job 将在它仍在 /var/app/ondeck 目录中时启动。通常这没问题,但我在某些工作中遇到了一些问题,因为该路径卡在它周围会导致错误,因为应用程序现在位于 /var/app/current

    我发现了一种未记录的(非常警告!)方法,您可以添加脚本以在您的应用服务器重新启动后运行(并且您的新部署位于 /var/app/current)。

    基本上,Elastic Beanstalk 将在 Web 服务器重新启动后执行 /opt/elasticbeanstalk/hooks/appdeploy/post 中的任何脚本。这意味着如果您将 shell 脚本放在此目录中,它们将被运行。

    我创建了一个这样的 shell 脚本:

    #!/usr/bin/env bash
    . /opt/elasticbeanstalk/support/envvars
    cd $EB_CONFIG_APP_CURRENT
    su -c "RAILS_ENV=production script/delayed_job --pid-dir=$EB_CONFIG_APP_SUPPORT/pids restart" $EB_CONFIG_APP_USER
    

    我将此脚本上传到 S3 存储桶,并确保它是“公开的”。然后,您可以使用.ebextensions 目录中的选项脚本(例如99delayed_job.config)将此脚本部署为应用程序部署的一部分,注意post 目录可能不存在:

    commands:
      create_post_dir:
        command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
        ignoreErrors: true
    files:
      "/opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh":
        mode: "000755"
        owner: root
        group: root
        source: http://YOUR_BUCKET.s3.amazonaws.com/99_restart_delayed_job.sh
    

    部署时,您应该在/var/log/eb-tools.log 中看到类似的内容:

    2013-05-16 01:20:53,759 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Executing directory: /opt/elasticbeanstalk/hooks/appdeploy/post/
    2013-05-16 01:20:53,760 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Executing script: /opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh
    2013-05-16 01:21:02,619 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Output from script: delayed_job: trying to stop process with pid 6139...
    delayed_job: process with pid 6139 successfully stopped.
    
    2013-05-16 01:21:02,620 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Script succeeded.
    

    正如我所说,将内容放入此“post”目录是未记录的 - 但希望亚马逊在某个时候为 .options 脚本添加实际支持以在部署后运行命令,在这种情况下,您可以将其移至官方支持的方法。

    【讨论】:

    • 谢谢!也为我工作。只是一些注意事项: - 如果您使用的是 rails 4,请修改 shell 脚本以执行 bin/delayed_job 而不是 script/delayed_job; - 我必须在脚本上的 cd $EB_CONFIG_APP_CURRENT 行之后添加这个(chmod +x bin/delayed_job)。获得许可错误; - 如果您在执行脚本时收到“没有这样的文件或目录”错误,您可能需要在 .ebextensions .config 文件中添加一些行。添加 dos2unix 包安装和命令 dos2unix /opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh
    • @Marcin 如果负载均衡器后面有多个实例,这不是在每个实例中启动后台作业吗?有没有办法只在一个实例中运行后台作业?或者您打算在哪里运行此代码。后台工作者?
    • @King'oriMaina - 是的,它会在每个实例上启动作业,但是延迟作业(我假设大多数排队系统)会锁定他们正在处理的作业,因此没有重复,并且工作是分布式的。使用 EB,您可以让命令仅在“领导者”上运行,因此如果您只想在一个实例上运行,请查看。
    • @Marcin 想通了,感谢您的确认。我知道在领导者上运行,但该选项仅存在于 container_commands 而不是 EB 上的 files 配置选项。
    • 神奇的 99 编号有什么用,为什么不是 1 或 79,我们可以做 109 吗?我在几个地方看到了九十多岁,但没有人解释它!
    【解决方案2】:

    在运行 Ruby 2.1(Passenger Standalone)的 64 位 Amazon Linux 2014.09 v1.1.0 上,感谢this post,它可以正常工作。

    请注意,此脚本以 root 身份运行,但您的工作人员应以 webapp 用户身份运行。

    # Adds a post-deploy hook such that after a new version is deployed
    # successfully, restarts the delayed_job workers.
    #
    # http://stackoverflow.com/questions/14401204/how-to-automatically-restart-delayed-job-when-deploying-a-rails-project-on-amazo
    # http://www.dannemanne.com/posts/post-deployment_script_on_elastic_beanstalk_restart_delayed_job
    files:
      "/opt/elasticbeanstalk/hooks/appdeploy/post/50_restart_delayed_job.sh":
        mode: "000755"
        owner: root
        group: root
        encoding: plain
        content: |
          #!/usr/bin/env bash
    
          EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
          EB_APP_CURRENT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
          EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
          EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
          EB_APP_PIDS_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
    
          . $EB_SUPPORT_DIR/envvars
          . $EB_SCRIPT_DIR/use-app-ruby.sh
    
          cd $EB_APP_CURRENT_DIR
    
          # Switch to the webapp user.  Worker shouldn't be run as root.
          su -s /bin/bash -c "bundle exec bin/delayed_job --pid-dir=$EB_APP_PIDS_DIR restart" $EB_APP_USER
    

    【讨论】:

      【解决方案3】:

      如果有人希望在最新的 ElasticBeanstalk(运行 Ruby 2.1 (Puma) 的 64 位 Amazon Linux 2014.09 v1.0.9)中获得延迟作业:我使用以下代码让它工作(感谢 damontorgerson)。该文件位于 .ebextensions 文件夹中的 ruby​​.config 中。

      # Install git in order to be able to bundle gems from git
      packages:
      yum:
        git: []
      
      files: 
        "/opt/elasticbeanstalk/hooks/appdeploy/post/50_restart_delayed_job":
          mode: "000777"
          owner: root
          group: root
          content: |
            EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
            EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
            EB_CONFIG_APP_CURRENT=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
            EB_CONFIG_APP_LOGS=$(/opt/elasticbeanstalk/bin/get-config container -k app_log_dir)
            EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
            EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
            EB_CONFIG_APP_PIDS=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
      
            . $EB_SUPPORT_DIR/envvars
            . $EB_SCRIPT_DIR/use-app-ruby.sh
      
            cd $EB_CONFIG_APP_CURRENT
      
            . $EB_SUPPORT_DIR/envvars.d/sysenv
      
            bin/delayed_job --pid-dir=/var/tmp restart
      

      【讨论】:

        【解决方案4】:

        我的“守护进程”gem 是这样工作的:

        commands:
          create_post_dir:
            command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
            ignoreErrors: true
          webapp_pids:
            command: "mkdir /home/webapp/pids"
            ignoreErrors: true
        files:
          "/opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh":
            mode: "000755"
            owner: root
            group: root
            content: |
              #!/usr/bin/env bash
              . /opt/elasticbeanstalk/support/envvars
              chown webapp:webapp /home/webapp/pids
              su -l -c "$EB_CONFIG_APP_CURRENT/bin/delayed_job --pid-dir=/home/webapp/pids restart" $EB_CONFIG_APP_USER
              echo "worker starting" >> /var/log/directory-hooks-executor.log
        

        【讨论】:

          猜你喜欢
          • 2015-09-11
          • 2013-06-14
          • 2012-02-24
          • 2019-05-25
          • 2014-12-13
          • 2013-03-05
          • 2016-09-24
          • 2016-10-12
          • 2018-09-15
          相关资源
          最近更新 更多