我正在尝试编写一个小脚本,它将使用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
。
答案 0 :(得分:1)
您可以使用atexit
和signal
模块注册回调,这些回调会在程序正常退出或分别收到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
异步启动进程然后退出。在任何情况下,您创建的其他线程都是不必要的。