You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails/Puma通过Systemd服务启动时无法读取环境变量

解决Systemd启动Puma时无法读取Rails环境变量的问题

这个问题我之前帮不少开发者排查过,核心原因很明确:Systemd启动的服务进程默认不会继承你登录shell里的环境变量——毕竟它是脱离用户会话独立启动的,不像你直接在命令行跑bundle exec puma那样能拿到.bashrc/.profile里的配置。下面给你几个靠谱的解决办法,按推荐优先级排序:

1. 直接在Systemd服务文件中定义环境变量

这是最稳妥、最符合Systemd设计规范的方案,把环境变量直接写进服务配置里,避免依赖用户shell的配置。

  • 编辑你的Puma服务文件(通常是/etc/systemd/system/puma.service)
  • 在[Service]段落里添加环境变量配置:
    [Service]
    User=deploy
    Group=deploy
    WorkingDirectory=/home/deploy/current
    
    # 方式1:单个变量逐一定义
    Environment=RAILS_ENV=production
    Environment=DATABASE_URL=postgres://db_user:db_pass@localhost/your_db
    Environment=SECRET_KEY_BASE=your_rails_secret_key
    
    # 方式2:用文件批量加载(推荐,方便管理)
    # 先创建一个环境变量文件,比如 /home/deploy/shared/config/env_vars,每行格式为 KEY=VALUE
    EnvironmentFile=/home/deploy/shared/config/env_vars
    
    ExecStart=/home/deploy/.rbenv/shims/bundle exec puma -e production -C /home/deploy/shared/config/puma.rb
    
  • 给环境变量文件设置安全权限,防止敏感信息泄露:sudo chmod 600 /home/deploy/shared/config/env_vars
  • 重新加载Systemd配置并重启服务:
    sudo systemctl daemon-reload
    sudo systemctl restart puma
    

2. 让Systemd加载用户的shell环境变量

如果你的环境变量已经存在于.bashrc或.profile中,不想重复定义,可以让Systemd在启动时加载这些配置:

  • 修改服务文件的[Service]段落:
    [Service]
    User=deploy
    Group=deploy
    Environment="HOME=/home/deploy"
    # 先加载用户的bash配置,导出到临时文件
    ExecStartPre=/bin/bash -c 'source /home/deploy/.profile && export > /tmp/puma_env'
    # 再读取临时文件的环境变量启动Puma
    ExecStart=/bin/bash -c 'source /tmp/puma_env && bundle exec puma -e production -C /home/deploy/shared/config/puma.rb'
    
  • 注意:.bashrc默认只针对交互式shell加载,所以推荐把环境变量放在.profile里,或者修改.bashrc去掉非交互式shell的判断逻辑。

3. 让Puma主动加载环境变量文件

如果不想碰Systemd配置,也可以在Puma的配置文件里直接读取环境变量文件,不管启动方式是什么都能生效:

  • 在/home/deploy/shared/config/puma.rb开头添加以下代码:
    # 加载自定义环境变量文件
    env_file = '/home/deploy/shared/config/env_vars'
    if File.exist?(env_file)
      File.read(env_file).split("\n").each do |line|
        next if line.empty? || line.start_with?('#') # 跳过空行和注释
        key, value = line.split('=', 2)
        ENV[key.strip] = value.strip unless key.nil? || value.nil?
      end
    end
    
  • 这样不管是命令行启动还是Systemd启动,Puma都会自己加载这个文件里的变量。

验证方法

配置完成后,可以用以下命令检查环境变量是否正确加载:

# 查看Systemd服务的环境变量
systemctl show puma | grep Environment

# 查看Puma进程的环境变量(替换成你的Puma进程ID)
cat /proc/<puma_pid>/environ | tr '\0' '\n'

内容的提问来源于stack exchange,提问作者learning_to_swim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:23:58