Reputation: 11734
I'm trying to write a small script which will use plink.exe (from the same folder) to create a ssh tunnel (on windows).
I'm basically using os.system
to launch the the command:
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'
However, it seems that the thread (and plink.exe) keep running. Why is this happening? Any way to force the thread to close? Better way to launch plink?
I want plink.exe to die when my program ends. Using a daemon thread was my plan of having the tunnel run in the background, and then dying when my main code exits.
BTW - same thing happens with subprocess.call
.
Upvotes: 1
Views: 354
Reputation: 94881
You can use the atexit
and signal
modules to register calls back that will explicitly kill the process when your program exits normally or receives SIGTERM
, respectively:
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'
The one thing that is odd about the behavior your desrcibed is that I would have expected your program to exit after your sleep
call, but leave plink running in the background, rather than having your program hang until the os.system
call completes. That's the behavior I see on Linux, at least. In any case, explicitly terminating the child process should solve the issue for you.
Upvotes: 1
Reputation: 5244
os.system
does not return until the child process exits. The same is true for subprocess.call
. That's why your thread is sitting there, waiting for plink to finish. You can probably use subprocess.Popen
to launch the process asynchronously and then exit. In any case, the additional thread you are creating is unnecessary.
Upvotes: 0