Class: WinRM::CommandExecutor

Inherits:
Object
  • Object
show all
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.

Author:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(service) ⇒ CommandExecutor

Creates a CommandExecutor given a ‘WinRM::WinRMWebService` object.

Parameters:

  • service (WinRM::WinRMWebService)

    a winrm web service object responds to ‘#debug` and `#info` (default: `nil`)



49
50
51
52
# File 'lib/winrm/command_executor.rb', line 49

def initialize(service)
  @service = service
  @command_count = 0
end

Instance Attribute Details

#serviceWinRM::WinRMWebService (readonly)

Returns a WinRM web service object.

Returns:



39
40
41
# File 'lib/winrm/command_executor.rb', line 39

def service
  @service
end

#shellString? (readonly)

Returns the identifier for the current open remote shell session, or ‘nil` if the session is not open.

Returns:

  • (String, nil)

    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.

Parameters:

  • shell_id (String)

    the remote shell identifier

  • service (WinRM::WinRMWebService)

    a winrm web service object



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

#closeObject

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_pageInteger

Code page appropriate to os version. utf-8 (65001) is buggy pre win7/2k8r2 So send MS-DOS (437) for earlier versions

Returns:

  • (Integer)

    code page in use



129
130
131
# File 'lib/winrm/command_executor.rb', line 129

def code_page
  @code_page ||= os_version < '6.1' ? 437 : 65_001
end

#max_commandsInteger

Returns the safe maximum number of commands that can be executed in one remote shell session.

Returns:

  • (Integer)

    the safe maximum number of commands that can be executed in one remote shell session



135
136
137
# File 'lib/winrm/command_executor.rb', line 135

def max_commands
  @max_commands ||= (os_version < '6.2' ? 15 : 1500) - 2
end

#openString

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.

Returns:

  • (String)

    the remote shell session indentifier



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.

Parameters:

  • command (String)

    the command to run on the remote system

  • arguments (Array<String>) (defaults to: [])

    arguments to the command

Yields:

  • (stdout, stderr)

    yields more live access the standard output and standard error streams as they are returns, if streaming behavior is desired

Returns:

  • (WinRM::Output)

    output object with stdout, stderr, and exit code



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/winrm/command_executor.rb', line 88

def run_cmd(command, arguments = [], &block)
  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
end

#run_powershell_script(script_file) {|stdout, stderr| ... } ⇒ WinRM::Output

Run a Powershell script that resides on the local box.

Parameters:

  • script_file (IO, String)

    an IO reference for reading the Powershell script or the actual file contents

Yields:

  • (stdout, stderr)

    yields more live access the standard output and standard error streams as they are returns, if streaming behavior is desired

Returns:

  • (WinRM::Output)

    output object with stdout, stderr, and exit code



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/winrm/command_executor.rb', line 109

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