Rails: 地址已在使用中 - bind(2) (Errno::EADDRINUSE)

173

我正在尝试使用 Puma Web 服务器部署 Rails 应用。当我尝试使用配置文件启动 Puma 服务器 bundle exec puma -C config/puma.rb 时,会出现一个错误,指出该地址已经在使用中。

是否有人知道如何解决这个问题?

bundle exec puma -C config/puma.rb
[23699] Puma starting in cluster mode...
[23699] * Version 2.11.3 (ruby 2.0.0-p353), codename: Intrepid Squirrel
[23699] * Min threads: 5, max threads: 5
[23699] * Environment: development
[23699] * Process workers: 2
[23699] * Preloading application
Jdbc-MySQL is only for use with JRuby
[23699] * Listening on tcp://0.0.0.0:3000
/.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:210:in `initialize': Address already in use - bind(2) (Errno::EADDRINUSE)
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:210:in `new'
    from /Users/lexi87/.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:210:in `add_tcp_listener'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:96:in `block in parse'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:82:in `each'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/binder.rb:82:in `parse'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/runner.rb:119:in `load_and_bind'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/cluster.rb:302:in `run'
    from /.rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/lib/puma/cli.rb:216:in `run'
    from /rvm/gems/ruby-2.0.0-p353/gems/puma-2.11.3/bin/puma:10:in `<top (required)>'
    from /.rvm/gems/ruby-2.0.0-p353/bin/puma:23:in `load'
    from /.rvm/gems/ruby-2.0.0-p353/bin/puma:23:in `<main>'
    from /.rvm/gems/ruby-2.0.0-p353/bin/ruby_executable_hooks:15:in `eval'
    from /.rvm/gems/ruby-2.0.0-p353/bin/ruby_executable_hooks:15:in `<main>'

1
有人已经在使用端口3000了。使用netstat命令来查找谁在使用端口3000。 - Mircea
5
当我试图终止它时,出现错误kill -59780 PID,提示“无效的信号规范”。我使用了lsof -wni tcp:3000命令来显示哪个进程正在使用端口3000。 - Cornelius Wilson
1
杀掉 -9 59780(通常用“杀掉 -9 pid_id”) - Mircea
您可以考虑查看我在相关问答中的回答(https://dev59.com/vpPfa4cB1Zd3GeqPGrX_#75231668),在那里我还指向了[111](https://dev59.com/BLD2oIgBc1ULPQZF-AdF)[222](https://dev59.com/5aXja4cB1Zd3GeqPMBqC)[333](https://dev59.com/WV8e5IYBdhLWcg3w_-hM)。 - Cadoiz
11个回答

353

你需要使用kill -9 59780命令,将59780替换为找到的PID号(使用lsof -wni tcp:3000查看哪个进程使用了3000端口并获取其进程PID)。

或者你可以修改你的Puma配置,将TCP端口tcp://127.0.0.1:3000中的3000改为未被占用的9292或其他端口。

或者你可以通过以下方式启动Rails应用:

bundle exec puma -C config/puma.rb -b tcp://127.0.0.1:3001

1
谢谢您的回答。我遇到了与 OP 相同的错误。后来我意识到我已经在另一个终端中使用了 rails s 命令。这就是为什么我会收到那个错误信息。然后我使用了不同的端口启动服务器 rails s -p 9090 - Fai Zal Dong

188

要杀死Puma进程,请先运行

lsof -wni tcp:3000 

展示使用端口3000的程序。然后使用给定的PID来终止该进程。

例如,运行 lsof -wni tcp:3000 命令后,可能会得到如下结果:

COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby    3366 dummy    8u  IPv4  16901      0t0  TCP 127.0.0.1:3000 (LISTEN)

现在运行以下命令来终止进程(其中3366为PID)。

kill -9 3366

应该解决问题


谢谢@sawo-cliff,它解决了我的问题。我有另一个应用程序在3000端口上运行。 - Nomis
3
这个回答比一年前被接受的回答多提供了哪些信息? - Andre Figueiredo
1
@AndreFigueiredo,不太确定我理解你的问题,但从中我能了解到的一点是,我的回答增加了如何知道哪个进程ID正在运行以便知道要终止哪个进程。 - Sawo Cliff
是的。我现在可以看到原始答案确实包含相同的信息。但直到我读了这个版本,我才完全明白我需要做什么。 - Jeff Zivkovic

47

你也可以尝试这个技巧:

ps aux | grep puma

样例输出:

myname           77921   0.0  0.0  2433828   1972 s000  R+   11:17AM   0:00.00 grep puma
myname           67661   0.0  2.3  2680504 191204 s002  S+   11:00AM   0:18.38 puma 3.11.2 (tcp://localhost:3000) [my_proj]

那么:

kill -9 67661

1
如果 kill 67661 并不能真正杀死进程(如上面的示例),请使用 kill -9 67661。这对我很有效!干杯! - Kyle Krzeski

6

在此Github问题中找到下面的脚本,对于我来说效果非常好。

#!/usr/bin/env ruby
port = ARGV.first || 3000
system("sudo echo kill-server-on #{port}")

pid = `sudo lsof -iTCP -sTCP:LISTEN -n -P | grep #{port} | awk '{ print $2 }' | head -n 1`.strip
puts "PID: #{pid}"
`kill -9 #{pid}` unless pid.empty?

你可以在irb中运行它,也可以在ruby文件中运行它。
对于后者,请创建server_killer.rb文件,然后使用ruby server_killer.rb运行它。

这对我有用,谢谢你。但是我去掉了sudo,因为似乎不需要它。 - Obromios

3

解决“Address already in use - bind(2) (Errno::EADDRINUSE)”问题

出现这个问题是因为我们尝试使用已经被占用的端口。所以我们需要停止正在运行在该端口上的服务,才能运行其他服务。 我们可以使用kill命令,例如kill -9 {PID}其中{PID}是正在运行在该端口上的服务的PID。要知道任何服务的PID,比如说“firefox”,我们可以使用以下命令:pidof firefoxps aux | grep -i firefoxpgrep firefox然后使用kill命令停止该服务。

有时候我们可能会遇到不知道要搜索的PID或服务名称的情况,在这种情况下,我们可以使用以下简短的ruby代码来帮助我们找到它们。(在本例中是端口3000,您可以根据需要更改)

#!/usr/bin/env ruby
port = ARGV.first || 3000
system("sudo echo kill-server-on #{port}")

pid = `sudo lsof -iTCP -sTCP:LISTEN -n -P | grep #{port} | awk '{ print $2 }' | head -n 1`.strip
puts "PID: #{pid}"
`kill -9 #{pid}` unless pid.empty?

将其保存为something.rb并运行sudo ruby something.rb


2
如果上述解决方案在Ubuntu/Linux上无效,您可以尝试这个。
sudo fuser -k -n tcp port

运行几次以关闭您选择的端口上的进程。例如,端口可以是3000。如果在运行命令后没有看到任何输出,则表示您已经杀死了所有进程。


1
您可以找到并结束正在运行的进程:ps aux | grep puma 然后您可以使用kill PID来结束它。

0
对我来说,我之前有一个挂起的ruby进程,来自于之前的rails/puma实例,我也在这个相关的问题/答案中回答过。简而言之:只需要执行killall ruby -9命令即可。
这应该比这个更一般的答案更容易解决。我可以先检查一下是否适用:
$ lsof -wni tcp:3000 # To know the process that blocks the port, returns:
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby    10660 simon    8u  IPv4  67071      0t0  TCP *:3000 (LISTEN)
ruby    10672 simon    8u  IPv4  67071      0t0  TCP *:3000 (LISTEN)
ruby    10684 simon    8u  IPv4  67071      0t0  TCP *:3000 (LISTEN)

0

我在我的Macbook Air上遇到了这个问题,运行的是Rails 5.0.3和Puma 5.2.2。

尝试运行lsof -wni tcp:3000,但是在这个端口号上没有进程。

通过运行以下命令成功解决了这个问题:

export PORT=3000 在我的终端上,然后我只需将此额外行添加到我的.bash_profile中即可。


我知道这是一个较旧的帖子,但我目前正在更新一个较旧的Rails应用程序,并在遇到原始帖子中的问题后找到了这个答案。这个方法确实有效,但我并不真正理解为什么会这样。你能否对此进行进一步解释?与此同时,我将继续深入研究,并在找到更多信息时更新这个评论。 - E Newmy

0
只需简单地打开 tmp/pids/server.pid,你会找到 pid,例如 -> 42345,只需输入 kill -9 42345。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接