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
相关产品推荐
相关产品推荐

