【问题标题】:Upstart task generated by foreman doesn't find file?工头生成的新贵任务找不到文件?
【发布时间】:2026-01-23 22:00:02
【问题描述】:

我使用 foreman 将我的 Procfile 导出到一个新贵任务。

过程文件:

web: bundle exec rails server
websocket: bundle exec rails runner websocket-server/em_websocket.rb

其中一个新贵任务(它们非常相似,并且因相同的错误而失败):

start on starting app-web
stop on stopping app-web
respawn

env PORT=5000

setuid app

chdir /var/www/app

exec bundle exec rails server

还有错误(我是通过 dmesg 得到的):

[35207.676836] init: Failed to spawn app-websocket-1 main process: unable to execute: No such file or directory
[35207.679577] init: Failed to spawn app-web-1 main process: unable to execute: No such file or directory

当我切换到应用用户时,我实际上可以从给定目录运行bundle exec rails server

有什么方法可以进一步确定错误吗?我在/var/log/upstart/没有找到任何相关的日志。

【问题讨论】:

    标签: ruby-on-rails upstart foreman


    【解决方案1】:

    如果您通过 RVM 安装 ruby​​,则可能会在 rvm 脚本运行之前运行 init。您是否尝试过使用对捆绑箱的绝对引用?

    whereis bundle 
    

    获得它

    RVM 显然未初始化或在新贵环境中不可用。幸运的是 rvm 有这种情况的包装器:https://rvm.io/integration/init-d

    【讨论】:

    • 它只返回bundle: 。我知道这应该如何影响在启动时运行任务,但是当我在系统运行时启动它时,这应该没有什么不同,对吧?
    • 如果暴发户运行一个新的控制台就不行...尝试使用:bash -c 'bundle exec rails server' 在你的 Procfile 中
    • 好的,我用 bash -c 试过了。当我使用工头运行 Procfile 时,它​​工作正常,但是当我启动服务时,我收到以下错误:“以状态 127 终止”,这显然意味着找不到命令。
    • 这可能是一个愚蠢的尝试,但请检查您仅使用 rails serverbash -c 'rails server' 得到的结果
    • 奇怪,和以前一样的错误。有没有办法进入新贵运行这些任务的相同环境?所以我可以弄清楚什么是可用的,什么是不可用的?顺便说一句,感谢您的帮助:)
    【解决方案2】:

    您可以通过其他方式运行 bundle。 而不是:

    web: bundle exec rails server
    

    你需要运行:

    web: bash -c '~/.rvm/bin/rvm default do bundle exec rails server'
    

    注意:~/.rvm/bin/rvm - 可以替换为服务器上 rvm 安装的实际路径。

    【讨论】:

      【解决方案3】:

      Upstart 命令需要底层用户的 sudo 权限。您是否考虑过为您的应用程序用户定义某种形式的无密码 sudo 权限来运行 rails 应用程序服务重启?

      例如,在 Ubuntu 中,在 /etc/sudoers.d/ 下创建一个新的 sudoer 定义?

      username ALL=(ALL) NOPASSWD:ALL
      

      一旦定义了“用户名”,应该能够通过 sudo service 'appname' stop|start|restart 运行 rails 应用程序。

      这里是为用户提供 sudo 权限的解释。我的 Capistrano 部署包含如下的工头导出定义 -

      namespace :foreman do
       desc 'Export the Procfile to Ubuntu upstart scripts'
       task :export do
         on roles(:app) do |host|
          log_path = shared_path.join('log')
          within release_path do
            execute :mv, ".env .envbkup"
            execute :echo, "'RACK_ENV=#{fetch(:deploy_env)}' >> .env"
            execute :echo, "'RAILS_ENV=#{fetch(:deploy_env)}' >> .env"
            execute :bundle, "exec foreman export upstart #{shared_path}/init -a #{fetch(:application)} -u #{host.user} -l #{log_path}"
            execute :rm, ".env"
            execute :mv, ".envbkup .env"
            as :root do
              execute :cp, "#{shared_path}/init/* /etc/init/"
            end
        end
       end
      end
      

      此 capistrano 定义是从 deploy_env.rb 'after' 操作调用的。

      【讨论】:

      • 注意到我的评论被否决了。我很想知道为什么。希望得到有关此解决方案不可接受的原因的反馈。谢谢。