opsconsole 0.1.6

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b1449525d723c920fe00c28c941adad147a816a3549d7880ca179562f798e76a
4
+ data.tar.gz: 97e546eef1d4ab5634a5ec12231f61d7dd8204f270d13a52e9afbde23a2652a7
5
+ SHA512:
6
+ metadata.gz: f7bf6c0731a7ff250ad34cd8e042b339fe2be7da652525511b9cd83ad9f2fe1e10a4974bcc77a2f67f33809e1820828982b51958ac1bd9d0bd2949de3f5c87b8
7
+ data.tar.gz: 9d4eee4e0041bafe5f9031a5d9a768a353b55bc6be8f0402303fabdecb8d247e7fac4beb2e4c6deba5d942e926455d6597dbdd455bc001f7f600bd02b2684e2b
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ *.swp
2
+ .DS_Store
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+ /vendor
13
+ .rspec_status
14
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ Metrics/AbcSize:
2
+ Max: 18
3
+
4
+ Metrics/BlockLength:
5
+ Max: 64
6
+
7
+ Metrics/ClassLength:
8
+ CountComments: false
9
+ Max: 256
10
+
11
+ Metrics/LineLength:
12
+ Max: 128
13
+
14
+ Metrics/MethodLength:
15
+ CountComments: false
16
+ Max: 128
17
+
18
+ Metrics/ParameterLists:
19
+ Max: 8
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.15.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Rafal Mierzwiak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # opsconsole
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'opsconsole'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install opsconsole
18
+
19
+ ## Overview
20
+
21
+ Tool to simultaneously access and interact with multiple remote machines.
22
+
23
+ Tool to access and interact with multiple remote machines at once. Console can be detached and re-attached at will. Terminals presented within current window can be accessed simultaneously.
24
+
25
+ **NOTES**
26
+
27
+ Console consists of sessions, windows and panes:
28
+
29
+ * Remote terminals are presented in panes, e.g. single pane shows output of a command running on a remote host.
30
+
31
+ * Multiple panes are organised in windows, this way operator is able to observe multiple terminals on one screen, also may organize certain commands and hosts into groups (e.g. a window called 'sysperf' showing 'iostat' and 'vmstat' commands running on database servers, another window called 'netperf' showing 'curl' and 'ping' commands running on web servers.
32
+
33
+ * Multiple windows are organized in sessions, this way operator may further organize and separate panes based on custom criteria, say keep 'staging' and 'production' session.
34
+
35
+ Console organises hosts in columns, commands in rows. Terminals are displayed on a single screen hence considerable amount of screen real estate is required for the tool to be usable.
36
+
37
+ tmux controls the console and the terminals, console can be detached and later re-attached at will. Terminals presented within current window can be accessed simultaneously. Refer to tmux documentation in regards to its configuration, in particular useful key bindings.
38
+
39
+ Upon creation console connects to remote server(s) via SSH using operators credentials and executes specified command(s). SSH connects to remote servers as $USER, that is unless different username is requested via $SSH_USER or tool's --user option. Make sure SSH keys are in place.
40
+
41
+ Command may be anything that works with with:
42
+
43
+ $ tmux new-window ssh host '<command>'
44
+
45
+ for example:
46
+
47
+ $ opsconsole create ... -c 'htop'
48
+
49
+ $ opsconsole create ... -c 'ping google.com'
50
+
51
+ $ opsconsole create ... -c 'while true; do echo $(date) $(nc -zw 2 google.com 80); sleep 1; done'
52
+
53
+ ## Usage
54
+
55
+ Situations when you may want to use it...
56
+
57
+ * Checking your servers vitals
58
+
59
+ ```
60
+ $ opsconsole create -w sysperf --hosts={host1,host2} -c 'iostat -d -p vda 1' -c 'vmstat 1' -c 'mpstat 1'
61
+ ```
62
+
63
+ ![screenshot-sysperf](examples/screenshot-sysperf.png)
64
+
65
+ * Checking whether your servers can connect to the outside world just fine
66
+
67
+ ```
68
+ $ opsconsole create -w netperf --hosts={host1,host2} -c 'mtr google.com' -c 'while true; do echo $(date) $(nc -zvw 2 google.com 80); sleep 1; done'
69
+ ```
70
+
71
+ ![screenshot-netperf](examples/screenshot-netperf.png)
72
+
73
+ ## Development
74
+
75
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
76
+
77
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
78
+
79
+ ## Contributing
80
+
81
+ Bug reports and merge requests are welcome on GitLab at [gitlab.com/rafalmierzwiak/opsconsole](https://gitlab.com/rafalmierzwiak/opsconsole).
82
+
83
+ ## License
84
+
85
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'opsconsole'
5
+
6
+ require 'pry'
7
+ Pry.start
8
+
9
+ require 'irb'
10
+ IRB.start(__FILE__)
data/bin/opsconsole ADDED
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gli'
4
+ require 'opsconsole'
5
+
6
+ include GLI::App
7
+
8
+ program_desc 'Remote terminal multiplexer'
9
+ program_long_desc <<-EOS
10
+ Tool to simultaneously access and interact with multiple remote machines.
11
+ EOS
12
+ version Opsconsole::VERSION
13
+
14
+ subcommand_option_handling :normal
15
+ arguments :strict
16
+
17
+ desc 'Attach console'
18
+ long_desc <<-EOS
19
+ If session not provided console active session will be attached.
20
+
21
+ If window not provided console active window will be attached.
22
+ EOS
23
+
24
+ command :attach do |c|
25
+ c.flag :s,
26
+ :session,
27
+ desc: 'Session name'
28
+ c.flag :w,
29
+ :window,
30
+ desc: 'Window name'
31
+
32
+ c.action do |_global, options, _args|
33
+ Console.attach(session: options.fetch(:session),
34
+ window: options.fetch(:window))
35
+ end
36
+ end
37
+
38
+ desc 'Create console'
39
+ long_desc <<-EOS
40
+ Console consists of sessions, windows and panes. Remote terminals are presented
41
+ in panes, e.g. single pane shows output of a command running on a remote host.
42
+ Multiple panes are organised in windows, this way operator is able to observe
43
+ multiple terminals on one screen, also may organize certain commands and hosts
44
+ into groups (e.g. a window called 'sysperf' showing 'iostat' and 'vmstat'
45
+ commands running on database servers, another window called 'netperf' showing
46
+ 'curl' and 'ping' commands running on web servers. Multiple windows are
47
+ organized in sessions, this way operator may further organize and separate panes
48
+ based on custom criteria, say keep 'staging' and 'production' session.
49
+
50
+ Console organises hosts in columns, commands in rows. Terminals are displayed on
51
+ a single screen hence considerable amount of screen real estate is required for
52
+ the tool to be usable.
53
+
54
+ tmux controls the console and the terminals, console can be detached and later
55
+ re-attached at will. Terminals presented within current window can be accessed
56
+ simultaneously. Refer to tmux documentation in regards to its configuration,
57
+ in particular useful key bindings.
58
+
59
+ Upon creation console connects to remote server(s) via SSH using operators
60
+ credentials and executes specified command(s). SSH connects to remote servers
61
+ as $USER, that is unless different username is requested via $SSH_USER or
62
+ tool's --user option. Make sure SSH keys are in place.
63
+
64
+ Command may be anything that works with:
65
+
66
+ tmux new-window ssh host '<command>'
67
+
68
+ for example:
69
+
70
+ -c 'htop'
71
+
72
+ -c 'ping google.com'
73
+
74
+ -c 'while true; do echo $(date) $(nc -zw 2 google.com 80); sleep 1; done'
75
+ EOS
76
+ command :create do |c|
77
+ c.flag :s,
78
+ :session,
79
+ desc: 'Session name',
80
+ default_value: 'opsconsole'
81
+ c.flag :w,
82
+ :window,
83
+ desc: 'Window name',
84
+ default_value: 'default'
85
+ c.flag :h,
86
+ :host,
87
+ desc: 'Host name',
88
+ required: true,
89
+ multiple: true
90
+ c.flag :c,
91
+ :command,
92
+ desc: 'Command',
93
+ required: true,
94
+ multiple: true
95
+ c.flag :u,
96
+ :user,
97
+ desc: 'Username',
98
+ default_value: ENV['SSH_USER'] ? ENV['SSH_USER'] : ENV['USER']
99
+ c.switch :synchronize,
100
+ desc: 'Synchronize panes',
101
+ default_value: true
102
+ c.switch :attach,
103
+ desc: 'Attach to console',
104
+ default_value: true
105
+
106
+ c.action do |_global, options, _args|
107
+ Console.create(session: options.fetch(:session),
108
+ window: options.fetch(:window),
109
+ user: options.fetch(:user),
110
+ hosts: options.fetch(:host, []),
111
+ commands: options.fetch(:command, []),
112
+ synchronize: options.fetch(:synchronize))
113
+ if options.fetch(:attach)
114
+ Console.attach(session: options.fetch(:session),
115
+ window: options.fetch(:window))
116
+ end
117
+ end
118
+ end
119
+
120
+ desc 'Destroy console'
121
+ long_desc <<-EOS
122
+ If window name provided all panes of the given window will be destroyed.
123
+
124
+ If session name provided all windows and panes of the given session will be
125
+ destroyed.
126
+ EOS
127
+
128
+ command :destroy do |c|
129
+ c.flag :s,
130
+ :session,
131
+ desc: 'Session name'
132
+ c.flag :w,
133
+ :window,
134
+ desc: 'Window name'
135
+
136
+ c.action do |_global, options, _args|
137
+ Console.destroy(session: options.fetch(:session),
138
+ window: options.fetch(:window))
139
+ end
140
+ end
141
+
142
+ desc 'List consoles panes'
143
+ long_desc <<-EOS
144
+ List columns contain the following information:
145
+
146
+ Session name, Window name, Window active, Pane index, Pane active
147
+ EOS
148
+ command :list do |c|
149
+ c.action do |_global, _options, _args|
150
+ Console.list
151
+ end
152
+ end
153
+
154
+ unless system('which', 'tmux', out: File::NULL, err: File::NULL)
155
+ STDERR.puts('Please install tmux, opsconsole depends on it.')
156
+ exit 1
157
+ end
158
+
159
+ exit run(ARGV)
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
Binary file
Binary file
@@ -0,0 +1,183 @@
1
+ # Tmux integration
2
+ #
3
+ class Console
4
+ def self.attach_session(session:, window: nil, pane: nil)
5
+ sh(%W[attach -t =#{session}:#{window}.#{pane}])
6
+ end
7
+
8
+ def self.sh(args)
9
+ system('tmux', '-L', 'opsconsole', *args)
10
+ end
11
+
12
+ def self.kill_session(session:)
13
+ sh(%W[kill-session -t =#{session}:])
14
+ end
15
+
16
+ def self.kill_pane(session:, window:, pane:)
17
+ sh(%W[killp -t =#{session}:#{window}.#{pane}])
18
+ end
19
+
20
+ def self.kill_window(session:, window:)
21
+ sh(%W[killw -t =#{session}:#{window}.])
22
+ end
23
+
24
+ def self.list_panes
25
+ fmt = ['#{session_name}',
26
+ '#{window_name}',
27
+ '#{window_active}',
28
+ '#{pane_index}',
29
+ '#{pane_active}'].join(' ')
30
+ sh(%W[lsp -a -F #{fmt}])
31
+ end
32
+
33
+ def self.new_session(session:, window:)
34
+ sh(%W[new -d -s #{session} -n #{window}])
35
+ end
36
+
37
+ def self.new_window(session:, window:)
38
+ sh(%W[neww -t #{session} -n #{window}])
39
+ end
40
+
41
+ def self.present?(target:)
42
+ sh(%W[has -t #{target}].push(err: File::NULL))
43
+ end
44
+
45
+ def self.set_option(session:, option:, value:)
46
+ sh(%W[set -t =#{session}: #{option} #{value}])
47
+ end
48
+
49
+ def self.set_window_option(session:, window:, option:, value:)
50
+ sh(%W[setw -t =#{session}:#{window}. #{option} #{value}])
51
+ end
52
+
53
+ def self.split_window(session:, window:, pane:, direction:, size:, command: nil)
54
+ if command.nil?
55
+ sh(%W[splitw -t =#{session}:#{window}.#{pane} -#{direction} -p #{size}])
56
+ else
57
+ sh(%W[splitw -t =#{session}:#{window}.#{pane} -#{direction} -p #{size} #{command}])
58
+ end
59
+ end
60
+
61
+ def self.select_pane(session:, window:, pane:)
62
+ sh(%W[selectp -t =#{session}:#{window}.#{pane}])
63
+ end
64
+
65
+ def self.select_window(session:, window:)
66
+ sh(%W[selectw -t =#{session}:#{window}.])
67
+ end
68
+
69
+ def self.attach(session:, window: nil, pane: nil)
70
+ select_pane(session: session,
71
+ window: window,
72
+ pane: pane)
73
+ attach_session(session: session,
74
+ window: window,
75
+ pane: pane)
76
+ end
77
+
78
+ def self.destroy(session:, window:)
79
+ if session.nil?
80
+ STDERR.puts 'can not find session'
81
+ elsif window.nil?
82
+ kill_session(session: session)
83
+ else
84
+ kill_window(session: session,
85
+ window: window)
86
+ end
87
+ end
88
+
89
+ def self.list
90
+ list_panes
91
+ end
92
+
93
+ def self.create(session:, window:, user:, hosts:, commands:, synchronize:)
94
+ return if present?(target: "=#{session}:#{window}.1")
95
+
96
+ if present?(target: "=#{session}:")
97
+ create_window(session: session,
98
+ window: window)
99
+ else
100
+ create_session(session: session,
101
+ window: window)
102
+ end
103
+
104
+ create_panes(session: session,
105
+ window: window,
106
+ user: user,
107
+ hosts: hosts,
108
+ commands: commands)
109
+
110
+ set_window_option(session: session,
111
+ window: window,
112
+ option: 'synchronize-panes',
113
+ value: synchronize ? 'on' : 'off')
114
+ end
115
+
116
+ def self.create_panes(session:, window:, user:, hosts:, commands:)
117
+ hosts.size.downto(2) do |h|
118
+ width = 100 / h
119
+ split_window(session: session,
120
+ window: window,
121
+ pane: 1,
122
+ direction: 'h',
123
+ size: width)
124
+ end
125
+
126
+ hosts.size.downto(1) do |h|
127
+ host = hosts[h - 1]
128
+ ssh = "ssh -tt -o ConnectTimeout=2 #{user}@#{host}"
129
+ commands = [ssh] if commands.empty?
130
+ commands.size.downto(1) do |c|
131
+ command = "#{ssh} '#{commands[c - 1]}'"
132
+ split_window(session: session,
133
+ window: window,
134
+ pane: h,
135
+ direction: 'v',
136
+ size: 100 / c,
137
+ command: command)
138
+ end
139
+ kill_pane(session: session,
140
+ window: window,
141
+ pane: h)
142
+ end
143
+
144
+ select_pane(session: session,
145
+ window: window,
146
+ pane: 1)
147
+ end
148
+
149
+ def self.create_session(session:, window:)
150
+ new_session(session: session,
151
+ window: window)
152
+ set_option(session: session,
153
+ option: 'base-index',
154
+ value: 1)
155
+ set_option(session: session,
156
+ option: 'pane-border-status',
157
+ value: 'top')
158
+ set_option(session: session,
159
+ option: 'pane-border-format',
160
+ value: '#{pane_index}')
161
+ set_option(session: session,
162
+ option: 'status-left-length',
163
+ value: session.size + 4)
164
+ set_option(session: session,
165
+ option: 'status-right',
166
+ value: ['#{session_name}',
167
+ '#{window_name}',
168
+ '#{pane_index}'].join(':'))
169
+ set_window_option(session: session,
170
+ window: window,
171
+ option: 'pane-base-index',
172
+ value: 1)
173
+ end
174
+
175
+ def self.create_window(session:, window:)
176
+ new_window(session: session,
177
+ window: window)
178
+ set_window_option(session: session,
179
+ window: window,
180
+ option: 'pane-base-index',
181
+ value: 1)
182
+ end
183
+ end
@@ -0,0 +1,3 @@
1
+ module Opsconsole
2
+ VERSION = '0.1.6'.freeze
3
+ end
data/lib/opsconsole.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'opsconsole/console'
2
+ require 'opsconsole/version'
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'opsconsole/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'opsconsole'
9
+ spec.version = Opsconsole::VERSION
10
+ spec.authors = ['Rafal Mierzwiak']
11
+ spec.email = ['rm@rm.pl']
12
+
13
+ spec.summary = <<-EOS
14
+ Remote terminal multiplexer.
15
+ EOS
16
+ spec.description = <<-EOS
17
+ Handy tool for server operators. Uses SSH to access remote hosts and execute commands on them. Uses tmux to present a consolidated console showing remote hosts terminals and allow for simultaneous interaction with the remote hosts.
18
+ EOS
19
+ spec.homepage = 'https://gitlab.com/rafalmierzwiak/opsconsole'
20
+ spec.license = 'MIT'
21
+
22
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
23
+ f.match(%r{^(test|spec|features)/})
24
+ end
25
+
26
+ spec.bindir = 'bin'
27
+ spec.executables = 'opsconsole'
28
+
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_development_dependency 'bundler', '~> 2.2.15'
32
+ spec.add_development_dependency 'rake', '~> 13.0.3'
33
+ spec.add_development_dependency 'rspec', '~> 3.10.0'
34
+
35
+ spec.add_runtime_dependency('gli', '2.20.0')
36
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opsconsole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.6
5
+ platform: ruby
6
+ authors:
7
+ - Rafal Mierzwiak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.15
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.15
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 13.0.3
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 13.0.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.10.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.10.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: gli
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.20.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.20.0
69
+ description: " Handy tool for server operators. Uses SSH to access remote hosts and
70
+ execute commands on them. Uses tmux to present a consolidated console showing remote
71
+ hosts terminals and allow for simultaneous interaction with the remote hosts.\n"
72
+ email:
73
+ - rm@rm.pl
74
+ executables:
75
+ - opsconsole
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - ".rspec"
81
+ - ".rubocop.yml"
82
+ - ".travis.yml"
83
+ - Gemfile
84
+ - LICENSE.txt
85
+ - README.md
86
+ - Rakefile
87
+ - bin/console
88
+ - bin/opsconsole
89
+ - bin/setup
90
+ - examples/screenshot-netperf.png
91
+ - examples/screenshot-sysperf.png
92
+ - lib/opsconsole.rb
93
+ - lib/opsconsole/console.rb
94
+ - lib/opsconsole/version.rb
95
+ - opsconsole.gemspec
96
+ homepage: https://gitlab.com/rafalmierzwiak/opsconsole
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.2.15
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Remote terminal multiplexer.
119
+ test_files: []