Ubuntu
帶有 systemd 和套接字啟動的 Puma - Errno::EADDRINUSE
我有一個 Rails 5 應用程序,在 puma 3.12.1、MRI 2.6.2 和 Ubuntu 18.04 上執行。它曾經使用
pumactl
自定義控制腳本執行,但我想使用 systemd 正確配置它,使用套接字啟動來進行零停機部署。問題是套接字持有埠,而 puma 想要綁定在同一個埠上,所以它給出了這個錯誤:
/opt/myapp/shared/vendor/ruby/2.6.0/gems/puma-3.12.1/lib/puma/binder.rb:273:in `initialize': Address already in use - bind(2) for "0.0.0.0" port 3000 (Errno::EADDRINUSE)
我根據puma docs和systemd docs設置了一切。
我當然重新載入了 systemd 配置並嘗試重新啟動幾次。我不太了解 systemd 是如何啟動此套接字的,但對我來說 puma 的錯誤消息似乎是合理的:/
也許 puma 不應該嘗試綁定該埠?但是我怎樣才能與 puma 通信而不綁定它但使用 systemd 的轉發流?
我的配置:
$ cat /etc/systemd/system/puma.socket [Unit] Description=Puma HTTP Server Accept Sockets [Socket] ListenStream=0.0.0.0:3000 # Socket options matching Puma defaults NoDelay=true ReusePort=true Backlog=1024 [Install] WantedBy=sockets.target
$ cat /etc/systemd/system/puma.service [Unit] Description=API with Puma server After=network.target Requires=puma.socket [Service] Type=simple WorkingDirectory=/opt/myapp/current ExecStart=/opt/myapp/current/script/bootup_puma SyslogIdentifier=api-puma PIDFile=/opt/myapp/current/tmp/pids/puma.pid Restart=no TimeoutSec=30 User=ubuntu [Install] WantedBy=multi-user.target
$ cat script/bootup_puma #!/bin/bash # [setting up some envvars here] bundle exec puma -C config/puma.rb
$ cat config/puma.rb # frozen_string_literal: true app_dir = File.expand_path("..", __dir__) workers ENV.fetch("API__PUMA_WORKERS", 4).to_i threads 1, ENV.fetch("RAILS_MAX_THREADS", 8).to_i bind "tcp://0.0.0.0:#{ENV.fetch('PORT', 3000)}" pidfile "#{app_dir}/tmp/pids/puma.pid" directory ENV.fetch("API__PUMA_DIRECTORY") unless ENV.fetch("RAILS_ENV", "development") == "development"
作為一個絕望的嘗試,我還嘗試使用 unix 套接字而不是 TCP,但儘管我小心不要通過符號連結引用套接字,但最終還是出現了類似的錯誤。
/opt/myapp/shared/vendor/ruby/2.6.0/gems/puma-3.12.1/lib/puma/binder.rb:367:in `add_unix_listener': There is already a server bound to: /opt/myapp/shared/tmp/puma.sock (RuntimeError)
我已經瀏覽過的其他有用資源:
問題在於 Micheal Hampton 在評論
bootup_puma
中指出的中間 shell 腳本。將服務更改為 指令
ExecStart=/opt/myapp/current/bin/puma -C config/puma.rb
並為環境提供EnvironmentFile
指令解決了該問題。