Python - Can't kill main thread with KeyboardInterrupt
我正在制作一个简单的多线程端口扫描器。 它扫描主机上的所有端口并返回打开的端口。 麻烦在于中断扫描。 扫描完成需要花费大量时间,有时我希望在扫描过程中用C-c杀死程序。 麻烦的是扫描不会停止。 主线程被锁定在queue.join()上,并且忘记了KeyboardInterrupt,直到处理了队列中的所有数据,因此解除了主线程并正常退出程序。 我的所有线程都被守护进来,所以当主线程死掉时,他们应该和他一起死掉。
我尝试使用信号库,没有成功。 重写threading.Thread类和正常终止的添加方法不起作用...主线程在执行queue.join()时不会收到KeyboardInterrupt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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) |
编辑:
我通过使用时间模块找到了解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #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() |
你已经创建了你的线程守护进程,但你需要保持主线程处于活动状态,而守护程序线程就在那里,有如何做到这一点:不能用Ctrl-C杀死Python脚本
创建线程时,将它们添加到正在运行的线程列表中,当处理ctrl-C时,向列表中的每个线程发送一个kill信号。 这样你就可以积极清理而不是依赖它为你完成。