socket.error: [Errno 48] Địa chỉ đã được sử dụng


224

Tôi đang cố gắng thiết lập một máy chủ với python từ thiết bị đầu cuối mac.

Tôi điều hướng đến vị trí thư mục sử dụng:

python -m SimpleHTTPServer

Nhưng điều này cho tôi lỗi:

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

Trước đây tôi đã mở một kết nối bằng cách sử dụng cùng một lệnh cho một trang web khác ở một vị trí khác trong máy của tôi.


2
Giết quá trình khác hoặc chạy quy trình này với một cổng khác:python -m SimpleHTTPServer 8081
Blender

Câu trả lời:


356

Bạn đã có một quy trình ràng buộc với cổng mặc định (8000). Nếu bạn đã chạy cùng một mô-đun trước đó, rất có thể quá trình đó vẫn bị ràng buộc với cổng. Hãy thử và xác định quá trình khác trước:

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

Các đối số lệnh được bao gồm, vì vậy bạn có thể phát hiện ra một đối tượng đang chạy SimpleHTTPServernếu có nhiều hơn một pythonquy trình được kích hoạt. Bạn có thể muốn kiểm tra nếuhttp://localhost:8000/ vẫn hiển thị danh sách thư mục cho các tệp cục bộ.

Số thứ hai là số quy trình; dừng máy chủ bằng cách gửi tín hiệu:

kill 81651

Điều này sẽ gửi một SIGTERMtín hiệu tiêu chuẩn ; nếu quá trình không phản hồi, bạn có thể phải sử dụng các phương pháp khó hơn như gửi tín hiệu SIGKILL( kill -s KILL <pid>hoặc kill -9 <pid>) thay thế. Xem Wikipedia để biết thêm chi tiết .

Hoặc, chạy máy chủ trên một cổng khác , bằng cách chỉ định cổng thay thế trên dòng lệnh:

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

sau đó truy cập máy chủ như http://localhost:8910; nơi 8910có thể là bất kỳ số nào từ 1024 trở lên, miễn là cổng chưa được lấy.


Tôi nên có url nào trong trình duyệt để xem nó có hoạt động không? Tôi đang chạy trên một cổng khác khi bạn bị chặn đường
irm

14
có thể cần sử dụngsudo kill -9 PID
Danpe

Cảm ơn, @Danpe, tôi đã thử "sudo kill PID" nhưng nó không hoạt động nhưng "sudo kill -9 PID" đã giết quá trình. Bất cứ ai cũng biết những gì -9 chỉ định? Ngay cả hướng dẫn sử dụng sudo dường như không bao gồm tham số này sudo.ws/man/sudo.man.html
seokhoonlee 17/03/2016

3
@seokhoonlee: killgửi tín hiệu đến tiến trình, nó có thể quyết định xử lý (như tắt một cách duyên dáng hoặc xoay logfile). Các tín hiệu này là các số nguyên (mỗi số có một tên), mặc định là 15, có nghĩa là TERMhoặc chấm dứt . Sử dụng -9 sẽ gửi tín hiệu 9, KILLmột quá trình không thể bắt và bỏ qua, và HĐH sẽ kết thúc quá trình mà nó thích hay không.
Martijn Pieters

@seokhoonlee: cũng xem bài viết về tín hiệu Unix trên Wikipedia.
Martijn Pieters

153

Giải pháp đơn giản

  1. Tìm quy trình sử dụng cổng 8080:

    sudo lsof -i:8080

  2. Giết nó:

    kill XXXX


8
Câu trả lời này sẽ được hưởng lợi từ một ví dụ về hình thức lsofđầu ra có thể trông như thế nào và cách tìm ID tiến trình ("XXXX" mà bạn liệt kê) trong đầu ra. Đối với bất kỳ ai nhìn thấy thông tin này mà không có thông tin đó, đó là trường thứ hai trong đầu ra, dưới nhãn tiêu đề của "PID".
lindes

2
@lindes Bạn là một vết nứt!
Carlos Rodríguez

@ CarlosRodríguez: hả? Tôi thực sự không biết những gì bạn có nghĩa là bằng cách bình luận rằng (Tôi biết nhiều định nghĩa về "vết nứt", và những cái tôi biết dường như không phù hợp ...)
lindes

2
@ CarlosRodríguez Tôi muốn tin rằng anh ấy đã tìm thấy phản hồi của bạn hoàn toàn đúng đắn. Tôi nghĩ rằng quan sát của bạn về sự cần thiết phải đưa ra các mẫu đầu ra của lsof và cách xác định PID là rất quan trọng. Mục thứ hai trong mỗi hàng được trả về thường là PID, nó luôn nằm dưới cột PID của đầu ra
Kudehinbu Oluwaponle

32

Sử dụng

 sudo lsof -i:5000

Điều này sẽ cung cấp cho bạn một danh sách các quy trình sử dụng cổng nếu có. Khi danh sách các quy trình được đưa ra, hãy sử dụng id trên cột PID để chấm dứt quá trình sử dụng

 kill 379 #use the provided PID

Điều đó thật hoàn hảo, đặc biệt là những người làm việc trên MAC OSX và không sử dụng SO_REUSEPORT thay vì SO_REUSEADDR
snr

16

Nhân tiện, để ngăn điều này xảy ra ngay từ đầu, chỉ cần nhấn Ctrl+C trong terminal trong khi SimpleHTTPServer vẫn chạy bình thường. Điều này sẽ "dừng" đúng cách máy chủ và giải phóng cổng để bạn không phải tìm và hủy quá trình lại trước khi khởi động lại máy chủ.

(Mods: Tôi đã cố gắng đưa nhận xét này vào câu trả lời tốt nhất nơi nó thuộc về, nhưng tôi không có đủ danh tiếng.)


12

Lệnh một dòng đơn giản để thoát khỏi nó, gõ lệnh bên dưới trong terminal,

ps -a

Điều này sẽ liệt kê tất cả quá trình, kiểm tra đang được Python sử dụng và gõ lệnh dưới đây trong terminal,

kill -9 (processID) 

Ví dụ: giết -9 33178


7

Bạn cũng có thể phục vụ trên cổng có sẵn cao nhất tiếp theo đang làm một cái gì đó như thế này trong 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

Nếu bạn cần làm điều tương tự cho các tiện ích khác, nó có thể thuận tiện hơn như một tập lệnh 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

Thiết lập nó dưới dạng thực thi với tên get-free-portvà bạn có thể làm một cái gì đó như thế này:

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

Điều đó không đáng tin cậy như cách tiếp cận Python nguyên bản vì tập lệnh bash không chiếm được cổng - một quy trình khác có thể lấy cổng trước khi quy trình của bạn thực hiện (điều kiện cuộc đua) - nhưng vẫn có thể đủ hữu ích khi sử dụng tiện ích không ' t có một cách tiếp cận thử lại của riêng mình.


6

Tôi chưa quen với Python, nhưng sau nghiên cứu ngắn gọn của tôi, tôi phát hiện ra rằng đây là điển hình của các socket bị ràng buộc. Nó chỉ xảy ra rằng ổ cắm vẫn đang được sử dụng và bạn có thể phải chờ để sử dụng nó. Hoặc, bạn chỉ có thể thêm:

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

Điều này sẽ làm cho cổng có sẵn trong một thời gian ngắn hơn. Trong trường hợp của tôi, nó làm cho cổng có sẵn gần như ngay lập tức.


4

Chỉ trong trường hợp các giải pháp trên không hoạt động:

  1. Nhận cổng mà quá trình của bạn đang lắng nghe:

    $ rìu | trăn grep

  2. Giết quá trình

    $ giết PROCESS_NAME


3

Tôi có một raspberry pi, và tôi đang sử dụng máy chủ web python (sử dụng Flask). Tôi đã thử mọi thứ ở trên, giải pháp duy nhất là đóng terminal (shell) và mở lại. Hoặc khởi động lại pi mâm xôi , vì không có gì ngăn cản máy chủ web đó ...


2

Bạn có thể cho phép máy chủ sử dụng lại một địa chỉ với allow_reuse_address .

Liệu máy chủ sẽ cho phép sử dụng lại một địa chỉ. Điều này mặc định Falsevà có thể được đặt trong các lớp con để thay đổi chính sách.

import SimpleHTTPServer, SocketServer
PORT = 8000
httpd = SocketServer.TCPServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.allow_reuse_address = True
print "Serving at port", PORT
httpd.serve_forever()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.