socket.error: [Errno 48] Adresse wird bereits verwendet

223

Ich versuche, einen Server mit Python vom Mac-Terminal aus einzurichten.

Ich navigiere zum Ordner und verwende ihn:

python -m SimpleHTTPServer

Aber das gibt mir Fehler:

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

Ich hatte zuvor eine Verbindung mit demselben Befehl für eine andere Website an einem anderen Ort auf meinem Computer geöffnet.

irm
quelle
2
Beenden Sie den anderen Prozess oder führen Sie diesen mit einem anderen Port aus:python -m SimpleHTTPServer 8081
Blender

Antworten:

355

Sie haben bereits einen Prozess an den Standardport (8000) gebunden. Wenn Sie bereits zuvor dasselbe Modul ausgeführt haben, ist der Prozess höchstwahrscheinlich immer noch an den Port gebunden. Versuchen Sie zuerst, den anderen Prozess zu finden:

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

Die Befehlsargumente sind enthalten, sodass Sie das laufende erkennen können, SimpleHTTPServerwenn mehr als ein pythonProzess aktiv ist. Möglicherweise möchten Sie testen, ob http://localhost:8000/noch eine Verzeichnisliste für lokale Dateien angezeigt wird .

Die zweite Nummer ist die Prozessnummer. Stoppen Sie den Server, indem Sie ihm ein Signal senden:

kill 81651

Dies sendet ein Standardsignal SIGTERM; Wenn der Prozess nicht reagiert, müssen Sie möglicherweise auf härtere Methoden wie das Senden eines SIGKILL( kill -s KILL <pid>oder kill -9 <pid>) Signals zurückgreifen . Siehe Wikipedia für weitere Details .

Alternativ können Sie den Server an einem anderen Port ausführen , indem Sie den alternativen Port in der Befehlszeile angeben:

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

dann auf den Server zugreifen als http://localhost:8910; Wo 8910kann eine beliebige Nummer ab 1024 sein, vorausgesetzt, der Port ist noch nicht belegt.

Martijn Pieters
quelle
Welche URL sollte ich im Browser haben, um zu sehen, ob es funktioniert? Ich laufe auf einem anderen Port, wie Sie vorgeschlagen haben
irm
14
Möglicherweise muss verwendet werdensudo kill -9 PID
Danpe
Danke, @Danpe, ich habe "sudo kill PID" ausprobiert, was nicht funktioniert hat, aber "sudo kill -9 PID" hat den Prozess beendet. Weiß jemand was -9 angibt? Selbst das Sudo-Handbuch scheint diesen Parameter nicht abzudecken. Sudo.ws/man/sudo.man.html
Seokhoonlee
3
@seokhoonlee: killSendet ein Signal an den Prozess, das er verarbeiten kann (z. B. ordnungsgemäßes Herunterfahren oder Drehen einer Protokolldatei). Diese Signale sind Ganzzahlen (jeweils mit einem Namen), wobei der Standardwert 15 ist, was bedeutet TERModer endet . Die Verwendung von -9 sendet das Signal 9, KILLdas ein Prozess nicht abfangen und ignorieren kann, und das Betriebssystem beendet den Prozess, ob es möchte oder nicht.
Martijn Pieters
@seokhoonlee: siehe auch die Unix - Signal Artikel auf Wikipedia.
Martijn Pieters
152

Einfache Lösung:

  1. Finden Sie den Prozess über Port 8080:

    sudo lsof -i:8080

  2. Töte es:

    kill XXXX

Schnecke
quelle
8
Diese Antwort würde von einem Beispiel profitieren, wie die lsofAusgabe aussehen könnte und wie die Prozess-ID (das von Ihnen aufgelistete "XXXX") in der Ausgabe gefunden wird. Für alle, die dies ohne diese Informationen sehen, ist es das zweite Feld in der Ausgabe unter der Überschriftenbezeichnung "PID".
Lindes
2
@ Lindes Du bist ein Riss!
Carlos Rodríguez
@ CarlosRodríguez: huh? Ich weiß wirklich nicht, was Sie mit diesem Kommentar meinen (ich kenne mehrere Definitionen von "Crack", und die, die ich kenne, scheinen nicht zu passen ...)
Lindes
2
@ CarlosRodríguez Ich möchte glauben, dass er Ihre Antwort absolut auf den Punkt gebracht hat. Ich denke, Ihre Beobachtung zur Notwendigkeit, Stichproben über die Ausgabe von lsof zu geben und wie man PID identifiziert, ist sehr wichtig. Das zweite Element in jeder zurückgegebenen Zeile ist normalerweise die PID. Sie befindet sich immer in der PID-Spalte der Ausgabe
Kudehinbu Oluwaponle,
32

Verwenden

 sudo lsof -i:5000

Dadurch erhalten Sie eine Liste der Prozesse, die den Port verwenden, falls vorhanden. Wenn die Liste der Prozesse angegeben ist, verwenden Sie die ID in der PID-Spalte, um die Prozessverwendung zu beenden

 kill 379 #use the provided PID
Süßigkeitenmann
quelle
Das ist perfekt, besonders für diejenigen, die unter MAC OSX arbeiten und SO_REUSEPORT nicht anstelle von SO_REUSEADDR verwendet haben
snr
16

Übrigens, um dies zu verhindern, drücken Sie einfach Ctrl+ Cim Terminal, während SimpleHTTPServer noch normal läuft. Dadurch wird der Server "ordnungsgemäß" gestoppt und der Port freigegeben, sodass Sie den Prozess nicht erneut suchen und beenden müssen, bevor Sie den Server neu starten.

(Mods: Ich habe versucht, diesen Kommentar auf die beste Antwort zu setzen, wo sie hingehört, aber ich habe nicht genug Ruf.)

Mark Chapel
quelle
12

Einfacher einzeiliger Befehl, um ihn loszuwerden. Geben Sie den folgenden Befehl in das Terminal ein.

ps -a

Dadurch werden alle Prozesse aufgelistet, die von Python verwendet werden, und der folgende Befehl wird in das Terminal eingegeben.

kill -9 (processID) 

Zum Beispiel töte -9 33178

Aditya
quelle
7

Sie können auch auf dem nächsthöheren verfügbaren Port arbeiten und in Python Folgendes tun:

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

Wenn Sie dasselbe für andere Dienstprogramme tun müssen, ist dies möglicherweise praktischer als ein Bash-Skript:

#!/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

Wenn Sie das als ausführbare Datei mit dem Namen get-free-porteinrichten, können Sie Folgendes tun:

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

Dies ist nicht so zuverlässig wie der native Python-Ansatz, da das Bash-Skript den Port nicht erfasst - ein anderer Prozess könnte den Port vor Ihrem Prozess abrufen (Race-Bedingung) -, aber dennoch nützlich genug sein kann, wenn Sie ein Dienstprogramm verwenden, das dies nicht tut. Ich habe keinen eigenen Versuch, es noch einmal zu versuchen.

Chris Johnson
quelle
6

Ich bin neu in Python, aber nach meiner kurzen Recherche habe ich herausgefunden, dass dies typisch für das Binden von Sockets ist. Es kommt einfach so vor, dass der Socket noch verwendet wird und Sie möglicherweise warten müssen, um ihn zu verwenden. Oder Sie können einfach hinzufügen:

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

Dies sollte den Port in kürzerer Zeit verfügbar machen. In meinem Fall wurde der Port fast sofort verfügbar.

PoisonIvee
quelle
4

Nur für den Fall, dass die oben genannten Lösungen nicht funktionieren:

  1. Holen Sie sich den Port, den Ihr Prozess abhört:

    $ ps ax | Grep Python

  2. Töte den Prozess

    $ kill PROCESS_NAME

user3305074
quelle
3

Ich habe einen Himbeer-Pi und verwende einen Python-Webserver (mit Flask). Ich habe alles oben versucht, die einzige Lösung besteht darin, das Terminal (Shell) zu schließen und wieder zu öffnen. Oder starten Sie den Himbeer-Pi neu , weil nichts diesen Webserver aufhält ...

Thiago Farias
quelle
2

Sie können dem Server erlauben, eine Adresse mit wiederzuverwenden allow_reuse_address.

Gibt an, ob der Server die Wiederverwendung einer Adresse zulässt. Dies ist standardmäßig der FalseFall und kann in Unterklassen festgelegt werden, um die Richtlinie zu ändern.

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