expect-pty 0.6.1 → 0.7.2
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/CHANGELOG.md +34 -3
- data/README.md +103 -120
- data/docs/API.md +76 -51
- data/docs/MIGRATION.md +68 -15
- data/lib/expect/cleanup.rb +4 -3
- data/lib/expect/interaction.rb +57 -56
- data/lib/expect/logging.rb +60 -106
- data/lib/expect/matcher.rb +22 -19
- data/lib/expect/pattern.rb +2 -1
- data/lib/expect/pattern_list.rb +5 -5
- data/lib/expect/redactor.rb +1 -1
- data/lib/expect/relay.rb +20 -19
- data/lib/expect/relay_writer.rb +5 -4
- data/lib/expect/result.rb +1 -1
- data/lib/expect/session.rb +114 -68
- data/lib/expect/session_resources.rb +10 -17
- data/lib/expect/version.rb +2 -2
- data/lib/expect.rb +47 -370
- data/sig/expect.rbs +203 -279
- metadata +5 -21
- data/lib/expect/configuration.rb +0 -143
- data/lib/expect/terminal.rb +0 -102
data/lib/expect.rb
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
require "pty"
|
|
4
4
|
require "io/console"
|
|
5
5
|
require "stringio"
|
|
6
|
-
require "forwardable"
|
|
7
6
|
require_relative "expect/version"
|
|
8
|
-
require_relative "expect/configuration"
|
|
9
7
|
require_relative "expect/result"
|
|
10
8
|
require_relative "expect/session_resources"
|
|
11
9
|
require_relative "expect/pattern"
|
|
@@ -14,30 +12,28 @@ require_relative "expect/matcher"
|
|
|
14
12
|
require_relative "expect/cleanup"
|
|
15
13
|
require_relative "expect/session"
|
|
16
14
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# 回调控制符:分别表示重置期限后继续,或保留原期限继续。
|
|
15
|
+
# PTY 会话的创建、匹配与转接入口;可变状态只属于返回的 Session。
|
|
16
|
+
module Expect
|
|
17
|
+
# 重置相对期限后继续等待。
|
|
21
18
|
CONTINUE = :continue
|
|
22
|
-
#
|
|
19
|
+
# 保留原相对期限继续等待。
|
|
23
20
|
CONTINUE_WITHOUT_RESET = :continue_without_reset
|
|
24
21
|
# 单轮非阻塞读写的最大字节数。
|
|
25
22
|
# @api private
|
|
26
23
|
READ_SIZE = 16_384
|
|
27
|
-
CONFIGURATION_MUTEX = Mutex.new
|
|
28
|
-
private_constant :CONFIGURATION_MUTEX
|
|
29
24
|
|
|
30
25
|
# PTY 创建后命令启动失败。
|
|
31
26
|
class SpawnError < StandardError; end
|
|
27
|
+
|
|
32
28
|
# 同一个来源不能同时交给两个 Relay。
|
|
33
29
|
class ReentrancyError < StandardError; end
|
|
34
30
|
|
|
35
|
-
#
|
|
31
|
+
# 本次写入已经确认交付的进度;其他嵌套写入的异常保留在 cause。
|
|
36
32
|
class WriteTimeout < IOError
|
|
33
|
+
# 本次 write 已被底层接受的字节数。
|
|
37
34
|
attr_reader :bytes_written
|
|
38
35
|
|
|
39
|
-
#
|
|
40
|
-
# @param bytes_written [Integer] 已交付字节数。
|
|
36
|
+
# 构造包含已交付字节数的背压超时。
|
|
41
37
|
def initialize(message = "write timed out", bytes_written: 0)
|
|
42
38
|
@bytes_written = bytes_written
|
|
43
39
|
super(message)
|
|
@@ -45,103 +41,63 @@ class Expect
|
|
|
45
41
|
end
|
|
46
42
|
|
|
47
43
|
class << self
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
CONFIGURATION_MUTEX.synchronize { @configuration ||= Configuration.new.freeze }
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# 基于旧快照构造可修改副本,全部赋值与配置块成功后才发布,异常时保留原配置。
|
|
58
|
-
# 配置关键字覆盖默认值,未知键抛出 ArgumentError。
|
|
59
|
-
# @yieldparam configuration [Expect::Configuration] 发布前可修改的副本。
|
|
60
|
-
# @return [Expect::Configuration] 新发布的冻结快照。
|
|
61
|
-
def configure(**)
|
|
62
|
-
raise ThreadError, "nested configure is not supported" if CONFIGURATION_MUTEX.owned?
|
|
63
|
-
|
|
64
|
-
# 初始化默认快照后,将整个读改写过程串行化,避免并发配置丢失更新。
|
|
65
|
-
configuration
|
|
66
|
-
CONFIGURATION_MUTEX.synchronize do
|
|
67
|
-
updated = Configuration.new(**configuration.to_h, **)
|
|
68
|
-
yield updated if block_given?
|
|
69
|
-
@configuration = updated.freeze
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# 创建并启动会话;有块时返回块结果并确保关闭,无块时由调用方负责生命周期。
|
|
74
|
-
# @param command [Array<String>] 命令及参数;单字符串遵循 Ruby 自动 shell 语义,多参数按 argv 执行。
|
|
75
|
-
# @param env [Hash<String, String, nil>] 子进程环境覆盖。
|
|
76
|
-
# @param chdir [String, nil] 子进程工作目录。
|
|
77
|
-
# @yieldparam connection [Expect] 自动关闭的用户会话。
|
|
78
|
-
# @return [Expect, Object] 无块返回会话,有块返回块结果。
|
|
79
|
-
def spawn(*command, env: {}, chdir: nil, **)
|
|
80
|
-
connection = nil
|
|
44
|
+
# 创建并启动 Session;有块时返回块结果,并按 graceful 策略关闭所属资源。
|
|
45
|
+
# raw 只控制本次子进程 PTY;日志与输出对象始终借用。
|
|
46
|
+
def spawn(*command, env: {}, chdir: nil, raw: false, graceful: false,
|
|
47
|
+
timeout: nil, write_timeout: nil, buffer_limit: nil, logger: nil, transcript: nil, outputs: [])
|
|
48
|
+
session = nil
|
|
81
49
|
spawned = false
|
|
82
|
-
cleanup = -> {
|
|
50
|
+
cleanup = -> { session&.close(graceful: spawned && graceful) if block_given? || !spawned }
|
|
83
51
|
Cleanup.always(cleanup) do
|
|
84
|
-
|
|
85
|
-
|
|
52
|
+
session = Session.new(timeout:, write_timeout:, buffer_limit:, logger:, transcript:, outputs:)
|
|
53
|
+
session.spawn(*command, env:, chdir:, raw:)
|
|
86
54
|
spawned = true
|
|
87
|
-
block_given? ? yield(
|
|
55
|
+
block_given? ? yield(session) : session
|
|
88
56
|
end
|
|
89
57
|
end
|
|
90
58
|
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
# @return [Expect, Object] 无块返回会话,有块返回块结果。
|
|
97
|
-
def open(io, writer: io, own: false, **)
|
|
98
|
-
connection = nil
|
|
59
|
+
# 适配真实 IO;own 只决定读写端点的关闭责任,日志与输出目标仍由调用者管理。
|
|
60
|
+
# 有块时返回块结果;初始化失败也清理已取得的所属端点。
|
|
61
|
+
def open(io, writer: io, own: false, graceful: false,
|
|
62
|
+
timeout: nil, write_timeout: nil, buffer_limit: nil, logger: nil, transcript: nil, outputs: [])
|
|
63
|
+
session = nil
|
|
99
64
|
initialized = false
|
|
100
65
|
cleanup = lambda do
|
|
101
|
-
if
|
|
102
|
-
|
|
103
|
-
|
|
66
|
+
if session && (block_given? || !initialized)
|
|
67
|
+
session.cleanup_session(io, writer:, own:, graceful: initialized && graceful)
|
|
68
|
+
elsif !session && own
|
|
69
|
+
SessionResources.close_handles(io, writer)
|
|
104
70
|
end
|
|
105
71
|
end
|
|
106
72
|
Cleanup.always(cleanup) do
|
|
107
|
-
|
|
108
|
-
|
|
73
|
+
session = Session.allocate
|
|
74
|
+
session.__send__(:initialize_io, io, writer:, own:, timeout:, write_timeout:, buffer_limit:,
|
|
75
|
+
logger:, transcript:, outputs:)
|
|
109
76
|
initialized = true
|
|
110
|
-
block_given? ? yield(
|
|
77
|
+
block_given? ? yield(session) : session
|
|
111
78
|
end
|
|
112
79
|
end
|
|
113
80
|
|
|
114
|
-
# 按
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# @return [Expect, nil] 停止来源;总期限到达返回 nil。
|
|
118
|
-
def interconnect(*connections, timeout: nil)
|
|
119
|
-
raise ArgumentError, "interconnect requires Expect sessions" unless connections.any? && connections.all?(Expect)
|
|
81
|
+
# 按 outputs 建立转发图,返回引发停止的 Session;总期限到达返回 nil。
|
|
82
|
+
def interconnect(*sessions, timeout: nil)
|
|
83
|
+
raise ArgumentError, "interconnect requires Session objects" unless sessions.any? && sessions.all?(Session)
|
|
120
84
|
|
|
121
|
-
Relay.new(
|
|
85
|
+
Relay.new(sessions, timeout).run
|
|
122
86
|
end
|
|
123
87
|
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# @yieldparam patterns [Expect::PatternList] 有参数块接收构建器;无参数块以 DSL 执行。
|
|
129
|
-
# @return [Expect::Result] 本次等待的不可变快照。
|
|
130
|
-
def expect(*patterns, from: [], timeout: configuration.timeout, deadline: nil, &)
|
|
131
|
-
run_expect(from, patterns, timeout, deadline:, &)
|
|
88
|
+
# 共同等待指定来源,返回不可变 Result。consume 控制本轮是否消费匹配文本。
|
|
89
|
+
# reset_timeout_on_read 仅重置相对期限,deadline 始终是不可延长的总期限。
|
|
90
|
+
def expect(*patterns, from: [], timeout: nil, deadline: nil, consume: true, reset_timeout_on_read: false, &)
|
|
91
|
+
run_expect(from, patterns, timeout, deadline:, consume:, reset_timeout_on_read:, &)
|
|
132
92
|
end
|
|
133
93
|
|
|
134
|
-
#
|
|
135
|
-
# @return [Symbol] 重置期限或保持期限的继续控制符。
|
|
94
|
+
# 返回回调继续控制符,reset_timeout 为 false 时保留原相对期限。
|
|
136
95
|
def continue(reset_timeout: true) = reset_timeout ? CONTINUE : CONTINUE_WITHOUT_RESET
|
|
137
96
|
|
|
138
|
-
#
|
|
139
|
-
# @return [Float] 当前单调时钟秒数。
|
|
97
|
+
# 当前单调时钟秒数;供跨多次等待共享 deadline。
|
|
140
98
|
def monotonic = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
141
99
|
|
|
142
|
-
#
|
|
143
|
-
# @param value [Numeric, String, nil] 可转换为有限非负秒数的值。
|
|
144
|
-
# @return [Float, nil] 校验后的秒数。
|
|
100
|
+
# 转换有限非负秒数,nil 表示无相对期限。
|
|
145
101
|
def duration(value)
|
|
146
102
|
return nil if value.nil?
|
|
147
103
|
|
|
@@ -151,12 +107,10 @@ class Expect
|
|
|
151
107
|
number
|
|
152
108
|
end
|
|
153
109
|
|
|
154
|
-
#
|
|
155
|
-
# @param sessions [Array<Expect>] 待读取来源。
|
|
156
|
-
# @return [Array<Expect>] 就绪来源,保持声明顺序。
|
|
110
|
+
# 返回可读 Session,不消费输入;去重、排除已关闭来源,并保留声明顺序。
|
|
157
111
|
def readable_sessions(*sessions, timeout: 0)
|
|
158
112
|
timeout = duration(timeout)
|
|
159
|
-
raise ArgumentError, "readable_sessions requires
|
|
113
|
+
raise ArgumentError, "readable_sessions requires Session objects" unless sessions.all?(Session)
|
|
160
114
|
|
|
161
115
|
active = sessions.uniq(&:object_id).reject(&:closed?)
|
|
162
116
|
return [] if active.empty?
|
|
@@ -182,14 +136,14 @@ class Expect
|
|
|
182
136
|
|
|
183
137
|
private
|
|
184
138
|
|
|
185
|
-
#
|
|
139
|
+
# 按对象身份归属就绪描述符,不能用 IO 的值相等规则合并来源。
|
|
186
140
|
def select_ready_sessions(sessions, readable)
|
|
187
141
|
by_io = readable.each_with_object({}.compare_by_identity) { |io, index| index[io] = true }
|
|
188
142
|
sessions.select { |session| by_io.key?(session.to_io) }
|
|
189
143
|
end
|
|
190
144
|
|
|
191
|
-
#
|
|
192
|
-
def run_expect(sessions, patterns, timeout, deadline
|
|
145
|
+
# 声明完成后固定模式;有参数块保留调用方 self,无参数块使用模式 DSL。
|
|
146
|
+
def run_expect(sessions, patterns, timeout, deadline:, consume:, reset_timeout_on_read:, &block)
|
|
193
147
|
timeout = duration(timeout)
|
|
194
148
|
deadline = Float(deadline) unless deadline.nil?
|
|
195
149
|
raise ArgumentError, "deadline must be finite" if deadline && !deadline.finite?
|
|
@@ -199,284 +153,7 @@ class Expect
|
|
|
199
153
|
if block
|
|
200
154
|
block.parameters.empty? ? pattern_list.instance_exec(&block) : block.call(pattern_list)
|
|
201
155
|
end
|
|
202
|
-
Matcher.new(pattern_list, timeout, deadline:).run
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
extend Forwardable
|
|
207
|
-
|
|
208
|
-
# @!method <<(object)
|
|
209
|
-
# 执行操作并返回当前用户会话,支持链式使用。
|
|
210
|
-
# @return [Expect]
|
|
211
|
-
# @!method after
|
|
212
|
-
# 读取最近结果中的字节快照;尚无结果时为 nil。
|
|
213
|
-
# @return [String, nil]
|
|
214
|
-
# @!method alive?
|
|
215
|
-
# 查询当前会话状态;输入结束、进程退出和关闭分别记录。
|
|
216
|
-
# @return [Boolean]
|
|
217
|
-
# @!method before
|
|
218
|
-
# 读取最近结果中的字节快照;尚无结果时为 nil。
|
|
219
|
-
# @return [String, nil]
|
|
220
|
-
# @!method buffer
|
|
221
|
-
# 取得接收字节;buffer 返回副本,clear_buffer 移交并清空现有内容。
|
|
222
|
-
# @return [String]
|
|
223
|
-
# @!method buffer=(value)
|
|
224
|
-
# 校验并替换当前设置;缓冲和集合采用副本,IO 与回调只借用。
|
|
225
|
-
# @return [void]
|
|
226
|
-
# @!method buffer_discarded_bytes
|
|
227
|
-
# 读取因匹配窗口上限裁剪而丢弃的累计字节数。
|
|
228
|
-
# @return [Integer]
|
|
229
|
-
# @!method buffer_limit
|
|
230
|
-
# 读取会话独立配置;更改类级默认值不会追溯影响已建立会话。
|
|
231
|
-
# @return [Integer, nil]
|
|
232
|
-
# @!method buffer_limit=(value)
|
|
233
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
234
|
-
# @return [void]
|
|
235
|
-
# @!method captures
|
|
236
|
-
# 读取最近捕获组;未参与的组为 nil,尚无结果时为空数组。
|
|
237
|
-
# @return [Array<String, nil>]
|
|
238
|
-
# @!method clear_buffer
|
|
239
|
-
# 取得接收字节;buffer 返回副本,clear_buffer 移交并清空现有内容。
|
|
240
|
-
# @return [String]
|
|
241
|
-
# @!method close(graceful: graceful_close?)
|
|
242
|
-
# 关闭所属资源并回收子进程;graceful 启用先收尾输出,硬关闭始终兜底。
|
|
243
|
-
# @return [nil]
|
|
244
|
-
# @!method closed?
|
|
245
|
-
# 查询当前会话状态;输入结束、进程退出和关闭分别记录。
|
|
246
|
-
# @return [Boolean]
|
|
247
|
-
# @!method command
|
|
248
|
-
# 读取已启动命令的冻结参数快照,未启动时为 nil。
|
|
249
|
-
# @return [Array<String>, nil]
|
|
250
|
-
# @!method debug_level
|
|
251
|
-
# 读取会话独立配置;更改类级默认值不会追溯影响已建立会话。
|
|
252
|
-
# @return [Integer]
|
|
253
|
-
# @!method debug_level=(value)
|
|
254
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
255
|
-
# @return [void]
|
|
256
|
-
# @!method diagnostic_output
|
|
257
|
-
# 读取借用的诊断目标;nil 使用 stderr。
|
|
258
|
-
# @return [#info, #write, Proc, nil]
|
|
259
|
-
# @!method diagnostic_output=(value)
|
|
260
|
-
# 校验并替换当前设置;缓冲和集合采用副本,IO 与回调只借用。
|
|
261
|
-
# @return [void]
|
|
262
|
-
# @!method eof?
|
|
263
|
-
# 查询当前会话状态;输入结束、进程退出和关闭分别记录。
|
|
264
|
-
# @return [Boolean]
|
|
265
|
-
# @!method error
|
|
266
|
-
# 读取最近 EOF、超时或原始 IO 错误,匹配成功时为 nil。
|
|
267
|
-
# @return [Symbol, Exception, nil]
|
|
268
|
-
# @!method exit_code
|
|
269
|
-
# 读取对应进程、IO 或匹配属性;尚无可用值时为 nil。
|
|
270
|
-
# @return [Integer, nil]
|
|
271
|
-
# @!method fileno
|
|
272
|
-
# 读取对应进程、IO 或匹配属性;尚无可用值时为 nil。
|
|
273
|
-
# @return [Integer, nil]
|
|
274
|
-
# @!method graceful_close=(value)
|
|
275
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
276
|
-
# @return [void]
|
|
277
|
-
# @!method graceful_close?
|
|
278
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
279
|
-
# @return [Boolean]
|
|
280
|
-
# @!method hard_close(timeout: 0.2)
|
|
281
|
-
# 等待或回收子进程,未取得真实状态时返回 nil;期限以秒计。
|
|
282
|
-
# @return [Process::Status, nil]
|
|
283
|
-
# @!method interact(input: $stdin, escape: nil, output: nil, timeout: nil)
|
|
284
|
-
# 临时转接输入和输出,退出时恢复终端与监听设置;超时返回 nil。
|
|
285
|
-
# @return [Expect, nil]
|
|
286
|
-
# @!method last_result
|
|
287
|
-
# 读取最近一次等待的不可变结果。
|
|
288
|
-
# @return [Expect::Result, nil]
|
|
289
|
-
# @!method listeners
|
|
290
|
-
# 读取监听目标数组的副本;监听器只借用,不随会话关闭。
|
|
291
|
-
# @return [Array<#write>]
|
|
292
|
-
# @!method listeners=(value)
|
|
293
|
-
# 校验并替换当前设置;缓冲和集合采用副本,IO 与回调只借用。
|
|
294
|
-
# @return [void]
|
|
295
|
-
# @!method log_listeners=(value)
|
|
296
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
297
|
-
# @return [void]
|
|
298
|
-
# @!method log_listeners?
|
|
299
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
300
|
-
# @return [Boolean]
|
|
301
|
-
# @!method log_output
|
|
302
|
-
# 读取当前接收日志目标,不包含发送数据。
|
|
303
|
-
# @return [#write, Proc, nil]
|
|
304
|
-
# @!method log_output=(value)
|
|
305
|
-
# 校验并替换当前设置;缓冲和集合采用副本,IO 与回调只借用。
|
|
306
|
-
# @return [void]
|
|
307
|
-
# @!method log_stdout=(value)
|
|
308
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
309
|
-
# @return [void]
|
|
310
|
-
# @!method log_stdout?
|
|
311
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
312
|
-
# @return [Boolean]
|
|
313
|
-
# @!method log_to(target = nil, mode: "a", &block)
|
|
314
|
-
# 设置借用日志目标或打开所属日志文件;返回目标。
|
|
315
|
-
# @return [#write, Proc]
|
|
316
|
-
# @yieldparam bytes [String] 实际读取的字节。
|
|
317
|
-
# @yieldreturn [Object] 回调返回值不影响匹配。
|
|
318
|
-
# @!method match
|
|
319
|
-
# 读取最近结果中的字节快照;尚无结果时为 nil。
|
|
320
|
-
# @return [String, nil]
|
|
321
|
-
# @!method match_number
|
|
322
|
-
# 读取对应进程、IO 或匹配属性;尚无可用值时为 nil。
|
|
323
|
-
# @return [Integer, nil]
|
|
324
|
-
# @!method on_sequence(sequence, &block)
|
|
325
|
-
# 执行操作并返回当前用户会话,支持链式使用。
|
|
326
|
-
# @return [Expect]
|
|
327
|
-
# @yield 转义匹配完成后运行,nil/false 停止,其余返回值继续。
|
|
328
|
-
# @yieldreturn [Object] 是否继续转接。
|
|
329
|
-
# @!method pending_output?
|
|
330
|
-
# 查询当前会话状态;输入结束、进程退出和关闭分别记录。
|
|
331
|
-
# @return [Boolean]
|
|
332
|
-
# @!method pid
|
|
333
|
-
# 读取对应进程、IO 或匹配属性;尚无可用值时为 nil。
|
|
334
|
-
# @return [Integer, nil]
|
|
335
|
-
# @!method preserve_buffer=(value)
|
|
336
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
337
|
-
# @return [void]
|
|
338
|
-
# @!method preserve_buffer?
|
|
339
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
340
|
-
# @return [Boolean]
|
|
341
|
-
# @!method process_status
|
|
342
|
-
# 非阻塞回收直属子进程并读取真实状态;未知时保留 nil。
|
|
343
|
-
# @return [Process::Status, nil]
|
|
344
|
-
# @!method puts(*objects)
|
|
345
|
-
# 按 Ruby puts 语义转换换行、nil 和数组后写入。
|
|
346
|
-
# @return [nil]
|
|
347
|
-
# @!method raw_pty=(value)
|
|
348
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
349
|
-
# @return [void]
|
|
350
|
-
# @!method raw_pty?
|
|
351
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
352
|
-
# @return [Boolean]
|
|
353
|
-
# @!method raw_terminal=(value)
|
|
354
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
355
|
-
# @return [void]
|
|
356
|
-
# @!method raw_terminal?
|
|
357
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
358
|
-
# @return [Boolean]
|
|
359
|
-
# @!method redact(*secrets)
|
|
360
|
-
# 执行操作并返回当前用户会话,支持链式使用。
|
|
361
|
-
# @return [Expect]
|
|
362
|
-
# @!method reset_timeout_on_read=(value)
|
|
363
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
364
|
-
# @return [void]
|
|
365
|
-
# @!method reset_timeout_on_read?
|
|
366
|
-
# 按 Ruby 真值规则查询此布尔配置。
|
|
367
|
-
# @return [Boolean]
|
|
368
|
-
# @!method send_slow(*objects, delay:)
|
|
369
|
-
# 返回已写字节数;背压超时抛出 WriteTimeout 并保留 bytes_written。
|
|
370
|
-
# @return [Integer]
|
|
371
|
-
# @!method slave
|
|
372
|
-
# 读取 PTY slave;适配已有 IO 时为 nil,启动后句柄已关闭。
|
|
373
|
-
# @return [IO, nil]
|
|
374
|
-
# @!method soft_close(timeout: 15, term_timeout: 1)
|
|
375
|
-
# 等待或回收子进程,未取得真实状态时返回 nil;期限以秒计。
|
|
376
|
-
# @return [Process::Status, nil]
|
|
377
|
-
# @!method spawn(*command, env: {}, chdir: nil)
|
|
378
|
-
# 执行操作并返回当前用户会话,支持链式使用。
|
|
379
|
-
# @return [Expect]
|
|
380
|
-
# @!method stty(*modes)
|
|
381
|
-
# 查询或设置终端模式;非 TTY 返回空字符串,失败抛出 IO 错误。
|
|
382
|
-
# @return [String]
|
|
383
|
-
# @!method timeout
|
|
384
|
-
# 读取会话独立配置;更改类级默认值不会追溯影响已建立会话。
|
|
385
|
-
# @return [Numeric, nil]
|
|
386
|
-
# @!method timeout=(value)
|
|
387
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
388
|
-
# @return [void]
|
|
389
|
-
# @!method to_io
|
|
390
|
-
# 取得底层读端或写端,不复制描述符。
|
|
391
|
-
# @return [IO]
|
|
392
|
-
# @!method tty?
|
|
393
|
-
# 查询当前会话状态;输入结束、进程退出和关闭分别记录。
|
|
394
|
-
# @return [Boolean]
|
|
395
|
-
# @!method tty_name
|
|
396
|
-
# 读取 PTY 终端路径;适配已有 IO 时为 nil。
|
|
397
|
-
# @return [String, nil]
|
|
398
|
-
# @!method wait(timeout: nil)
|
|
399
|
-
# 等待或回收子进程,未取得真实状态时返回 nil;期限以秒计。
|
|
400
|
-
# @return [Process::Status, nil]
|
|
401
|
-
# @!method winsize
|
|
402
|
-
# 读取终端行列数,保留原生 IO 错误。
|
|
403
|
-
# @return [Array<Integer>]
|
|
404
|
-
# @!method winsize=(value)
|
|
405
|
-
# 校验并替换当前设置;缓冲和集合采用副本,IO 与回调只借用。
|
|
406
|
-
# @return [void]
|
|
407
|
-
# @!method write(*objects)
|
|
408
|
-
# 返回已写字节数;背压超时抛出 WriteTimeout 并保留 bytes_written。
|
|
409
|
-
# @return [Integer]
|
|
410
|
-
# @!method write_log(*objects)
|
|
411
|
-
# 向当前接收日志补写数据;返回目标调用结果,过滤暂存时可为 nil。
|
|
412
|
-
# @return [Object]
|
|
413
|
-
# @!method write_timeout
|
|
414
|
-
# 读取会话独立配置;更改类级默认值不会追溯影响已建立会话。
|
|
415
|
-
# @return [Numeric, nil]
|
|
416
|
-
# @!method write_timeout=(value)
|
|
417
|
-
# 校验并设置会话配置;非法数值不改变当前值,布尔值遵循 Ruby 真值。
|
|
418
|
-
# @return [void]
|
|
419
|
-
# @!method writer
|
|
420
|
-
# 取得底层读端或写端,不复制描述符。
|
|
421
|
-
# @return [IO]
|
|
422
|
-
# @!method inspect
|
|
423
|
-
# 返回不含缓冲、命令或秘密内容的安全诊断摘要。
|
|
424
|
-
# @return [String]
|
|
425
|
-
# 用户会话只委托稳定接口,内核读写、转接标记和资源账本不出现在公开方法中。
|
|
426
|
-
def_delegators :@session,
|
|
427
|
-
:<<, :after, :alive?, :before, :buffer, :buffer=, :buffer_discarded_bytes, :buffer_limit,
|
|
428
|
-
:buffer_limit=, :captures, :clear_buffer, :close, :closed?, :command, :debug_level,
|
|
429
|
-
:debug_level=, :diagnostic_output, :diagnostic_output=, :eof?, :error, :exit_code, :fileno,
|
|
430
|
-
:graceful_close=, :graceful_close?, :hard_close, :interact, :last_result,
|
|
431
|
-
:listeners, :listeners=, :log_listeners=, :log_listeners?, :log_output,
|
|
432
|
-
:log_output=, :log_stdout=, :log_stdout?, :log_to, :match, :match_number,
|
|
433
|
-
:on_sequence, :pending_output?, :pid, :preserve_buffer=, :preserve_buffer?,
|
|
434
|
-
:process_status, :puts, :raw_pty=, :raw_pty?, :raw_terminal=,
|
|
435
|
-
:raw_terminal?, :redact, :reset_timeout_on_read=,
|
|
436
|
-
:reset_timeout_on_read?, :send_slow, :slave, :soft_close, :spawn, :stty, :timeout, :timeout=,
|
|
437
|
-
:to_io, :tty?, :tty_name, :wait, :winsize, :winsize=, :write, :write_log, :write_timeout,
|
|
438
|
-
:write_timeout=, :writer, :inspect
|
|
439
|
-
|
|
440
|
-
# 创建 PTY,可立即执行命令;未完成初始化时按局部所有权释放全部句柄。
|
|
441
|
-
# @param command [Array<String>] 可选启动命令及参数。
|
|
442
|
-
# @return [Expect] 已创建的用户会话。
|
|
443
|
-
def initialize(*command, env: {}, chdir: nil, **)
|
|
444
|
-
master = slave = nil
|
|
445
|
-
Cleanup.on_failure(-> { cleanup_session(master, writer: master, slave:, own: true) }) do
|
|
446
|
-
master, slave = PTY.open
|
|
447
|
-
initialize_session(master, writer: master, slave:, own: true, **)
|
|
448
|
-
spawn(*command, env:, chdir:) unless command.empty?
|
|
449
|
-
end
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
# 返回不可变结果;模式块无参数时使用 DSL,有参数时保留调用者 self。
|
|
453
|
-
# @param patterns [Array<String, Regexp, Symbol>] 文本模式、:eof 或 :timeout。
|
|
454
|
-
# @param timeout [Numeric, nil] 相对秒数,nil 无限,0 非阻塞轮询。
|
|
455
|
-
# @param deadline [Numeric, nil] 单调时钟绝对期限,不被回调延长。
|
|
456
|
-
# @yieldparam patterns [Expect::PatternList] 有参数块接收构建器;无参数块以 DSL 执行。
|
|
457
|
-
# @return [Expect::Result] 本次等待的不可变快照。
|
|
458
|
-
def expect(*patterns, timeout: self.timeout, deadline: nil, &)
|
|
459
|
-
self.class.__send__(:run_expect, [self], patterns, timeout, deadline:, &)
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
# 返回回调继续控制符,可选择保持原期限。
|
|
463
|
-
# @return [Symbol] 重置期限或保持期限的继续控制符。
|
|
464
|
-
def continue(reset_timeout: true) = Expect.continue(reset_timeout:)
|
|
465
|
-
|
|
466
|
-
private
|
|
467
|
-
|
|
468
|
-
attr_reader :session
|
|
469
|
-
|
|
470
|
-
def initialize_session(reader, **)
|
|
471
|
-
@session = Session.allocate
|
|
472
|
-
@session.initialize_connection(self, reader, **)
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
def cleanup_session(reader, writer:, own:, slave: nil, graceful: false)
|
|
476
|
-
if @session
|
|
477
|
-
@session.cleanup_session(reader, writer:, own:, slave:, graceful:)
|
|
478
|
-
elsif own
|
|
479
|
-
SessionResources.close_handles(reader, writer, slave)
|
|
156
|
+
Matcher.new(pattern_list, timeout, deadline:, consume:, reset_timeout_on_read:).run
|
|
480
157
|
end
|
|
481
158
|
end
|
|
482
159
|
end
|