守护程序线程启动软件不会死

时间:2014-07-29 18:25:55

标签: python multithreading python-2.7

我正在尝试编写一个小脚本,它将使用plink.exe(来自同一文件夹)创建一个ssh隧道(在Windows上)。 我基本上使用os.system来启动命令:

import time
import threading
from os.path import join, dirname, realpath
pc_tunnel_command = '-ssh -batch -pw xxxx -N -L 1234:host1:5678 user@host2'

if __name__ == '__main__':
    t = threading.Thread(target = os.system, \
                         args = (join(dirname(realpath(__file__)), 'plink.exe ') + \
                                      pc_tunnel_command,))
    t.daemon = True
    t.start()
    #without this line it will die. I guess that plink doesn't have enough time to start.
    time.sleep(5) 
    print 'Should die now'

然而,似乎线程(和plink.exe)继续运行。为什么会这样?有什么方法可以强制线程关闭?推出plink的更好方法是什么?

我希望程序结束时plink.exe会死掉。使用守护程序线程是我的计划让隧道在后台运行,然后在我的主代码退出时死亡。

BTW - 同样的事情发生在subprocess.call

2 个答案:

答案 0 :(得分:1)

您可以使用atexitsignal模块注册回调,这些回调会在程序正常退出或分别收到SIGTERM时明确终止该过程:

import sys
import time
import atexit
import signal
import subprocess
from functools import partial
from os.path import join, dirname, realpath

pc_tunnel_command = '-ssh -batch -pw xxxx -N -L 1234:host1:5678 user@host2'


def handle_exit(p, *args):
    print("killing it")
    p.terminate()
    sys.exit(0)

if __name__ == '__main__':
    p = subprocess.Popen(join(dirname(realpath(__file__)), 'plink.exe ') + pc_tunnel_command, shell=True)
    func = partial(handle_exit, p)
    signal.signal(signal.SIGTERM, func)
    atexit.register(func)
    print 'Should die now'

关于你的desrcibed行为的一个奇怪之处在于我希望你的程序在sleep调用之后退出,但是让plink在后台运行,而不是让你的程序挂起直到{ {1}}通话完成。这至少是我在Linux上看到的行为。在任何情况下,明确终止子进程都应该为您解决问题。

答案 1 :(得分:0)

在子进程退出之前,

os.system不会返回。 subprocess.call也是如此。这就是为什么你的线程坐在那里,等待plink完成的原因。您可以使用subprocess.Popen异步启动进程然后退出。在任何情况下,您创建的其他线程都是不必要的。