ronin-post_ex 0.1.0.beta1
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 +7 -0
- data/.document +6 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/API_SPEC.md +235 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +23 -0
- data/Gemfile +36 -0
- data/README.md +245 -0
- data/Rakefile +34 -0
- data/examples/bind_shell.rb +19 -0
- data/gemspec.yml +25 -0
- data/lib/ronin/post_ex/cli/shell_shell.rb +66 -0
- data/lib/ronin/post_ex/cli/system_shell.rb +811 -0
- data/lib/ronin/post_ex/remote_dir.rb +190 -0
- data/lib/ronin/post_ex/remote_file/stat.rb +174 -0
- data/lib/ronin/post_ex/remote_file.rb +417 -0
- data/lib/ronin/post_ex/remote_process.rb +170 -0
- data/lib/ronin/post_ex/resource.rb +144 -0
- data/lib/ronin/post_ex/sessions/bind_shell.rb +60 -0
- data/lib/ronin/post_ex/sessions/remote_shell_session.rb +48 -0
- data/lib/ronin/post_ex/sessions/reverse_shell.rb +67 -0
- data/lib/ronin/post_ex/sessions/rpc_session.rb +779 -0
- data/lib/ronin/post_ex/sessions/session.rb +73 -0
- data/lib/ronin/post_ex/sessions/shell_session.rb +618 -0
- data/lib/ronin/post_ex/system/fs.rb +650 -0
- data/lib/ronin/post_ex/system/process.rb +422 -0
- data/lib/ronin/post_ex/system/shell.rb +1037 -0
- data/lib/ronin/post_ex/system.rb +191 -0
- data/lib/ronin/post_ex/version.rb +26 -0
- data/lib/ronin/post_ex.rb +22 -0
- data/ronin-post_ex.gemspec +61 -0
- data/spec/sessions/bind_shell_spec.rb +31 -0
- data/spec/sessions/remote_shell_session_spec.rb +28 -0
- data/spec/sessions/reverse_shell_spec.rb +49 -0
- data/spec/sessions/rpc_session_spec.rb +500 -0
- data/spec/sessions/session_spec.rb +61 -0
- data/spec/sessions/shell_session_spec.rb +482 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/system_spec.rb +66 -0
- metadata +155 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-post_ex - a Ruby API for Post-Exploitation.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-post_ex is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-post_ex is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-post_ex. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/post_ex/system'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module PostEx
|
25
|
+
module Sessions
|
26
|
+
#
|
27
|
+
# Base class for all post-exploitation session classes.
|
28
|
+
#
|
29
|
+
class Session
|
30
|
+
|
31
|
+
#
|
32
|
+
# The session name.
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
# @raise [NotImplementedError]
|
37
|
+
# The session class did not set `@name`.
|
38
|
+
#
|
39
|
+
def name
|
40
|
+
@name || raise(NotImplementedError,"#{self.class}#name was not set")
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# The remote system connected to the session.
|
45
|
+
#
|
46
|
+
# @return [System]
|
47
|
+
#
|
48
|
+
def system
|
49
|
+
@system ||= System.new(self)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Closes the session.
|
54
|
+
#
|
55
|
+
# @abstract
|
56
|
+
#
|
57
|
+
def close
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Converts the session to a String.
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
# The session's {#name}.
|
65
|
+
#
|
66
|
+
def to_s
|
67
|
+
name
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,618 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-post_ex - a Ruby API for Post-Exploitation.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-post_ex is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-post_ex is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-post_ex. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/post_ex/sessions/session'
|
22
|
+
|
23
|
+
require 'shellwords'
|
24
|
+
require 'base64'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module PostEx
|
28
|
+
module Sessions
|
29
|
+
#
|
30
|
+
# Base class for all interactive shell based post-exploitation sessions.
|
31
|
+
#
|
32
|
+
# ## Features
|
33
|
+
#
|
34
|
+
# * Supports Bash, Zsh, and all POSIX shells.
|
35
|
+
# * Emulates most of the post-exploitation API via shell commands.
|
36
|
+
#
|
37
|
+
class ShellSession < Session
|
38
|
+
|
39
|
+
# The IO object used to communicate with the shell.
|
40
|
+
#
|
41
|
+
# @return [Socket, IO]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
attr_reader :io
|
45
|
+
|
46
|
+
#
|
47
|
+
# Initializes the shell session.
|
48
|
+
#
|
49
|
+
# @param [Socet, IO] io
|
50
|
+
# The IO object used to communicate with the shell.
|
51
|
+
#
|
52
|
+
def initialize(io)
|
53
|
+
@io = io
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# @group Shell Methods
|
58
|
+
#
|
59
|
+
|
60
|
+
#
|
61
|
+
# Writes a line to the shell.
|
62
|
+
#
|
63
|
+
# @param [String] line
|
64
|
+
# The line to write.
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
#
|
68
|
+
def shell_puts(line)
|
69
|
+
@io.write("#{line}\n")
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Reads a line from the shell.
|
74
|
+
#
|
75
|
+
# @return [String, nil]
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
#
|
79
|
+
def shell_gets
|
80
|
+
@io.gets
|
81
|
+
end
|
82
|
+
|
83
|
+
# Deliminator line to indicate the beginning and end of output
|
84
|
+
DELIMINATOR = '---'
|
85
|
+
|
86
|
+
#
|
87
|
+
# Executes a shell command and returns it's output.
|
88
|
+
#
|
89
|
+
# @param [String] command
|
90
|
+
# The shell command to execute.
|
91
|
+
#
|
92
|
+
# @return [String]
|
93
|
+
# The output of the shell command.
|
94
|
+
#
|
95
|
+
def shell_exec(command)
|
96
|
+
shell_puts("echo #{DELIMINATOR}; #{command} 2>/dev/null | base64; echo #{DELIMINATOR}")
|
97
|
+
|
98
|
+
# consume any leading output before the command output
|
99
|
+
while (line = shell_gets)
|
100
|
+
if line.chomp == DELIMINATOR
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
output = String.new
|
106
|
+
|
107
|
+
while (line = shell_gets)
|
108
|
+
if line.chomp == DELIMINATOR
|
109
|
+
break
|
110
|
+
end
|
111
|
+
|
112
|
+
output << line
|
113
|
+
end
|
114
|
+
|
115
|
+
return Base64.decode64(output)
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Joins a command with arguments into a single command String.
|
120
|
+
#
|
121
|
+
# @param [String] command
|
122
|
+
# The command name to execute.
|
123
|
+
#
|
124
|
+
# @param [Array<String>] arguments
|
125
|
+
# Additional arguments for the command.
|
126
|
+
#
|
127
|
+
# @return [String]
|
128
|
+
# The command string.
|
129
|
+
#
|
130
|
+
# @api private
|
131
|
+
#
|
132
|
+
def command_join(command,*arguments)
|
133
|
+
Shellwords.join([command,*arguments])
|
134
|
+
end
|
135
|
+
|
136
|
+
#
|
137
|
+
# Invokes a specific command with arguments.
|
138
|
+
#
|
139
|
+
# @param [String] command
|
140
|
+
# The command name to execute.
|
141
|
+
#
|
142
|
+
# @param [Array<String>] arguments
|
143
|
+
# Additional arguments for the command.
|
144
|
+
#
|
145
|
+
# @return [String, nil]
|
146
|
+
# The command's output or `nil` if there was no output.
|
147
|
+
#
|
148
|
+
# @api private
|
149
|
+
#
|
150
|
+
def command_exec(command,*arguments)
|
151
|
+
output = shell_exec(command_join(command,*arguments))
|
152
|
+
|
153
|
+
if output.empty? then nil
|
154
|
+
else output
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# @group System Methods
|
160
|
+
#
|
161
|
+
|
162
|
+
#
|
163
|
+
# Gets the current time and returns the UNIX timestamp.
|
164
|
+
#
|
165
|
+
# @return [Integer]
|
166
|
+
# The current time as a UNIX timestamp.
|
167
|
+
#
|
168
|
+
# @note executes the `date +%s` command.
|
169
|
+
#
|
170
|
+
def sys_time
|
171
|
+
shell_exec('date +%s').to_i
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# Gets the system's hostname.
|
176
|
+
#
|
177
|
+
# @return [String]
|
178
|
+
#
|
179
|
+
# @note executes the `echo $HOSTNAME` command.
|
180
|
+
#
|
181
|
+
def sys_hostname
|
182
|
+
shell_exec("echo $HOSTNAME").chomp
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# @group File-System methods
|
187
|
+
#
|
188
|
+
|
189
|
+
#
|
190
|
+
# Gets the current working directory and returns the directory path.
|
191
|
+
#
|
192
|
+
# @return [String]
|
193
|
+
# The remote current working directory.
|
194
|
+
#
|
195
|
+
# @note executes the `pwd` command.
|
196
|
+
#
|
197
|
+
def fs_getcwd
|
198
|
+
shell_exec('pwd').chomp
|
199
|
+
end
|
200
|
+
|
201
|
+
#
|
202
|
+
# Changes the current working directory.
|
203
|
+
#
|
204
|
+
# @param [String] path
|
205
|
+
# The new remote current working directory.
|
206
|
+
#
|
207
|
+
# @note executes the `cd <path>` command.
|
208
|
+
#
|
209
|
+
def fs_chdir(path)
|
210
|
+
shell_puts("cd #{Shellwords.escape(path)} 2>/dev/null")
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# Reads the entire file at the given path and returns the full file's
|
215
|
+
# contents.
|
216
|
+
#
|
217
|
+
# @param [String] path
|
218
|
+
# The remote path to read.
|
219
|
+
#
|
220
|
+
# @return [String, nil]
|
221
|
+
# The contents of the remote file or `nil` if the file could not be
|
222
|
+
# read.
|
223
|
+
#
|
224
|
+
# @note executes the `cat <path>` command.
|
225
|
+
#
|
226
|
+
def fs_readfile(path)
|
227
|
+
command_exec('cat',path)
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
# Reads the destination path of a remote symbolic link.
|
232
|
+
#
|
233
|
+
# @param [String] path
|
234
|
+
# The remote path to read.
|
235
|
+
#
|
236
|
+
# @return [String, nil]
|
237
|
+
# The destination of the remote symbolic link or `nil` if the symbolic
|
238
|
+
# link could not be read.
|
239
|
+
#
|
240
|
+
# @note executes the `readlink -f <path>` command.
|
241
|
+
#
|
242
|
+
def fs_readlink(path)
|
243
|
+
command_exec('readlink','-f',path).chomp
|
244
|
+
end
|
245
|
+
|
246
|
+
#
|
247
|
+
# Reads the contents of a remote directory and returns an Array of
|
248
|
+
# directory entry names.
|
249
|
+
#
|
250
|
+
# @param [String] path
|
251
|
+
# The path of the remote directory to read.
|
252
|
+
#
|
253
|
+
# @return [Array<String>]
|
254
|
+
# The entities within the remote directory.
|
255
|
+
#
|
256
|
+
# @note executes the `ls <path>` command.
|
257
|
+
#
|
258
|
+
def fs_readdir(path)
|
259
|
+
command_exec('ls',path).lines(chomp: true)
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# Evaluates a directory glob pattern and returns all matching paths.
|
264
|
+
#
|
265
|
+
# @param [String] pattern
|
266
|
+
# The glob pattern to search for remotely.
|
267
|
+
#
|
268
|
+
# @return [Array<String>]
|
269
|
+
# The matching paths.
|
270
|
+
#
|
271
|
+
# @note executes the `ls <pattern>` command.
|
272
|
+
#
|
273
|
+
def fs_glob(pattern,&block)
|
274
|
+
shell_exec("ls #{pattern}").lines(chomp: true)
|
275
|
+
end
|
276
|
+
|
277
|
+
#
|
278
|
+
# Creates a remote temporary file with the given file basename.
|
279
|
+
#
|
280
|
+
# @param [String] basename
|
281
|
+
# The basename for the new temporary file.
|
282
|
+
#
|
283
|
+
# @return [String]
|
284
|
+
# The path of the newly created temporary file.
|
285
|
+
#
|
286
|
+
# @note executes the `mktemp <basename>` command.
|
287
|
+
#
|
288
|
+
def fs_mktemp(basename)
|
289
|
+
command_exec('mktemp',basename).chomp
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# Creates a new remote directory at the given path.
|
294
|
+
#
|
295
|
+
# @param [String] new_path
|
296
|
+
# The new remote directory to create.
|
297
|
+
#
|
298
|
+
# @note executes the `mkdir <path>` command.
|
299
|
+
#
|
300
|
+
def fs_mkdir(new_path)
|
301
|
+
command_exec('mkdir',new_path)
|
302
|
+
end
|
303
|
+
|
304
|
+
#
|
305
|
+
# Copies a source file to the destination path.
|
306
|
+
#
|
307
|
+
# @param [String] path
|
308
|
+
# The source file.
|
309
|
+
#
|
310
|
+
# @param [String] new_path
|
311
|
+
# The destination path.
|
312
|
+
#
|
313
|
+
# @note executes the `cp -r <path> <new_path>` command.
|
314
|
+
#
|
315
|
+
def fs_copy(path,new_path)
|
316
|
+
command_exec('cp','-r',path,new_path)
|
317
|
+
end
|
318
|
+
|
319
|
+
#
|
320
|
+
# Removes a file at the given path.
|
321
|
+
#
|
322
|
+
# @param [String] path
|
323
|
+
# The remote path to remove.
|
324
|
+
#
|
325
|
+
# @note executes the `rm <path>` command.
|
326
|
+
#
|
327
|
+
def fs_unlink(path)
|
328
|
+
command_exec('rm',path)
|
329
|
+
end
|
330
|
+
|
331
|
+
#
|
332
|
+
# Removes an empty directory at the given path.
|
333
|
+
#
|
334
|
+
# @param [String] path
|
335
|
+
# The remote directory path to remove.
|
336
|
+
#
|
337
|
+
# @note executes the `rmdir <path>` command.
|
338
|
+
#
|
339
|
+
def fs_rmdir(path)
|
340
|
+
command_exec('rmdir',path)
|
341
|
+
end
|
342
|
+
|
343
|
+
#
|
344
|
+
# Moves or renames a remote source file to a new destination path.
|
345
|
+
#
|
346
|
+
# @param [String] path
|
347
|
+
# The source file path.
|
348
|
+
#
|
349
|
+
# @param [String] new_path
|
350
|
+
# The destination file path.
|
351
|
+
#
|
352
|
+
# @note executes the `mv <path> <new_path>` command.
|
353
|
+
#
|
354
|
+
def fs_move(path,new_path)
|
355
|
+
command_exec('mv',path,new_path)
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Creates a remote symbolic link at the destination path pointing to the
|
360
|
+
# source path.
|
361
|
+
#
|
362
|
+
# @param [String] src
|
363
|
+
# The source file path for the new symbolic link.
|
364
|
+
#
|
365
|
+
# @param [String] dest
|
366
|
+
# The remote path of the new symbolic link.
|
367
|
+
#
|
368
|
+
# @note executes the `ln -s <src> <dest>` command.
|
369
|
+
#
|
370
|
+
def fs_link(src,dest)
|
371
|
+
command_exec('ln','-s',src,dest)
|
372
|
+
end
|
373
|
+
|
374
|
+
#
|
375
|
+
# Changes the group ownership of a remote file or directory.
|
376
|
+
#
|
377
|
+
# @param [String] group
|
378
|
+
# The new group name for the remote file or directory.
|
379
|
+
#
|
380
|
+
# @param [String] path
|
381
|
+
# The path of the remote file or directory.
|
382
|
+
#
|
383
|
+
# @note executes the `chgrp <group> <path>` command.
|
384
|
+
#
|
385
|
+
def fs_chgrp(group,path)
|
386
|
+
command_exec('chgrp',group,path)
|
387
|
+
end
|
388
|
+
|
389
|
+
#
|
390
|
+
# Changes the user ownership of remote a file or directory.
|
391
|
+
#
|
392
|
+
# @param [String] user
|
393
|
+
# The new user for the remote file or directory.
|
394
|
+
#
|
395
|
+
# @param [String] path
|
396
|
+
# The path of the remote file or directory.
|
397
|
+
#
|
398
|
+
# @note executes the `chown <user> <path>` command.
|
399
|
+
#
|
400
|
+
def fs_chown(user,path)
|
401
|
+
command_exec('chown',user,path)
|
402
|
+
end
|
403
|
+
|
404
|
+
#
|
405
|
+
# Changes the permissions on a remote file or directory.
|
406
|
+
#
|
407
|
+
# @param [Integer] mode
|
408
|
+
# The permissions mode for the remote file or directory.
|
409
|
+
#
|
410
|
+
# @param [String] path
|
411
|
+
# The path of the remote file or directory.
|
412
|
+
#
|
413
|
+
# @note executes the `chmod <umask> <path>` command.
|
414
|
+
#
|
415
|
+
def fs_chmod(mode,path)
|
416
|
+
umask = "%.4o" % mode
|
417
|
+
|
418
|
+
command_exec('chmod',umask,path)
|
419
|
+
end
|
420
|
+
|
421
|
+
#
|
422
|
+
# Queries file information for the given remote path and returns a Hash
|
423
|
+
# of file metadata.
|
424
|
+
#
|
425
|
+
# @param [String] path
|
426
|
+
# The path to the remote file or directory.
|
427
|
+
#
|
428
|
+
# @return [Hash{Symbol => Object}, nil]
|
429
|
+
# The metadata for the remote file.
|
430
|
+
#
|
431
|
+
# @note executes the `stat -t <path>` command.
|
432
|
+
#
|
433
|
+
def fs_stat(path)
|
434
|
+
fields = command_exec('stat','-t',path).strip.split(' ')
|
435
|
+
|
436
|
+
return {
|
437
|
+
path: path,
|
438
|
+
size: fields[1].to_i,
|
439
|
+
blocks: fields[2].to_i,
|
440
|
+
uid: fields[4].to_i,
|
441
|
+
gid: fields[5].to_i,
|
442
|
+
inode: fields[7].to_i,
|
443
|
+
links: fields[8].to_i,
|
444
|
+
atime: Time.at(fields[11].to_i),
|
445
|
+
mtime: Time.at(fields[12].to_i),
|
446
|
+
ctime: Time.at(fields[13].to_i),
|
447
|
+
blocksize: fields[14].to_i
|
448
|
+
}
|
449
|
+
end
|
450
|
+
|
451
|
+
#
|
452
|
+
# @group Process methods
|
453
|
+
#
|
454
|
+
|
455
|
+
#
|
456
|
+
# Gets the current process's Process ID (PID).
|
457
|
+
#
|
458
|
+
# @return [Integer]
|
459
|
+
# The current process's PID.
|
460
|
+
#
|
461
|
+
# @note executes the `echo $$` command.
|
462
|
+
#
|
463
|
+
def process_getpid
|
464
|
+
shell_exec('echo $$').to_i
|
465
|
+
end
|
466
|
+
|
467
|
+
#
|
468
|
+
# Gets the current process's parent Process ID (PPID).
|
469
|
+
#
|
470
|
+
# @return [Integer]
|
471
|
+
# The current process's PPID.
|
472
|
+
#
|
473
|
+
# @note executes the `echo $PPID` command.
|
474
|
+
#
|
475
|
+
def process_getppid
|
476
|
+
shell_exec('echo $PPID').to_i
|
477
|
+
end
|
478
|
+
|
479
|
+
#
|
480
|
+
# Gets the current process's user ID (UID).
|
481
|
+
#
|
482
|
+
# @return [Integer]
|
483
|
+
# The current process's UID.
|
484
|
+
#
|
485
|
+
# @note executes the `id -u` command.
|
486
|
+
#
|
487
|
+
def process_getuid
|
488
|
+
command_exec('id','-u').to_i
|
489
|
+
end
|
490
|
+
|
491
|
+
#
|
492
|
+
# Gets the current process's group ID (GID).
|
493
|
+
#
|
494
|
+
# @return [Integer]
|
495
|
+
# The group ID (GID) for the current process.
|
496
|
+
#
|
497
|
+
# @note executes the `id -g` command.
|
498
|
+
#
|
499
|
+
def process_getgid
|
500
|
+
command_exec('id','-g').to_i
|
501
|
+
end
|
502
|
+
|
503
|
+
#
|
504
|
+
# Queries all environment variables of the current process. Returns a
|
505
|
+
# Hash of the env variable names and values.
|
506
|
+
#
|
507
|
+
# @return [Hash{String => String}]
|
508
|
+
# The Hash of environment variables.
|
509
|
+
#
|
510
|
+
# @note executes the `env` command.
|
511
|
+
#
|
512
|
+
def process_environ
|
513
|
+
Hash[command_exec('env').each_line(chomp: true).map { |line|
|
514
|
+
line.split('=',2)
|
515
|
+
}]
|
516
|
+
end
|
517
|
+
|
518
|
+
#
|
519
|
+
# Gets an individual environment variable. If the environment variable
|
520
|
+
# has not been set, `nil` will be returned.
|
521
|
+
#
|
522
|
+
# @param [String] name
|
523
|
+
# The environment variable name to get.
|
524
|
+
#
|
525
|
+
# @return [String]
|
526
|
+
# The environment variable value.
|
527
|
+
#
|
528
|
+
# @note executes the `echo $<name>` command.
|
529
|
+
#
|
530
|
+
def process_getenv(name)
|
531
|
+
shell_exec("echo $#{name}").chomp
|
532
|
+
end
|
533
|
+
|
534
|
+
#
|
535
|
+
# Sets an environment variable to the given value.
|
536
|
+
#
|
537
|
+
# @param [String] name
|
538
|
+
# The environment variable name to set.
|
539
|
+
#
|
540
|
+
# @param [String] value
|
541
|
+
# The new value for the environment variable.
|
542
|
+
#
|
543
|
+
# @note executes the `export <name>=<value>` command.
|
544
|
+
#
|
545
|
+
def process_setenv(name,value)
|
546
|
+
shell_puts("export #{name}=#{value}")
|
547
|
+
end
|
548
|
+
|
549
|
+
#
|
550
|
+
# Un-sets an environment variable.
|
551
|
+
#
|
552
|
+
# @param [String] name
|
553
|
+
# The environment variable to unset.
|
554
|
+
#
|
555
|
+
# @note executes the `unset <name>` command.
|
556
|
+
#
|
557
|
+
def process_unsetenv(name)
|
558
|
+
shell_puts("unset #{name}")
|
559
|
+
end
|
560
|
+
|
561
|
+
#
|
562
|
+
# Kills another process using the given Process ID (POD) and the signal
|
563
|
+
# number.
|
564
|
+
#
|
565
|
+
# @param [Integer] pid
|
566
|
+
# The process ID (PID) to kill.
|
567
|
+
#
|
568
|
+
# @param [Integer] signal
|
569
|
+
# The signal to send the process ID (PID).
|
570
|
+
#
|
571
|
+
# @note executes the `kill -s <signal> <pid>` command.
|
572
|
+
#
|
573
|
+
def process_kill(pid,signal)
|
574
|
+
command_exec('kill','-s',signal,pid)
|
575
|
+
end
|
576
|
+
|
577
|
+
#
|
578
|
+
# Spawns a new process using the given program and additional arguments.
|
579
|
+
#
|
580
|
+
# @param [String] command
|
581
|
+
# The command name to spawn.
|
582
|
+
#
|
583
|
+
# @param [Array<String>] arguments
|
584
|
+
# Additional arguments for the program.
|
585
|
+
#
|
586
|
+
# @return [Integer]
|
587
|
+
# The process ID (PID) of the spawned process.
|
588
|
+
#
|
589
|
+
# @note
|
590
|
+
# executes the command with additional arguments as a background
|
591
|
+
# process.
|
592
|
+
#
|
593
|
+
def process_spawn(command,*arguments)
|
594
|
+
command = command_join(command,*arguments)
|
595
|
+
|
596
|
+
shell_exec("#{command} 2>&1 >/dev/null &; echo $!").to_i
|
597
|
+
end
|
598
|
+
|
599
|
+
#
|
600
|
+
# Exits the current process.
|
601
|
+
#
|
602
|
+
# @note executes the `exit` command.
|
603
|
+
#
|
604
|
+
def process_exit
|
605
|
+
shell_puts('exit')
|
606
|
+
end
|
607
|
+
|
608
|
+
#
|
609
|
+
# Closes the remote shell.
|
610
|
+
#
|
611
|
+
def close
|
612
|
+
@io.close
|
613
|
+
end
|
614
|
+
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|