Class: WinRM::CommandExecutor
- Inherits:
-
Object
- Object
- WinRM::CommandExecutor
- Defined in:
- lib/winrm/command_executor.rb
Overview
Object which can execute multiple commands and Powershell scripts in one shared remote shell session. The maximum number of commands per shell is determined by interrogating the remote host when the session is opened and the remote shell is automatically recycled before the threshold is reached.
Instance Attribute Summary collapse
-
#service ⇒ WinRM::WinRMWebService
readonly
A WinRM web service object.
-
#shell ⇒ String?
readonly
The identifier for the current open remote shell session, or ‘nil` if the session is not open.
Class Method Summary collapse
-
.finalize(shell_id, service) ⇒ Object
Closes an open remote shell session left open after a command executor is garbage collecyted.
Instance Method Summary collapse
-
#close ⇒ Object
Closes the open remote shell session.
-
#code_page ⇒ Integer
Code page appropriate to os version.
-
#initialize(service) ⇒ CommandExecutor
constructor
Creates a CommandExecutor given a ‘WinRM::WinRMWebService` object.
-
#max_commands ⇒ Integer
The safe maximum number of commands that can be executed in one remote shell session.
-
#open ⇒ String
Opens a remote shell session for reuse.
-
#run_cmd(command, arguments = []) {|stdout, stderr| ... } ⇒ WinRM::Output
Runs a CMD command.
-
#run_powershell_script(script_file) {|stdout, stderr| ... } ⇒ WinRM::Output
Run a Powershell script that resides on the local box.
Constructor Details
#initialize(service) ⇒ CommandExecutor
Creates a CommandExecutor given a ‘WinRM::WinRMWebService` object.
49 50 51 52 |
# File 'lib/winrm/command_executor.rb', line 49 def initialize(service) @service = service @command_count = 0 end |
Instance Attribute Details
#service ⇒ WinRM::WinRMWebService (readonly)
Returns a WinRM web service object.
39 40 41 |
# File 'lib/winrm/command_executor.rb', line 39 def service @service end |
#shell ⇒ String? (readonly)
Returns the identifier for the current open remote shell session, or ‘nil` if the session is not open.
43 44 45 |
# File 'lib/winrm/command_executor.rb', line 43 def shell @shell end |
Class Method Details
.finalize(shell_id, service) ⇒ Object
Closes an open remote shell session left open after a command executor is garbage collecyted.
34 35 36 |
# File 'lib/winrm/command_executor.rb', line 34 def self.finalize(shell_id, service) proc { service.close_shell(shell_id) } end |
Instance Method Details
#close ⇒ Object
Closes the open remote shell session. This method can be called multiple times, even if there is no open session.
56 57 58 59 60 61 62 |
# File 'lib/winrm/command_executor.rb', line 56 def close return if shell.nil? service.close_shell(shell) remove_finalizer @shell = nil end |
#code_page ⇒ Integer
Code page appropriate to os version. utf-8 (65001) is buggy pre win7/2k8r2 So send MS-DOS (437) for earlier versions
148 149 150 |
# File 'lib/winrm/command_executor.rb', line 148 def code_page @code_page ||= os_version < Gem::Version.new('6.1') ? 437 : 65_001 end |
#max_commands ⇒ Integer
Returns the safe maximum number of commands that can be executed in one remote shell session.
154 155 156 |
# File 'lib/winrm/command_executor.rb', line 154 def max_commands @max_commands ||= (os_version < Gem::Version.new('6.2') ? 15 : 1500) - 2 end |
#open ⇒ String
Opens a remote shell session for reuse. The maxiumum command-per-shell threshold is also determined the first time this method is invoked and cached for later invocations.
69 70 71 72 73 74 75 76 77 |
# File 'lib/winrm/command_executor.rb', line 69 def open close retryable(service.retry_limit, service.retry_delay) do @shell = service.open_shell(codepage: code_page) end add_finalizer(shell) @command_count = 0 shell end |
#run_cmd(command, arguments = []) {|stdout, stderr| ... } ⇒ WinRM::Output
Runs a CMD command.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/winrm/command_executor.rb', line 88 def run_cmd(command, arguments = [], &block) tries ||= 2 reset if command_count > max_commands ensure_open_shell! @command_count += 1 result = nil service.run_command(shell, command, arguments) do |command_id| result = service.get_command_output(shell, command_id, &block) end result rescue WinRMWSManFault => e # Fault code 2150858843 may be raised if the shell id that the command is sent on # has been closed. One might see this on a target windows machine that has just # been provisioned and restarted the winrm service at the end of its provisioning # routine. If this hapens, we should give the command one more try. # Fault code 2147943418 may be raised if the shell is installing an msi and for # some reason it tries to read a registry key that has been deleted. This sometimes # happens for 2008r2 when installing the Chef omnibus msi. if %w(2150858843 2147943418).include?(e.fault_code) && (tries -= 1) > 0 service.logger.debug('[WinRM] opening new shell since the current one failed') @shell = nil open retry else raise end end |
#run_powershell_script(script_file) {|stdout, stderr| ... } ⇒ WinRM::Output
Run a Powershell script that resides on the local box.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/winrm/command_executor.rb', line 128 def run_powershell_script(script_file, &block) # this code looks overly compact in an attempt to limit local # variable assignments that may contain large strings and # consequently bloat the Ruby VM run_cmd( 'powershell', [ '-encodedCommand', ::WinRM::PowershellScript.new( script_file.is_a?(IO) ? script_file.read : script_file ).encoded ], &block ) end |