@@ -43,6 +43,39 @@ class MissingHostKey(object):
4343 auto_add = paramiko .AutoAddPolicy ()
4444 accept = AcceptParamikoPolicy ()
4545
46+ class WindowsShellType (object ):
47+ supports_which = True
48+
49+ def generate_run_command (self , command_args , store_pid ,
50+ cwd = None , update_env = {}, new_process_group = False ):
51+
52+ if new_process_group :
53+ raise UnsupportedArgumentError ("'new_process_group' is not supported when using a windows shell" )
54+
55+ commands = []
56+
57+ if store_pid :
58+ commands .append ("powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId" )
59+
60+ if cwd is not None :
61+ commands .append ("cd {0} 2>&1 || ( echo. & echo spur-cd: %errorlevel% & exit 1 )" .format (win_escape_sh (cwd )))
62+ commands .append ("echo. & echo spur-cd: 0" )
63+
64+ update_env_commands = [
65+ "SET {0}={1}" .format (key , value )
66+ for key , value in _iteritems (update_env )
67+ ]
68+ commands += update_env_commands
69+ commands .append (
70+ "( (powershell Get-Command {0} > nul 2>&1) && echo 0) || (echo %errorlevel% & exit 1)" .format (
71+ win_escape_sh (command_args [0 ])))
72+
73+ commands .append (" " .join (command_args ))
74+ return " & " .join (commands )
75+
76+ def generate_kill_command (self , pid ):
77+ return "taskkill /F /PID {0}" .format (pid )
78+
4679
4780class MinimalShellType (object ):
4881 supports_which = False
@@ -64,6 +97,8 @@ def generate_run_command(self, command_args, store_pid,
6497
6598 return " " .join (map (escape_sh , command_args ))
6699
100+ def generate_kill_command (self , pid ):
101+ return "kill {0}" .format (pid )
67102
68103 def _unsupported_argument_error (self , name ):
69104 return UnsupportedArgumentError ("'{0}' is not supported when using a minimal shell" .format (name ))
@@ -99,6 +134,9 @@ def generate_run_command(self, command_args, store_pid,
99134 commands .append (command )
100135 return "; " .join (commands )
101136
137+ def generate_kill_command (self , pid ):
138+ return "kill {0}" .format (pid )
139+
102140 def _generate_which_commands (self , command ):
103141 which_commands = ["command -v {0}" , "which {0}" ]
104142 return (
@@ -113,6 +151,7 @@ def _generate_which_command(self, which, command):
113151class ShellTypes (object ):
114152 minimal = MinimalShellType ()
115153 sh = ShShellType ()
154+ windows = WindowsShellType ()
116155
117156
118157class SshShell (object ):
@@ -141,7 +180,7 @@ def __init__(self,
141180 self ._password = password
142181 self ._private_key_file = private_key_file
143182 self ._client = None
144- self ._connect_timeout = connect_timeout if not None else _ONE_MINUTE
183+ self ._connect_timeout = connect_timeout if connect_timeout is not None else _ONE_MINUTE
145184 self ._look_for_private_keys = look_for_private_keys
146185 self ._load_system_host_keys = load_system_host_keys
147186 self ._closed = False
@@ -358,6 +397,10 @@ def escape_sh(value):
358397 return "'" + value .replace ("'" , "'\\ ''" ) + "'"
359398
360399
400+ def win_escape_sh (value ):
401+ return '"' + value + '"'
402+
403+
361404class SshProcess (object ):
362405 def __init__ (self , channel , allow_error , process_stdout , stdout , stderr , encoding , shell ):
363406 self ._channel = channel
@@ -382,6 +425,9 @@ def stdin_write(self, value):
382425 def send_signal (self , signal ):
383426 self ._shell .run (["kill" , "-{0}" .format (signal ), str (self .pid )])
384427
428+ def kill (self ):
429+ self ._shell .run ([self ._shell ._shell_type .generate_kill_command (self .pid )])
430+
385431 def wait_for_result (self ):
386432 if self ._result is None :
387433 self ._result = self ._generate_result ()
0 commit comments