mixlib-shellout 3.3.9 → 3.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mixlib/shellout/unix.rb +1 -0
- data/lib/mixlib/shellout/version.rb +1 -1
- data/lib/mixlib/shellout/windows/core_ext.rb +0 -3
- data/lib/mixlib/shellout/windows.rb +26 -26
- data/lib/mixlib/shellout.rb +10 -6
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fcac251ffc6584464c8df6cc4d1583eb3d8c0d520ac987139f733baffcde3f24
|
|
4
|
+
data.tar.gz: 53076e837afe3d68a5c23c92186df8c44243a1432615866edf4cd527924d0918
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '019e84c71357cc9d3e79ce34d45f31d18d1fda1dc1f4e54a3172a26822481f873d25a1aea1f70f71cc39a84a687b4cbc4fc49b08eb7581ecac0a0c184ca7c952'
|
|
7
|
+
data.tar.gz: bafd1b3456b24b846346d8dc1acf1b88791fec0fc9912e84befe4554898019ae4eafbd413bf3f5b34d31fe8a946dee874b21cf73cab012c975ab8fd1a09a744c
|
data/lib/mixlib/shellout/unix.rb
CHANGED
|
@@ -447,7 +447,6 @@ module Process
|
|
|
447
447
|
|
|
448
448
|
def create_process_as_user(token, app, cmd, process_security,
|
|
449
449
|
thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo)
|
|
450
|
-
|
|
451
450
|
bool = CreateProcessAsUserW(
|
|
452
451
|
token, # User token handle
|
|
453
452
|
app, # App name
|
|
@@ -479,7 +478,6 @@ module Process
|
|
|
479
478
|
|
|
480
479
|
def create_process_with_logon(logon, domain, passwd, logon_flags, app, cmd,
|
|
481
480
|
creation_flags, env, cwd, startinfo, procinfo)
|
|
482
|
-
|
|
483
481
|
bool = CreateProcessWithLogonW(
|
|
484
482
|
logon, # User
|
|
485
483
|
domain, # Domain
|
|
@@ -501,7 +499,6 @@ module Process
|
|
|
501
499
|
|
|
502
500
|
def create_process(app, cmd, process_security, thread_security, inherit,
|
|
503
501
|
creation_flags, env, cwd, startinfo, procinfo)
|
|
504
|
-
|
|
505
502
|
bool = CreateProcessW(
|
|
506
503
|
app, # App name
|
|
507
504
|
cmd, # Command line
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
# Author:: Daniel DeLeo (<dan@chef.io>)
|
|
3
5
|
# Author:: John Keiser (<jkeiser@chef.io>)
|
|
4
6
|
# Author:: Ho-Sheng Hsiao (<hosh@chef.io>)
|
|
@@ -24,7 +26,6 @@ require_relative "windows/core_ext"
|
|
|
24
26
|
module Mixlib
|
|
25
27
|
class ShellOut
|
|
26
28
|
module Windows
|
|
27
|
-
|
|
28
29
|
include Process::Functions
|
|
29
30
|
include Process::Constants
|
|
30
31
|
|
|
@@ -44,9 +45,9 @@ module Mixlib
|
|
|
44
45
|
raise InvalidCommandOption, "`elevated` option should be passed only with `username` and `password`."
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
return unless opts[:elevated] && opts[:elevated] != true && opts[:elevated] != false
|
|
49
|
+
|
|
50
|
+
raise InvalidCommandOption, "Invalid value passed for `elevated`. Please provide true/false."
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
#--
|
|
@@ -59,18 +60,17 @@ module Mixlib
|
|
|
59
60
|
stdout_read, stdout_write = IO.pipe
|
|
60
61
|
stderr_read, stderr_write = IO.pipe
|
|
61
62
|
stdin_read, stdin_write = IO.pipe
|
|
62
|
-
open_streams = [
|
|
63
|
+
open_streams = [stdout_read, stderr_read]
|
|
63
64
|
@execution_time = 0
|
|
64
65
|
|
|
65
66
|
begin
|
|
66
|
-
|
|
67
67
|
#
|
|
68
68
|
# Set cwd, environment, appname, etc.
|
|
69
69
|
#
|
|
70
70
|
app_name, command_line = command_to_run(combine_args(*command))
|
|
71
71
|
create_process_args = {
|
|
72
|
-
app_name
|
|
73
|
-
command_line
|
|
72
|
+
app_name:,
|
|
73
|
+
command_line:,
|
|
74
74
|
startup_info: {
|
|
75
75
|
stdout: stdout_write,
|
|
76
76
|
stderr: stderr_write,
|
|
@@ -110,12 +110,10 @@ module Mixlib
|
|
|
110
110
|
@execution_time = Time.now - start_wait
|
|
111
111
|
# Get process exit code
|
|
112
112
|
exit_code = [0].pack("l")
|
|
113
|
-
unless GetExitCodeProcess(process.process_handle, exit_code)
|
|
114
|
-
raise get_last_error
|
|
115
|
-
end
|
|
113
|
+
raise get_last_error unless GetExitCodeProcess(process.process_handle, exit_code)
|
|
116
114
|
|
|
117
115
|
@status = ThingThatLooksSortOfLikeAProcessStatus.new
|
|
118
|
-
@status.exitstatus = exit_code.
|
|
116
|
+
@status.exitstatus = exit_code.unpack1("l")
|
|
119
117
|
|
|
120
118
|
return self
|
|
121
119
|
when WAIT_TIMEOUT
|
|
@@ -144,16 +142,13 @@ module Mixlib
|
|
|
144
142
|
else
|
|
145
143
|
raise "Unknown response from WaitForSingleObject(#{process.process_handle}, #{timeout * 1000}): #{wait_status}"
|
|
146
144
|
end
|
|
147
|
-
|
|
148
145
|
end
|
|
149
|
-
|
|
150
146
|
ensure
|
|
151
147
|
CloseHandle(process.thread_handle) if process.thread_handle
|
|
152
148
|
CloseHandle(process.process_handle) if process.process_handle
|
|
153
149
|
Process.unload_user_profile(token, profile) if profile
|
|
154
150
|
CloseHandle(token) if token
|
|
155
151
|
end
|
|
156
|
-
|
|
157
152
|
ensure
|
|
158
153
|
#
|
|
159
154
|
# Consume all remaining data from the pipes until they are closed
|
|
@@ -168,6 +163,7 @@ module Mixlib
|
|
|
168
163
|
|
|
169
164
|
class ThingThatLooksSortOfLikeAProcessStatus
|
|
170
165
|
attr_accessor :exitstatus
|
|
166
|
+
|
|
171
167
|
def success?
|
|
172
168
|
exitstatus == 0
|
|
173
169
|
end
|
|
@@ -183,7 +179,11 @@ module Mixlib
|
|
|
183
179
|
|
|
184
180
|
if ready.first.include?(stdout_read)
|
|
185
181
|
begin
|
|
186
|
-
|
|
182
|
+
# The unary plus operator (+) creates a mutable copy of the string returned by readpartial.
|
|
183
|
+
# This is necessary because readpartial may return a frozen string, and we need to be able
|
|
184
|
+
# to modify the string (append to buffers, manipulate encoding, etc.) in subsequent operations.
|
|
185
|
+
# Without the +, attempting to modify a frozen string would raise a FrozenError.
|
|
186
|
+
next_chunk = +stdout_read.readpartial(READ_SIZE)
|
|
187
187
|
@stdout << next_chunk
|
|
188
188
|
@live_stdout << next_chunk if @live_stdout
|
|
189
189
|
rescue EOFError
|
|
@@ -194,7 +194,7 @@ module Mixlib
|
|
|
194
194
|
|
|
195
195
|
if ready.first.include?(stderr_read)
|
|
196
196
|
begin
|
|
197
|
-
next_chunk = stderr_read.readpartial(READ_SIZE)
|
|
197
|
+
next_chunk = +stderr_read.readpartial(READ_SIZE)
|
|
198
198
|
@stderr << next_chunk
|
|
199
199
|
@live_stderr << next_chunk if @live_stderr
|
|
200
200
|
rescue EOFError
|
|
@@ -261,7 +261,7 @@ module Mixlib
|
|
|
261
261
|
if exe_needs_cmd?(exe)
|
|
262
262
|
run_under_cmd(command)
|
|
263
263
|
else
|
|
264
|
-
[
|
|
264
|
+
[exe, command]
|
|
265
265
|
end
|
|
266
266
|
end
|
|
267
267
|
|
|
@@ -275,14 +275,14 @@ module Mixlib
|
|
|
275
275
|
# https://github.com/chef/mixlib-shellout/pull/2#issuecomment-4837859
|
|
276
276
|
# http://ss64.com/nt/syntax-esc.html
|
|
277
277
|
def run_under_cmd(command)
|
|
278
|
-
[
|
|
278
|
+
[ENV["COMSPEC"], "cmd /c \"#{command}\""]
|
|
279
279
|
end
|
|
280
280
|
|
|
281
281
|
# FIXME: this extracts ARGV[0] but is it correct?
|
|
282
282
|
def candidate_executable_for_command(command)
|
|
283
283
|
if command =~ /^\s*"(.*?)"/ || command =~ /^\s*([^\s]+)/
|
|
284
284
|
# If we have quotes, do an exact match, else pick the first word ignoring the leading spaces
|
|
285
|
-
|
|
285
|
+
::Regexp.last_match(1)
|
|
286
286
|
else
|
|
287
287
|
""
|
|
288
288
|
end
|
|
@@ -405,15 +405,15 @@ module Mixlib
|
|
|
405
405
|
def kill_process(instance, logger)
|
|
406
406
|
child_pid = instance.wmi_ole_object.processid
|
|
407
407
|
logger&.debug([
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
408
|
+
"killing child process #{child_pid}::",
|
|
409
|
+
"#{instance.wmi_ole_object.Name} of parent #{pid}",
|
|
410
|
+
].join)
|
|
411
411
|
Process.kill(:KILL, instance.wmi_ole_object.processid)
|
|
412
412
|
rescue SystemCallError
|
|
413
413
|
logger&.debug([
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
414
|
+
"Failed to kill child process #{child_pid}::",
|
|
415
|
+
"#{instance.wmi_ole_object.Name} of parent #{pid}",
|
|
416
|
+
].join)
|
|
417
417
|
end
|
|
418
418
|
|
|
419
419
|
def format_process(process, app_name, command_line, timeout)
|
data/lib/mixlib/shellout.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#--
|
|
2
3
|
# Author:: Daniel DeLeo (<dan@chef.io>)
|
|
3
4
|
# Copyright:: Copyright (c) Chef Software Inc.
|
|
@@ -170,7 +171,8 @@ module Mixlib
|
|
|
170
171
|
# cmd = Mixlib::ShellOut.new("apachectl", "start", :user => 'www', :env => nil, :cwd => '/tmp')
|
|
171
172
|
# cmd.run_command # etc.
|
|
172
173
|
def initialize(*command_args)
|
|
173
|
-
|
|
174
|
+
# Since ruby 4.0 will freeze string literals by default, we are assigning mutable strings here.
|
|
175
|
+
@stdout, @stderr, @process_status = String.new(""), String.new(""), String.new("")
|
|
174
176
|
@live_stdout = @live_stderr = nil
|
|
175
177
|
@input = nil
|
|
176
178
|
@log_level = :debug
|
|
@@ -238,7 +240,7 @@ module Mixlib
|
|
|
238
240
|
def format_for_exception
|
|
239
241
|
return "Command execution failed. STDOUT/STDERR suppressed for sensitive resource" if sensitive
|
|
240
242
|
|
|
241
|
-
msg =
|
|
243
|
+
msg = String.new
|
|
242
244
|
msg << "#{@terminate_reason}\n" if @terminate_reason
|
|
243
245
|
msg << "---- Begin output of #{command} ----\n"
|
|
244
246
|
msg << "STDOUT: #{stdout.strip}\n"
|
|
@@ -268,7 +270,9 @@ module Mixlib
|
|
|
268
270
|
# within +timeout+ seconds (default: 600s)
|
|
269
271
|
def run_command
|
|
270
272
|
if logger
|
|
271
|
-
|
|
273
|
+
prefix = log_tag.nil? ? "" : "#{@log_tag} "
|
|
274
|
+
log_message = prefix + "sh(#{@command})"
|
|
275
|
+
# log_message = (log_tag.nil? ? "" : "#{@log_tag} ") << "sh(#{@command})"
|
|
272
276
|
logger.send(log_level, log_message)
|
|
273
277
|
end
|
|
274
278
|
super
|
|
@@ -334,11 +338,11 @@ module Mixlib
|
|
|
334
338
|
when "returns"
|
|
335
339
|
self.valid_exit_codes = Array(setting)
|
|
336
340
|
when "live_stream"
|
|
337
|
-
self.live_stdout = self.live_stderr = setting
|
|
341
|
+
self.live_stdout = self.live_stderr = setting.is_a?(String) ? String.new(setting) : setting
|
|
338
342
|
when "live_stdout"
|
|
339
|
-
self.live_stdout = setting
|
|
343
|
+
self.live_stdout = setting.is_a?(String) ? String.new(setting) : setting
|
|
340
344
|
when "live_stderr"
|
|
341
|
-
self.live_stderr = setting
|
|
345
|
+
self.live_stderr = setting.is_a?(String) ? String.new(setting) : setting
|
|
342
346
|
when "input"
|
|
343
347
|
self.input = setting
|
|
344
348
|
when "logger"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mixlib-shellout
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chef Software Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-12-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chef-utils
|
|
@@ -50,14 +50,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '3.
|
|
53
|
+
version: '3.1'
|
|
54
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
55
|
requirements:
|
|
56
56
|
- - ">="
|
|
57
57
|
- !ruby/object:Gem::Version
|
|
58
58
|
version: '0'
|
|
59
59
|
requirements: []
|
|
60
|
-
rubygems_version: 3.
|
|
60
|
+
rubygems_version: 3.3.27
|
|
61
61
|
signing_key:
|
|
62
62
|
specification_version: 4
|
|
63
63
|
summary: Run external commands on Unix or Windows
|