Multithreading 如何在后台运行tshark命令并在python中使用子进程退出它

Multithreading 如何在后台运行tshark命令并在python中使用子进程退出它,multithreading,python-2.7,subprocess,background-process,tshark,Multithreading,Python 2.7,Subprocess,Background Process,Tshark,我想在连接到telnet上的远程主机设备时,使用Wireshark的命令行风格tshark,进行数据包捕获。我想调用我为捕获而编写的函数: def wire_cap(ip1,ip2,op_fold,file_name,duration): # invoke tshark to capture traffic during session if duration == 0: cmd='"tshark" -i 1 -P -w '+ op_fold+file_name+'.p

我想在连接到telnet上的远程主机设备时,使用Wireshark的命令行风格
tshark
,进行数据包捕获。我想调用我为捕获而编写的函数:

def wire_cap(ip1,ip2,op_fold,file_name,duration):  # invoke tshark to capture traffic during session
    if duration == 0:
        cmd='"tshark" -i 1 -P -w '+ op_fold+file_name+'.pcap src ' + str(ip1) + ' or src '+ str(ip2)
    else:
        cmd='"tshark" -i 1 -a duration:'+str(duration)+' -P -w '+ op_fold+file_name+'.pcap src ' + str(ip1) + ' or src '+ str(ip2)

    p = subprocess.Popen(cmd, shell=True,stderr=subprocess.PIPE)
    while True:
        out = p.stderr.read(1)
        if out == '' and p.poll() != None:
            break
        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()
出于调试目的,我希望在后台运行此函数,在需要时调用它,并在获取捕获后停止它。比如:

Start a thread or a background process called wire_capture
//Do something here
Stop the thread or the background process wire_capture
通过阅读,我意识到
thread.start\u new\u thread()
threading.thread()
似乎只有在我知道捕获的持续时间(退出条件)时才合适。我尝试使用
thread.exit()
,但它的行为类似于
sys.exit()
,完全停止了程序的执行。我还尝试了
threading.Event()
,如下所示:

if cap_flg:
    print "Starting a packet capture thread...."
    th_capture = threading.Thread(target=wire_cap, name='Thread_Packet_Capture', args=(IP1, IP2, output, 'wire_capture', 0, ))
    th_capture.setDaemon(True)
    th_capture.start()

.
.
.
.
.

if cap_flg:
    thread_kill = threading.Event()
    print "Exiting the packet capture thread...."
    thread_kill.set()
    th_capture.join()
我想知道,当我想停止进程时,如何让它停止(比如可以添加退出条件,以便退出线程执行)。我尝试的上述代码似乎不起作用。

线程化.Event()方法是正确的,但您需要在两个线程中都能看到事件,因此您需要在启动第二个线程并传递它之前创建它:

if cap_flg:
    print "Starting a packet capture thread...."
    thread_kill = threading.Event()
    th_capture = threading.Thread(target=wire_cap, name='Thread_Packet_Capture', args=(IP1, IP2, output, 'wire_capture', 0, thread_kill))
    th_capture.setDaemon(True)
    th_capture.start()
while
循环中,让监视线程在每次迭代中检查事件,如果设置了循环,则停止循环(也可能杀死它启动的
tshark
)。您还需要确保流程不会永远等待流程的输出并忽略终止事件,如果有数据可用,只从管道中读取:

def wire_cap(ip1,ip2,op_fold,file_name,duration,event):  # invoke tshark to capture traffic during session
    if duration == 0:
        cmd='"tshark" -i 1 -P -w '+ op_fold+file_name+'.pcap src ' + str(ip1) + ' or src '+ str(ip2)
    else:
        cmd='"tshark" -i 1 -a duration:'+str(duration)+' -P -w '+ op_fold+file_name+'.pcap src ' + str(ip1) + ' or src '+ str(ip2)

    p = subprocess.Popen(cmd, shell=True,stderr=subprocess.PIPE)
    while not event.is_set():
        # Make sure to not block forever waiting for 
        # the process to say things, so we can see if
        # the event gets set. Only read if data is available.
        if len(select.select([p.stderr], [], [], 0.1)) > 0:
            out = p.stderr.read(1)
            if out == '' and p.poll() != None:
                break
            if out != '':
                sys.stdout.write(out)
                sys.stdout.flush()
    p.kill()
然后要真正告诉线程停止,只需设置事件:

if cap_flg:
    print "Exiting the packet capture thread...."
    thread_kill.set()
    th_capture.join()

可能问题在于,如中所述,
setDaemon()
被忽略:主线程不是守护线程,因此在主线程中创建的所有线程默认为daemon=False。当没有活动的非守护进程线程时,整个Python程序就会退出。@LuisMuñoz我错过了这一部分。也许这就是为什么它不在后台运行。但是,我想知道是否有替代
线程化的方法。这方面有什么线索吗?不幸的是,在python上没有太多的线程经验。也许从辅助线程启动该线程会有所帮助。向popen请求pid,然后简单地杀死它怎么样?