サーバーを起動するために頻繁に実行するCherryPyスクリプトがあります。今日、設定ファイルのいくつかのバグを修正するために数回起動および停止する必要がありました。ソケットを再起動しようとしたときに次の問題が発生したため、ソケットが完全に閉じなかったと思います。
[23/Mar/2015:14:08:00] ENGINE Listening for SIGHUP.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGTERM.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGUSR1.
[23/Mar/2015:14:08:00] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.
[23/Mar/2015:14:08:00] ENGINE Started monitor thread 'Autoreloader'.
[23/Mar/2015:14:08:00] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Mar/2015:14:08:00] ENGINE Error in HTTP server: shutting down
Traceback (most recent call last):
File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/process/servers.py", line 188, in _start_http_thread
self.httpserver.start()
File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1848, in start
raise socket.error(msg)
error: No socket could be created
CherryPyのwsgiserver2.pyを編集して、socket.errorとerror.strerror
は
98 (98, 'Address already in use') Address already in use
一方、私のソケットは次のように構成されています:
af = 2
socktype = 1
proto = 6
canonname = ''
sa = ('0.0.0.0', 2112)
self.bind(af, socktype, proto)
(これは正確なコードではありませんが、エラーが発生したときの値です)
Netstatをチェックしたところ、ポート2112でリッスンしているものは何もありませんでした。何が問題の原因であり、どのように診断すればよいですか?
ありがとう!
以下を試すことができます
from socket import *
sock=socket()
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# then bind
ドキュメントから:
SO_REUSEADDRフラグは、本来のタイムアウトが切れるのを待たずに、TIME_WAIT状態のローカルソケットを再利用するようにカーネルに指示します。
ここに完全な説明があります:
実行間の遅延が小さすぎる例を数回実行すると、このエラーが発生する可能性があります。
socket.error: [Errno 98] Address already in use
これは、前回の実行でソケットがTIME_WAIT状態のままになり、すぐに再利用できないためです。
これを防止するために設定するソケットフラグがあります。socket.SO_REUSEADDR:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((Host, PORT))
次のようにして、プロセスを見つけてkill
できます。
ps aux | grep python
、プロセスIDを見つけ、次のようにして手動で停止します。
Sudo kill -9 PID
pIDをPIDに置き換えます。
Flask/CherryPyでテストしている間、私はしばしばこれをしなければなりません。より簡単な方法があるかどうかに興味があります(たとえば、そもそもそれを防ぐため)
それを行うのははるかに簡単です:
PIDを確認します(127.0.0.1:5000で実行して以来、:5000はホストです):$ lsof -i :5000
それからそれを殺します:$ Sudo kill -9 PID