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

本地启动不同端口Puma实例时遭遇Address already in use错误求助

问题:启动两个Hanami Puma实例时端口9293地址占用报错

我在开发机上启动两个基于Hanami的Puma服务实例(一个API、一个Web应用),API服务能正常启动,但Web应用启动失败,报错:Address already in use - bind(2) for "127.0.0.1" port 9293。

API应用启动日志

jignesh@jignesh-Latitude-7290:~/hanami_projects/my_api_app$ bundle exec hanami server --port=2400
13:59:36 - INFO - Using Guardfile at /......./my_api_app/Guardfile.
13:59:36 - INFO - Puma starting on port 2400 in development environment.
13:59:36 - INFO - Guard is now watching at '/......./my_api_app'
[15170] Puma starting in cluster mode...
[15170] * Puma version: 6.2.1 (ruby 3.1.2-p20) ("Speaking of Now")
[15170] *  Min threads: 5
[15170] *  Max threads: 5
[15170] *  Environment: development
[15170] *   Master PID: 15170
[15170] *      Workers: 2
[15170] *     Restarts: (✔) hot (✖) phased
[15170] * Preloading application
[15170] * Listening on http://0.0.0.0:2400
[15170] Use Ctrl-C to stop
[15170] * Starting control server on http://127.0.0.1:9293
[15170] * Starting control server on http://[::1]:9293
[15170] - Worker 0 (PID: 15177) booted in 0.0s, phase: 0
[15170] - Worker 1 (PID: 15179) booted in 0.0s, phase: 0
[15170] ! Terminating timed out worker (worker failed to check in within 60 seconds): 15177
[15170] - Worker 0 (PID: 25100) booted in 0.0s, phase: 0

Web应用启动日志

jignesh@jignesh-Latitude-7290:~/hanami_projects/my_web_app$ bundle exec hanami server
15:32:31 - INFO - Using Guardfile at /......./my_web_app/Guardfile.
15:32:32 - INFO - Puma starting on port 2300 in development environment.
15:32:32 - INFO - Guard is now watching at '/......./my_web_app'
[25763] Puma starting in cluster mode...
[25763] * Puma version: 6.2.2 (ruby 3.1.2-p20) ("Speaking of Now")
[25763] *  Min threads: 5
[25763] *  Max threads: 5
[25763] *  Environment: development
[25763] *   Master PID: 25763
[25763] *      Workers: 2
[25763] *     Restarts: (✔) hot (✖) phased
[25763] * Preloading application
[25763] * Listening on http://127.0.0.1:2300
[25763] Use Ctrl-C to stop
/home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `initialize': Address already in use - bind(2) for "127.0.0.1" port 9293 (Errno::EADDRINUSE)
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `new'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `add_tcp_listener'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:329:in `block in add_tcp_listener'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `each'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `add_tcp_listener'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:164:in `block in parse'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `each'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `parse'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/runner.rb:78:in `start_control'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cluster.rb:410:in `run'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/launcher.rb:194:in `run'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cli.rb:75:in `run'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/bin/puma:10:in `<top (required)>'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `load'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `<main>'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `eval'
    from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `<main>'

通用Puma配置文件(两个应用相同)

# frozen_string_literal: true

max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5)
min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

port        ENV.fetch("HANAMI_PORT", 2300)
environment ENV.fetch("HANAMI_ENV", "development")
workers     ENV.fetch("HANAMI_WEB_CONCURRENCY", 2)

on_worker_boot do
  Hanami.shutdown
end

preload_app!

已尝试的无效操作

修改Web应用的my_web_app/config/puma.rb,将port配置替换为bind:

#port        ENV.fetch("HANAMI_PORT", 2300)
bind        "tcp://127.0.0.1:2300"

/etc/hosts内容

127.0.0.1   localhost
127.0.1.1   jignesh-Latitude-7290
127.0.0.1 api.some_api.local

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

解决方案

问题出在Puma的控制服务器端口上,不是应用服务端口。从API日志能看到,Puma集群模式下会默认启动控制服务器监听127.0.0.1:9293,两个实例都用这个默认端口就会冲突。

解决方法是给每个应用指定不同的控制服务器端口,有两种方式:

方式1:修改Puma配置文件

在Web应用的config/puma.rb中添加control_url和control_auth_token配置,指定专属端口:

# frozen_string_literal: true

max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5)
min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

port        ENV.fetch("HANAMI_PORT", 2300)
environment ENV.fetch("HANAMI_ENV", "development")
workers     ENV.fetch("HANAMI_WEB_CONCURRENCY", 2)

# 添加控制服务器配置,指定不同端口
control_url "tcp://127.0.0.1:9294"
control_auth_token "your_unique_token_here" # 可选,但建议添加,避免未授权访问

on_worker_boot do
  Hanami.shutdown
end

preload_app!

API应用也可以修改控制端口,或者保持默认9293,只要两个端口不重复即可。

方式2:启动时通过命令行参数指定

启动Web应用时,加上--control-url参数:

bundle exec hanami server --control-url tcp://127.0.0.1:9294

验证方法

启动Web应用后,检查端口占用情况:

lsof -i :9294

如果能看到Puma进程监听该端口,说明配置生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:38:08