我正在製作一個簡單的多線程端口掃描器。它掃描主機上的所有端口並返回開放端口。麻煩是中斷掃描。掃描完成需要很長時間,有時我希望在掃描過程中用C-c殺死程序。麻煩是掃描不會停止。主線程被鎖定在queue.join()上,並且忘記KeyboardInterrupt,直到隊列中的所有數據都被處理,從而對主線程進行解鎖並優雅地退出程序。我的所有線程都被守護進程,所以當主線程死亡時,它們應該與他一起死亡。Python - 無法用KeyboardInterrupt殺死主線程
我嘗試使用信號庫,沒有成功。重寫threading.Thread類,並增加了對正常終止沒有工作方法...主線程就不會在執行queue.join收到一個KeyboardInterrupt()
import threading, sys, Queue, socket
queue = Queue.Queue()
def scan(host):
while True:
port = queue.get()
if port > 999 and port % 1000 == 0:
print port
try:
#sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#sock.settimeout(2) #you need timeout or else it will try to connect forever!
#sock.connect((host, port))
#----OR----
sock = socket.create_connection((host, port), timeout = 2)
sock.send('aaa')
data = sock.recv(100)
print "Port {} open, message: {}".format(port, data)
sock.shutdown()
sock.close()
queue.task_done()
except:
queue.task_done()
def main(host):
#populate queue
for i in range(1, 65536):
queue.put(i)
#spawn worker threads
for port in range(100):
t = threading.Thread(target = scan, args = (host,))
t.daemon = True
t.start()
if __name__ == '__main__':
host = ""
#does input exist?
try:
host = sys.argv[1]
except:
print "No argument was recivied!"
exit(1)
#is input sane?
try:
host = socket.gethostbyname(host)
except:
print "Adress does not exist"
exit(2)
#execute main program and wait for scan to complete
main(host)
print "Post main() call!"
try:
queue.join()
except KeyboardInterrupt:
print "C-C"
exit(3)
編輯:
我已經找到了解決方案使用時間模塊。
#execute main program and wait for scan to complete
main(host)
#a little trick. queue.join() makes main thread immune to keyboardinterrupt. So use queue.empty() with time.sleep()
#queue.empty() is "unreliable" so it may return True a bit earlier then intented.
#when queue is true, queue.join() is executed, to confirm that all data was processed.
#not a true solution, you can't interrupt main thread near the end of scan (when queue.empty() returns True)
try:
while True:
if queue.empty() == False:
time.sleep(1)
else:
break
except KeyboardInterrupt:
print "Alas poor port scanner..."
exit(1)
queue.join()
有誰知道,如果有一種方法可以做到這一點沒有真正一會兒?這浪費了大量的CPU,而我正在使用線程從線程來避免一段時間的真實。 'thread.join'是非常完美的,只要我能夠殺死它(沒有CPU時間浪費的無限循環)。有任何想法嗎?我將運行的測試並不要求我殺死它,因爲線程無限期地持續下去(理論上它會一直持續下去),但是,出於測試目的和將來的參考(因爲在另一個術語中執行'pkill python'是一種痛苦每次開窗都會),我真心想知道。謝謝(並且不要說ctrl + z) – dylnmc
如果你在Windows上運行這個,這是「正常的」。 Python解釋器捕獲CTRL-C並設置一個內部標誌,然後等待控制返回到Python解釋,以便它可以引發'KeyboardInterrupt'。它依靠阻止系統調用返回'EINTR'以返回並檢查內部標誌。但是,當發生這種情況時,阻止Windows上的系統操作不會返回'EINTR'錯誤代碼,因此'KeyboardInterrupt'異常會延遲到您的阻止操作完成。 –