【问题标题】:Sidekiq process on Elastic Beanstalk - Errno::ENOENT: No such file or directory - getcwdElastic Beanstalk 上的 Sidekiq 进程 - Errno::ENOENT:没有这样的文件或目录 - getcwd
【发布时间】:2026-01-29 18:25:01
【问题描述】:

我们正在使用 rest-client 在 Sidekiq 工作人员上发送外部 API 请求,这些工作人员在我们的 Elastic Beanstalk 管理的 EC2 实例上启动 as a process

Dir.home 失败时,rest-client 使用 netrc 和 netrc calls Dir.pwd。我们偶尔会看到此错误:

Errno::ENOENT: No such file or directory - getcwd
[GEM_ROOT]/gems/netrc-0.10.3/lib/netrc.rb:26 :in `pwd`

这表明ENV['HOME']没有设置,显然当前目录不再存在。通常,HOME 已在 EB 实例上设置,我们已尝试通过 eb setenv 设置它以确保安全。

问题是这种情况如何在 EB 上出现,以及我们将来如何避免这种情况。我犹豫不决,但也许我们没有在部署之间正确杀死 Sidekiq 进程,并且旧的 sidekiq 进程仍然存在,引用旧目录?我对EB还不是很熟悉;任何指导将不胜感激。

【问题讨论】:

    标签: ruby-on-rails amazon-web-services amazon-ec2 sidekiq amazon-elastic-beanstalk


    【解决方案1】:

    正如问题和一些答案所预示的,这是一个避免终止的流氓进程,在这种情况下,由于我们早期部署中的一个粗心的配置更改。我们sidekiq.config的第30行控制了进程的数量,我们从2降到1但是没有在改动后手动从服务器中移除第二个进程。

    这个故事的寓意是,Sidekiq 进程不仅在部署期间容易受到意外行为的影响。即使没有在多个部署中停止/启动,我们的错误进程也很高兴地完成了工作,但是任何依赖于 Dir.pwd 的任何脚本以及可能需要 ENV 数据的任何其他脚本都会在稳定部署后失败在持久化进程上运行。

    如果您看到此类故障,请绝对肯定您之前的部署中没有运行意外进程。这意味着确保它们在部署期间被正确终止as @JeffD23 mentioned,但同时还要确保您没有从过去的部署中挂起。

    【讨论】:

    • 我也有同样的问题。我已经怀疑这是原因,但我无法得到最终的解决方案。也许我可以根据您共享的 sidekiq.config 解决这个问题。谢谢。
    【解决方案2】:

    我认为sidekiq api 可能会帮助您调试它。

    首先,从 beanstalk 进入 rails 控制台:/var/app/current run RAILS_ENV=production bundle exec rails c 然后 require 'sidekiq/api'

    如果您运行Sidekiq::Queue.new,它将返回您排队的作业或Sidekiq::RetrySet.new 用于计划重试的作业。如果您在上次部署之前有旧作业排队,那应该证实您对引用已删除目录的怀疑。

    要安全关闭 Sidekiq,您需要向其发送 USR1 信号 在您的部署过程中尽可能早地发出 TERM 信号 尽可能。 USR1 告诉 Sidekiq 停止拉新工作并完成 当前的所有工作。 TERM 告诉 Sidekiq 在 N 秒内退出,其中 N 由 -t timeout 选项设置,默认为 8。使用 USR1+TERM 在 您的部署过程为您的工作提供了最大的时间 在退出之前完成。

    您可以通过设置 sidekiq 工作人员只尝试一次然后死掉来避免这种情况。否则,您的工作人员将持续失败 25 次重试或 21 天。

    class NonRetryableWorker
      include Sidekiq::Worker
      sidekiq_options retry: false
      # your perform method
    end
    

    您还可以设置sidekiq_options retry: 5 或任何其他整数来明确设置重试次数。

    如果您使用 capistrano 进行部署,则可以使用 capistrano-sidekiq gem 管理部署之间的作业

    【讨论】:

    • 有趣,所以在一次部署中排队或失败意味着它将在下一次部署中失败,就像它以某种方式记住它的上下文一样?如果属实,这似乎是不可取的,想知道是否有解决方法。没有通过 sidekiq api 显示任何排队的作业 atm,但我肯定会进一步调查
    • 实际上我们在 Sidekiq::RetrySet 中有一些。感觉这可能是问题
    • 听起来就是这样。我使用 sidekiq 部署文档中解释问题的一些附加信息更新了答案。
    • 因此,除非我误解了这里的理论,否则作业要么记住它们的失败上下文,并且您不能在另一个部署中运行从一个部署排队的作业(即not true)。或者 Sidekiq 没有通过 USR1/TERM 序列正确关闭,但是我们只会在部署期间看到此故障(事实并非如此,我在 10 分钟前才看到一个,而且我们已经好几天没有部署了)。
    • 作业不记得失败的上下文,问题似乎与使用旧环境配置运行的部署序列有关。如果您运行 Sidekiq::RetrySet.new.map { |x|,您会收到什么样的错误消息? x.item["error_message"] }
    【解决方案3】:

    我无法运行您的sidekiq.conf0010_sidekiq.config(最接近您的配置)。我也不确定您第一次如何配置 sidekiq,也许您可​​以提供有关您的 .ebextensions 和配置的更多详细信息。当我尝试使用你的配置时,我得到which sidekiq line is error:

    /var/log/eb-activity.log

    ...
    
      ++ which bundle
      + BUNDLE=/opt/rubies/ruby-2.2.2/bin/bundle
      ++ which sidekiq
      which: no sidekiq in (/opt/rubies/ruby-2.2.2/bin:/opt/elasticbeanstalk/lib/ruby/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin)
      + SIDEKIQ= (Executor::NonZeroExitStatus)
    
    
    [2015-09-08T15:24:52.326Z] INFO  [4963]  - [Application update/AppDeployStage1/AppDeployPostHook/50_restart_sidekiq.sh] : Activity failed.
    [2015-09-08T15:24:52.327Z] INFO  [4963]  - [Application update/AppDeployStage1/AppDeployPostHook] : Activity failed.
    [2015-09-08T15:24:52.327Z] INFO  [4963]  - [Application update/AppDeployStage1] : Activity failed.
    [2015-09-08T15:24:52.327Z] INFO  [4963]  - [Application update] : Completed activity. Result:
      Application update - Command CMD-AppDeploy failed
    

    但是,我正在使用另一个.ebextensionshttps://github.com/jolks/ebextensions(注意:不要忘记将RAILS_ENV 设置为您的EB 环境变量)。它运行正常。基本上,.ebextensions 会在您的应用刚刚部署后尝试重新启动 sidekiq。

    【讨论】:

    • 根据您的回复不确定该去哪里...我们的 sidekiq 配置在大多数情况下似乎都可以正常工作;看起来你没有运行 bundle 或其他东西,因为 which sidekiq 如果安装不应该失败并且我们没有这个问题。我们的RAILS_ENV 设置正确。
    • 能否提供与sidekiq相关的.ebextensions
    • 这就是this,你已经在引用它了。我们没有其他与 sidekiq 相关的配置文件
    • 当你运行bundle install安装sidekiq?
    【解决方案4】:

    我在你描述的场景中遇到了这个错误:

    我们的一些后台工作人员未能停止部署,然后 capistrano 开始删除旧部署的目录。如果在旧(现已删除)目录之一中启动的工作人员仍然存在,那么您观察到的错误开始发生......

    解决方案显然是确保在部署时正确终止您的旧进程......不幸的是我既不使用 EB 也不使用 Sidekiq 所以我不能帮您解决具体问题...

    【讨论】:

    • 嗯,很高兴知道这不是一个新问题:)。听起来这支持了我最初的猜测,现在来追查为什么这些进程没有被终止......
    最近更新 更多