socket.error: [Errno 48] ที่อยู่ที่ใช้งานแล้ว


224

ฉันพยายามตั้งค่าเซิร์ฟเวอร์ด้วย python จาก terminal mac

ฉันไปที่ตำแหน่งโฟลเดอร์การใช้งาน:

python -m SimpleHTTPServer

แต่นี่ทำให้ฉันเกิดข้อผิดพลาด:

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

ก่อนหน้านี้ฉันเปิดการเชื่อมต่อโดยใช้คำสั่งเดียวกันสำหรับเว็บไซต์อื่นในตำแหน่งที่ตั้งอื่นในเครื่องของฉัน


2
ฆ่ากระบวนการอื่น ๆ หรือใช้อย่างใดอย่างหนึ่งกับพอร์ตที่แตกต่างกัน:python -m SimpleHTTPServer 8081
ปั่น

คำตอบ:


356

คุณมีกระบวนการเชื่อมโยงกับพอร์ตเริ่มต้น (8000) แล้ว หากคุณเคยรันโมดูลเดิมมาก่อนมันเป็นไปได้มากที่กระบวนการจะยังคงเชื่อมโยงกับพอร์ต ลองและค้นหากระบวนการอื่นก่อน:

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

อาร์กิวเมนต์คำสั่งถูกรวมไว้ดังนั้นคุณสามารถมองเห็นการทำงานSimpleHTTPServerหากpythonกระบวนการมากกว่าหนึ่งกระบวนการทำงานอยู่ คุณอาจต้องการทดสอบว่า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

14
อาจจำเป็นต้องใช้sudo kill -9 PID
Danpe

ขอบคุณ @Danpe ฉันลอง "sudo kill PID" ซึ่งใช้งานไม่ได้ แต่ "sudo kill -9 PID" ฆ่ากระบวนการ ใครรู้ว่าสิ่งที่ -9 ระบุ? แม้แต่ sudo manual ก็ดูเหมือนจะไม่ครอบคลุมพารามิเตอร์นี้sudo.ws/man/sudo.man.html
seokhoonlee

3
@ seokhoonlee: killส่งสัญญาณไปยังกระบวนการซึ่งมันสามารถตัดสินใจที่จะจัดการ (เช่นปิดลงอย่างสง่างามหรือหมุน logfile) สัญญาณเหล่านี้เป็นจำนวนเต็ม (แต่ละคนมีชื่อ) เริ่มต้นเป็น 15 ความหมายTERMหรือยุติ การใช้ -9 ส่งสัญญาณ 9 KILLซึ่งเป็นโปรเซสไม่สามารถตรวจจับและเพิกเฉยได้และระบบปฏิบัติการจะยุติกระบวนการตามที่ต้องการหรือไม่
Martijn Pieters

@ seokhoonlee: ดูบทความสัญญาณ Unixบน Wikipedia
Martijn Pieters

153

วิธีแก้ง่าย:

  1. ค้นหากระบวนการโดยใช้พอร์ต8080:

    sudo lsof -i:8080

  2. ฆ่ามัน:

    kill XXXX


8
คำตอบนี้จะได้รับประโยชน์จากตัวอย่างของlsofผลลัพธ์ที่อาจมีลักษณะและวิธีการค้นหา ID กระบวนการ (รายการ "XXXX" ที่คุณ) ภายในผลลัพธ์ สำหรับทุกคนที่เห็นสิ่งนี้โดยไม่มีข้อมูลนั้นมันเป็นฟิลด์ที่สองในผลลัพธ์ภายใต้ป้ายส่วนหัวของ "PID"
lindes

2
@lindes คุณแตก!
Carlos Rodríguez

@ CarlosRodríguez: เหรอ? ฉันไม่รู้จริงๆว่าคุณหมายถึงอะไรโดยความคิดเห็นนั้น (ฉันรู้หลายคำนิยามของ "เสียงแตก" และสิ่งที่ฉันรู้ว่าดูเหมือนจะไม่พอดี ... )
38919

2
@ CarlosRodríguezฉันต้องการเชื่อว่าเขาพบคำตอบของคุณอย่างแน่นอน ฉันคิดว่าการสังเกตของคุณเกี่ยวกับความจำเป็นในการให้ตัวอย่างผลลัพธ์ของ lsof และวิธีการระบุ PID นั้นสำคัญมาก รายการที่สองในแต่ละแถวที่ส่งคืนโดยปกติจะเป็น PID ซึ่งจะอยู่ภายใต้คอลัมน์ PID ของผลลัพธ์
เสมอ

32

ใช้

 sudo lsof -i:5000

นี่จะให้รายการของกระบวนการที่ใช้พอร์ตถ้ามี เมื่อรายการของกระบวนการได้รับการใช้ id ในคอลัมน์ PID เพื่อยุติการใช้กระบวนการ

 kill 379 #use the provided PID

มันสมบูรณ์แบบโดยเฉพาะอย่างยิ่งผู้ที่ทำงานกับ MAC OSX และไม่ได้ใช้SO_REUSEPORTแทนSO_REUSEADDR
snr

16

โดยวิธีการเพื่อป้องกันสิ่งนี้เกิดขึ้นในสถานที่แรกเพียงกดCtrl+ Cใน terminal ในขณะที่ SimpleHTTPServer ยังคงทำงานตามปกติ การดำเนินการนี้จะ "หยุด" เซิร์ฟเวอร์และปล่อยพอร์ตเพื่อให้คุณไม่ต้องค้นหาและฆ่ากระบวนการอีกครั้งก่อนที่จะรีสตาร์ทเซิร์ฟเวอร์

(Mods: ฉันพยายามใส่ความคิดเห็นนี้เพื่อหาคำตอบที่ดีที่สุดในที่นี้ แต่ฉันมีชื่อเสียงไม่เพียงพอ)


12

คำสั่งหนึ่งบรรทัดง่าย ๆ เพื่อกำจัดมันพิมพ์คำสั่งด้านล่างในเทอร์มินัล

ps -a

นี่จะแสดงรายการกระบวนการทั้งหมดเช็คเอาต์ซึ่งใช้โดย Python และพิมพ์คำสั่ง bellow ในเทอร์มินัล

kill -9 (processID) 

ตัวอย่างเช่น kill -9 33178


7

นอกจากนี้คุณยังสามารถให้บริการบนพอร์ตที่มีลำดับสูงสุดถัดไปซึ่งทำสิ่งนี้ใน 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

หากคุณต้องการทำสิ่งเดียวกันกับยูทิลิตี้อื่น ๆ มันอาจจะสะดวกกว่าในฐานะของสคริปต์ทุบตี:

#!/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 ดั้งเดิมเนื่องจากสคริปต์ทุบตีไม่ได้จับพอร์ต - กระบวนการอื่นสามารถคว้าพอร์ตก่อนที่กระบวนการของคุณจะทำ (สภาพการแข่งขัน) - แต่ก็อาจมีประโยชน์เพียงพอเมื่อใช้ยูทิลิตี้ที่ไม่ได้ ' ไม่มีวิธีการลองด้วยตนเองอีกครั้ง


6

ฉันใหม่กับ Python แต่หลังจากการวิจัยสั้น ๆ ของฉันฉันพบว่านี่เป็นเรื่องปกติของซ็อกเก็ตที่ถูกผูกไว้ มันเกิดขึ้นจนซ็อกเก็ตยังคงใช้งานอยู่และคุณอาจต้องรอใช้งาน หรือคุณสามารถเพิ่ม:

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

สิ่งนี้จะทำให้พอร์ตพร้อมใช้งานภายในเวลาอันสั้น ในกรณีของฉันมันทำให้พอร์ตพร้อมใช้งานเกือบจะทันที


4

ในกรณีข้างบนโซลูชันไม่ทำงาน:

  1. รับพอร์ตที่กระบวนการของคุณกำลังรับฟัง:

    $ ps ax | หลาม grep

  2. ฆ่ากระบวนการ

    $ kill PROCESS_NAME


3

ฉันมีราสเบอร์รี่ปี่และฉันใช้เว็บเซิร์ฟเวอร์หลาม (ใช้ Flask) ฉันได้ลองทุกอย่างด้านบนทางออกเดียวคือปิดเทอร์มินัล (เชลล์)และเปิดอีกครั้ง หรือรีสตาร์ทราสเบอร์รี่ piเพราะไม่มีอะไรหยุดเว็บเซิร์ฟเวอร์นั้น ...


2

คุณสามารถอนุญาตให้เซิร์ฟเวอร์ใช้ที่อยู่ซ้ำ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()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.