套接字错误:[Errno 48] 地址已在使用中。

317
我正在尝试从Mac终端使用Python设置服务器。 我转到文件夹位置并使用以下命令:
python -m SimpleHTTPServer

但是这个会让我出错:

socket.error: [Errno 48] Address already in use

我之前使用同样的命令为我的机器上另一个位置的不同网站开启了连接。


2
结束其他进程或使用不同的端口运行此进程:python -m SimpleHTTPServer 8081 - Blender
1
这是许多情况可能引起的症状。我建议将下面的答案用作故障排除指南,而不是一组“答案”,投票代表故障排除路径的受欢迎程度。 - Gibron
相关问题:在端口没有被任何进程使用且处于TIME_WAIT状态的情况下,可以参考linux - Python [Errno 98] Address already in use - Stack Overflow。此外,还可以查看unix - How to kill a process running on particular port in Linux? - Stack Overflow以获取更多终止运行在特定端口上的进程的方法。 - undefined
16个回答

463

您已经有一个绑定在默认端口(8000)的进程。如果您之前已经运行过相同的模块,则很可能该进程仍然绑定在端口上。请先尝试找到其他进程:

$ ps -fA | grep python
  501 81651 12648   0  9:53PM ttys000    0:00.16 python -m SimpleHTTPServer

命令参数已经包括了,所以如果有多个python进程在运行,你可以找到正在运行SimpleHTTPServer的那个。你可能想要测试一下http://localhost:8000/是否仍然显示本地文件的目录列表。

第二个数字是进程号;通过发送信号停止服务器:

kill 81651

这会发送一个标准的SIGTERM信号;如果进程无响应,您可能需要采用更严厉的方法,例如发送一个SIGKILL (kill -s KILL <pid>kill -9 <pid>)信号。有关更多详细信息,请参见维基百科

或者,通过在命令行上指定替代端口来在不同的端口上运行服务器:

$ python -m SimpleHTTPServer 8910
Serving HTTP on 0.0.0.0 port 8910 ...

然后通过 http://localhost:8910 访问服务器;其中的 8910 可以是从1024开始的任何数字,只要该端口未被占用。


我应该在浏览器中输入什么网址来查看它是否工作?正如你建议的那样,我正在使用不同的端口运行。 - irm
21
也许需要使用sudo kill -9 PID命令。该命令可用于强制终止进程。请注意,执行此操作可能会导致数据丢失或其他不良影响,请谨慎使用。 - Danpe
3
谢谢,@Danpe,我尝试了“sudo kill PID”,但它没有起作用,但“sudo kill -9 PID”杀掉了进程。有人知道“-9”是什么意思吗?即使是sudo手册似乎也没有涵盖这个参数 https://www.sudo.ws/man/sudo.man.html - seokhoonlee
4
kill命令向进程发送一个信号,进程可以决定如何处理该信号(比如优雅地关闭或旋转日志文件)。这些信号是整数(每个信号都有一个名称),默认为15,意味着TERM终止。使用-9发送信号9,即KILL,进程无法捕获和忽略该信号,操作系统将结束该进程,无论它是否愿意。 - Martijn Pieters
@seokhoonlee:还可以在维基百科上查看关于Unix信号的文章。 - Martijn Pieters

299

简单解决方案:

  1. 查找正在使用端口8080的进程:
sudo lsof -i:8080
  1. 关闭该端口上的进程:
kill $PID

kill -9 $PID  //to forcefully kill the port

PID是从步骤1的输出中获得的。


17
这个答案如果有一个lsof输出结果的例子,以及如何在输出中找到进程ID(即你所列出的“XXXX”),将会更好。对于任何没有这些信息的读者来说,在输出结果中,进程ID位于标题标签为"PID"下的第二个字段。 - lindes
2
@lindes 你真是个天才! - Carlos Rodríguez
2
@CarlosRodríguez:啥?我真的不知道你在评论中想表达什么(我知道“crack”的多个定义,但我所知道的似乎都不合适……) - lindes
3
@CarlosRodríguez我想相信他认为你的回应非常到位。 我认为你对于提供lsof输出样本以及如何识别PID的观察非常重要。每行返回的第二项通常是PID,它总是在输出的PID列下。 - Kudehinbu Oluwaponle
1
@mercury,-9 是 -KILL 的缩写格式 --> 使用 kill 命令时,您可以指定某些信号,而 -KILL 或 -9 是其中之一的信号... - Ali
显示剩余3条评论

56

使用

 sudo lsof -i:5000
这将给你一个正在使用该端口的进程列表。一旦得到进程列表,使用PID列上的ID终止进程的使用。
 kill 379 #use the provided PID

1
这太完美了,特别是那些在MAC OSX上工作且没有使用_SO_REUSEPORT_而是使用_SO_REUSEADDR_的人。 - Soner from The Ottoman Empire
这个答案解决了我的问题。我之前无法访问本地主机的5000端口,出现了一个错误(该网站无法访问,本地主机拒绝连接)。 - Fatimah Mohmmed

33

在终端中键入以下命令即可轻松一行命令解决此问题:

ps -a

这将列出所有的进程,检查哪些是由Python使用的,并在终端中键入以下命令:

kill -9 (processID) 

例如 kill -9 33178


4
我在 MacOSX 上工作(我不知道这是否相关),但我必须使用“-9”参数才能使其正常工作。这是唯一提到这一点的答案。 - Ideogram

24
顺便说一下,为了防止这种情况发生,只需在SimpleHTTPServer正常运行时,在终端中按下Ctrl+C。这样会“正确地”停止服务器并释放端口,这样您就不必在重新启动服务器之前再次查找和终止进程了。

4
这里有些有用的信息,我无意中按了Ctrl+Z,使进程继续运行。按Ctrl+C可以释放端口,不需要手动杀死它。 - BcK

13

您可以使用allow_reuse_address来允许服务器重用地址。

服务器是否允许重用地址。默认为False,可以在子类中设置以更改策略。

import SimpleHTTPServer, SocketServer
PORT = 8000
httpd = SocketServer.TCPServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.allow_reuse_address = True
print "Serving at port", PORT
httpd.serve_forever()

1
属性必须在实例化之前设置在类上而不是对象/实例上:SocketServer.TCPServer.allow_reuse_address = True(来自 https://dev59.com/-GUp5IYBdhLWcg3wdXaa#15278302 )。更好的做法可能是继承TCPServer到一个新类并在那里设置该值。 - thomasa88

8
你也可以在Python中执行以下操作,服务于下一个可用的端口:

您可以执行此类操作,服务于下一个可用的端口:

import SimpleHTTPServer
import SocketServer

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

port = 8000
while True:
    try:
        httpd = SocketServer.TCPServer(('', port), Handler)
        print 'Serving on port', port
        httpd.serve_forever()
    except SocketServer.socket.error as exc:
        if exc.args[0] != 48:
            raise
        print 'Port', port, 'already in use'
        port += 1
    else:
        break

如果您需要对其他工具执行相同的操作,将其作为bash脚本可能更方便:
#!/usr/bin/env bash

MIN_PORT=${1:-1025}
MAX_PORT=${2:-65535}

(netstat -atn | awk '{printf "%s\n%s\n", $4, $4}' | grep -oE '[0-9]*$'; seq "$MIN_PORT" "$MAX_PORT") | sort -R | head -n 1

将其设置为可执行文件,命名为get-free-port,然后您可以执行以下操作:

someprogram --port=$(get-free-port)

与本机Python方法相比,这并不是很可靠,因为bash脚本无法捕获端口 - 另一个进程可能会在您的进程之前抢占端口(竞争条件) - 但仍然可能在使用没有自己的重试方式的实用程序时非常有用。


7

我刚开始学习Python,但是在我的简短调查之后,我发现这是套接字绑定的典型情况。恰好此时套接字仍在使用中,您可能需要等待才能使用它。或者,您可以添加以下内容:

tcpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

这应该可以在更短的时间内使端口变得可用。在我的情况下,它几乎立即使端口可用。


没有导入?就这样? - Nathan B

6

我的案例

当我在调试或运行服务器时,完成后,我通常不会使用 终止 进程,而是使用 断开连接

PyCharm 告诉我们,在服务器仍在运行时尝试关闭它时需要选择这两个选项。

这样做的结果是,进程仍在以该特定地址为背景运行,因此会出现 地址已在使用中 的错误。

解决方案

pkill python

可以用。

另一种情况 - 多进程

如果你有多个运行着Python的服务器/应用程序(显然在不同端口),那么就要通过PORT来获取该进程的PID,然后再用kill命令关闭它。

sudo lsof -i :5000 # here 5000 is the port number  

| COMMAND | PID    | USER     | FD | TYPE | DEVICE | SIZE/OFF | NODE | NAME                    |
|---------|--------|----------|----|------|--------|----------|------|-------------------------|
| python  | 185339 | username | 7u | IPv4 | 598745 | 0t0      | TCP  | localhost:5000 (LISTEN) |
| python  | 185348 | username | 7u | IPv4 | 598745 | 0t0      | TCP  | localhost:5000 (LISTEN) |
| python  | 185350 | username | 8u | IPv4 | 598745 | 0t0      | TCP  | localhost:5000 (LISTEN) |


kill -9 185339 # here 185339 is the PID from above output; keep the -9 as it is

请查看@Andrew的答案,以避免将来出现此问题。

参考文献:kill命令kill/pkill/killalllsof

Namaste


5

如果以上解决方案都没有奏效:

  1. 获取您的进程正在侦听的端口:

    $ ps ax | grep python

  2. 杀死该进程

    $ kill PROCESS_NAME


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