netchk 0.0.1.beta → 0.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4af327a7ff918c38cb651ae7dbd06e6ce031e8f09f8f389972ecb2fa60caacfa
4
- data.tar.gz: 54c330ab7509d734e4814ae8621324ba663f5014f868a35138f4768447be9f44
3
+ metadata.gz: 5079145cee4710e0517016a89fcc1a8a94003578621d78735b9afcf326619aaa
4
+ data.tar.gz: 2d6e638cc1487e033d3339927f3aa3dcf930f9b33f54ac07544aff14f38808aa
5
5
  SHA512:
6
- metadata.gz: c8e950c0eec0ee1c76378bcccda3c234f9e5f0288a94ad4aeabcc64a3e24f6e3f5f23a966d387f63086545e47552d892cafe9cc9477de5c2b0b0053e3e06a233
7
- data.tar.gz: 6f301bf1526f13a0263624bbe33c3b65d3aa045adcceff2ff45bef2dc3a1bd41066ecf257b9332bc4e1da26099d4742359de4ef2bb3f143a08278c79430b52f2
6
+ metadata.gz: 3d7c8588a927c08e854bde76ece5f05b7a33a39addbd4022ce7f1ae2f2ccaf483417a7a825ab53da2e919451cd70f8de74fc303494561d212926aabda810faa3
7
+ data.tar.gz: 47a7c0624cd73a6bbab35811d49c7cfae60f0f90139bd045f6ca35aff7088bb7e396758a737be2ee99d0a0a6329e434c310653aca6d402587ee91a8692237986
data/.gitignore CHANGED
@@ -6,3 +6,6 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ .idea
10
+ vendor
11
+ *.gem
@@ -0,0 +1,200 @@
1
+ require:
2
+ - rubocop-performance
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
6
+ DisabledByDefault: true
7
+ Exclude:
8
+ - '**/vendor/**/*'
9
+ - 'db/schema.rb'
10
+ - 'bin/**'
11
+ - 'docs/**/*'
12
+
13
+ Bundler/DuplicatedGem:
14
+ Enabled: true
15
+
16
+ Bundler/InsecureProtocolSource:
17
+ Enabled: true
18
+
19
+ Bundler/OrderedGems:
20
+ Enabled: true
21
+
22
+ # Prefer &&/|| over and/or.
23
+ Style/AndOr:
24
+ Enabled: true
25
+
26
+ # Align `when` with `case`.
27
+ Layout/CaseIndentation:
28
+ Enabled: true
29
+
30
+ # Align comments with method definitions.
31
+ Layout/CommentIndentation:
32
+ Enabled: true
33
+
34
+ # No extra empty lines.
35
+ Layout/EmptyLines:
36
+ Enabled: true
37
+
38
+ # In a regular class definition, no empty lines around the body.
39
+ Layout/EmptyLinesAroundClassBody:
40
+ Enabled: true
41
+
42
+ # In a regular method definition, no empty lines around the body.
43
+ Layout/EmptyLinesAroundMethodBody:
44
+ Enabled: true
45
+
46
+ # In a regular module definition, no empty lines around the body.
47
+ Layout/EmptyLinesAroundModuleBody:
48
+ Enabled: true
49
+
50
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
51
+ Style/HashSyntax:
52
+ Enabled: true
53
+
54
+ # Method definitions after `private` or `protected` isolated calls need one
55
+ # extra level of indentation.
56
+ Layout/IndentationConsistency:
57
+ Enabled: true
58
+ EnforcedStyle: indented_internal_methods
59
+
60
+ # Two spaces, no tabs (for indentation).
61
+ Layout/IndentationWidth:
62
+ Enabled: true
63
+
64
+ Layout/SpaceAfterColon:
65
+ Enabled: true
66
+
67
+ Layout/SpaceAfterComma:
68
+ Enabled: true
69
+
70
+ Layout/SpaceAroundEqualsInParameterDefault:
71
+ Enabled: true
72
+
73
+ Layout/SpaceAroundKeyword:
74
+ Enabled: true
75
+
76
+ Layout/SpaceAroundOperators:
77
+ Enabled: true
78
+
79
+ Layout/SpaceBeforeFirstArg:
80
+ Enabled: true
81
+
82
+ # Defining a method with parameters needs parentheses.
83
+ Style/MethodDefParentheses:
84
+ Enabled: true
85
+
86
+ # Use `foo {}` not `foo{}`.
87
+ Layout/SpaceBeforeBlockBraces:
88
+ Enabled: true
89
+
90
+ # Use `foo { bar }` not `foo {bar}`.
91
+ Layout/SpaceInsideBlockBraces:
92
+ Enabled: true
93
+
94
+ # Use `{ a: 1 }` not `{a:1}`.
95
+ Layout/SpaceInsideHashLiteralBraces:
96
+ Enabled: true
97
+
98
+ Layout/SpaceInsideParens:
99
+ Enabled: true
100
+
101
+ Style/FrozenStringLiteralComment:
102
+ Enabled: true
103
+
104
+ # Check quotes usage according to lint rule below.
105
+ Style/StringLiterals:
106
+ Enabled: true
107
+ EnforcedStyle: single_quotes
108
+
109
+ # Detect hard tabs, no hard tabs.
110
+ Layout/IndentationStyle:
111
+ Enabled: true
112
+
113
+ # Blank lines should not have any spaces.
114
+ Layout/TrailingEmptyLines:
115
+ Enabled: true
116
+
117
+ # No trailing whitespace.
118
+ Layout/TrailingWhitespace:
119
+ Enabled: true
120
+
121
+ # Use quotes for string literals when they are enough.
122
+ Style/RedundantPercentQ:
123
+ Enabled: true
124
+
125
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
126
+ Lint/RequireParentheses:
127
+ Enabled: true
128
+
129
+ Performance/Casecmp:
130
+ Enabled: true
131
+
132
+ Performance/ChainArrayAllocation:
133
+ Enabled: true
134
+
135
+ Performance/CompareWithBlock:
136
+ Enabled: true
137
+
138
+ Performance/Count:
139
+ Enabled: true
140
+
141
+ Performance/Detect:
142
+ Enabled: true
143
+
144
+ Performance/DoubleStartEndWith:
145
+ Enabled: true
146
+
147
+ Performance/EndWith:
148
+ Enabled: true
149
+
150
+ Performance/FixedSize:
151
+ Enabled: true
152
+
153
+ Performance/InefficientHashSearch:
154
+ Enabled: true
155
+
156
+ Performance/OpenStruct:
157
+ Enabled: true
158
+
159
+ Performance/RedundantBlockCall:
160
+ Enabled: true
161
+
162
+ Performance/RedundantMatch:
163
+ Enabled: true
164
+
165
+ Performance/RedundantMerge:
166
+ Enabled: true
167
+
168
+ Performance/RegexpMatch:
169
+ Enabled: true
170
+
171
+ Performance/ReverseEach:
172
+ Enabled: true
173
+
174
+ Performance/StartWith:
175
+ Enabled: true
176
+
177
+ Performance/StringReplacement:
178
+ Enabled: true
179
+
180
+ Performance/TimesMap:
181
+ Enabled: true
182
+
183
+ Performance/UriDefaultParser:
184
+ Enabled: true
185
+
186
+ Security/Eval:
187
+ Enabled: true
188
+
189
+ Security/JSONLoad:
190
+ Enabled: true
191
+
192
+ Security/MarshalLoad:
193
+ Enabled: true
194
+
195
+ Security/Open:
196
+ Enabled: true
197
+
198
+ Security/YAMLLoad:
199
+ Enabled: true
200
+
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
2
3
 
3
4
  gemspec
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ netchk (0.0.1)
5
+ net-ping (~> 2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.4.1)
11
+ net-ping (2.0.8)
12
+ parallel (1.19.2)
13
+ parser (2.7.1.4)
14
+ ast (~> 2.4.1)
15
+ rainbow (3.0.0)
16
+ regexp_parser (1.7.1)
17
+ rexml (3.2.4)
18
+ rubocop (0.86.0)
19
+ parallel (~> 1.10)
20
+ parser (>= 2.7.0.1)
21
+ rainbow (>= 2.2.2, < 4.0)
22
+ regexp_parser (>= 1.7)
23
+ rexml
24
+ rubocop-ast (>= 0.0.3, < 1.0)
25
+ ruby-progressbar (~> 1.7)
26
+ unicode-display_width (>= 1.4.0, < 2.0)
27
+ rubocop-ast (0.1.0)
28
+ parser (>= 2.7.0.1)
29
+ rubocop-performance (1.6.1)
30
+ rubocop (>= 0.71.0)
31
+ ruby-progressbar (1.10.1)
32
+ unicode-display_width (1.7.0)
33
+
34
+ PLATFORMS
35
+ ruby
36
+ x86_64-darwin-19
37
+
38
+ DEPENDENCIES
39
+ netchk!
40
+ rubocop
41
+ rubocop-performance
42
+
43
+ BUNDLED WITH
44
+ 2.1.2
@@ -1,21 +1,13 @@
1
- The MIT License (MIT)
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
2
3
 
3
- Copyright (c) 2020 Moray Baruh
4
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
4
5
 
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:
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
11
9
 
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
14
12
 
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.
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
data/README.md CHANGED
@@ -1,40 +1,68 @@
1
1
  # Netchk
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/netchk`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Simple tool to troubleshoot internet connectivity issues. This tool verifies:
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ - your computer has at least one IP address
6
+ - you have at least one DNS configured
7
+ - you can reach the configured nameservers
8
+ - the nameservers can resolve hosts
6
9
 
7
- ## Installation
10
+ Finally, some ICMP ping statistics are presented with average durations and error rates.
8
11
 
9
- Add this line to your application's Gemfile:
12
+ ## Installation
10
13
 
11
- ```ruby
12
- gem 'netchk'
14
+ ```sh
15
+ gem install netchk
13
16
  ```
14
17
 
15
- And then execute:
16
-
17
- $ bundle install
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install netchk
22
-
23
18
  ## Usage
24
19
 
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- 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).
20
+ Just run `netchk` from your terminal and basic diagnosis will start showing you progress and
21
+ any error if present.
22
+
23
+ Note: On Linux system, this gem requires `sudo` to perform the ICMP ping operations. On macOS, this is not needed.
24
+
25
+ You also can configure how netchk verifies your connections by configuring a `~/.netchk.yaml` or `~/.netchk.yml` file
26
+ like below.
27
+
28
+ ```yaml
29
+ # Settings to test DNS server connectivity.
30
+ dns:
31
+ # Path to resolv.conf file to check presence and connectivity of DNS.
32
+ # Path should be absolute to avoid issues when running netchk
33
+ # from different directories.
34
+ resolv.conf: /etc/resolv.conf
35
+
36
+ # Settings to test DNS resolution.
37
+ resolv:
38
+ # Path to resolv.conf file to use for testing DNS resolution.
39
+ # Path should be absolute to avoid issues when running netchk
40
+ # from different directories. It is advised to be the same
41
+ # as dns.resolv.conf.
42
+ resolv.conf: /etc/resolv.conf
43
+ # The list of domains to test for DNS resolution.
44
+ domains:
45
+ - google.com
46
+ - youtube.com
47
+ - facebook.com
48
+
49
+ # Settings to test icmp ping.
50
+ icmp:
51
+ # A list of hosts to ping with ICMP. It is advised to use
52
+ # IP addresses instead of domains to rule out any issues with
53
+ # DNS resolution, which is tested separately.
54
+ hosts:
55
+ - 1.1.1.1
56
+ - 8.8.8.8
57
+ # The number of ping to issue each host.
58
+ count: 20
59
+ # The duration in seconds to wait between each ping.
60
+ # Setting this value too low might cause timeouts.
61
+ interval: 0.2
62
+ ```
63
+
64
+ Each value is optional. If one is missing the default value will be used. The file above shows the default values.
32
65
 
33
66
  ## Contributing
34
67
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/netchk.
36
-
37
-
38
- ## License
39
-
40
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
68
+ Bug reports and pull requests are welcome on GitHub at https://github.com/moray95/netchk.
data/Rakefile CHANGED
@@ -1,10 +1,11 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
6
+ t.libs << 'test'
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/**/*_test.rb']
8
9
  end
9
10
 
10
- task :default => :test
11
+ task default: :test
data/bin/netchk CHANGED
@@ -4,9 +4,20 @@ require "netchk"
4
4
  require 'netchk/ip_verifier'
5
5
  require 'netchk/dns_server_verifier'
6
6
  require 'netchk/dns_resolv_verifier'
7
- require 'netchk/tcp_ping_verifier'
7
+ require 'netchk/icmp_ping_verifier'
8
+ require 'yaml'
9
+
10
+ config_files = %w[.netchk.yaml .netchk.yml].map { |f| File.join(Dir.home, f) }
11
+
12
+ config_file = config_files.find(&File.method(:exists?))
13
+
14
+ config = config_file
15
+ &.then(&File.method(:read))
16
+ &.then(&YAML.method(:load))
17
+
18
+ config = config || {}
8
19
 
9
20
  Netchk::IpVerifier.new.verify
10
- Netchk::DNSServerVerifier.new.verify
11
- Netchk::DNSResolvVerifier.new.verify
12
- Netchk::TcpPingVerifier.new.verify
21
+ Netchk::DNSServerVerifier.new(**(config['dns'] || {})).verify
22
+ Netchk::DNSResolvVerifier.new(**(config['resolv'] || {})).verify
23
+ Netchk::ICMPPingVerifier.new(**(config['icmp'] || {})).verify
@@ -1,4 +1,5 @@
1
- require "netchk/version"
1
+ # frozen_string_literal: true
2
+ require 'netchk/version'
2
3
 
3
4
  module Netchk
4
5
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  module Netchk
3
3
  class DNSResolvVerifier
4
- def initialize
5
- @domains = %w[google.com facebook.com]
4
+ def initialize(**options)
5
+ @domains = options['domains'] || %w[google.com youtube.com facebook.com]
6
+ @resolv_conf = options['resolv.conf']
6
7
  end
7
8
 
8
9
  def verify
9
- ::Resolv::DNS.open do |dns|
10
+ ::Resolv::DNS.open(@resolv_conf) do |dns|
10
11
  @domains.each do |domain|
11
12
  begin
12
13
  dns.getaddress(domain)
@@ -5,10 +5,14 @@ require 'net/ping/tcp'
5
5
 
6
6
  module Netchk
7
7
  class DNSServerVerifier
8
+ def initialize(**options)
9
+ @resolve_conf = options['resolv.conf']
10
+ end
11
+
8
12
  def verify
9
13
  nameservers = self.nameservers
10
14
  if nameservers.empty?
11
- $stderr.puts "No DNS server found. Verify your configuration."
15
+ $stderr.puts 'No DNS server found. Verify your configuration.'
12
16
  else
13
17
  puts "Using DNS servers #{nameservers.map { |ns| ns.join('#') }.join(', ')}"
14
18
  nameservers.map do |ns|
@@ -17,21 +21,20 @@ module Netchk
17
21
  end
18
22
  end
19
23
 
20
-
21
24
  private
22
25
  def verify_nameserver(ip, port)
23
26
  ping = Net::Ping::TCP.new(ip, port)
24
27
  unless ping.ping?
25
- $stderr.puts "Failed to ping DNS server #{ip}:#{port}"
28
+ $stderr.puts "Failed to ping DNS server #{ip}##{port}"
26
29
  end
27
30
  end
28
31
 
29
32
  def nameservers
30
33
  # Dirty trick to get default nameserver list from /etc/resolv.conf
31
34
  # without parsing the file manually.
32
- ::Resolv::DNS.open do |dns|
35
+ ::Resolv::DNS.open(@resolve_conf) do |dns|
33
36
  dns.lazy_initialize
34
- dns.instance_variable_get("@config").instance_variable_get("@nameserver_port")
37
+ dns.instance_variable_get('@config').instance_variable_get('@nameserver_port')
35
38
  end
36
39
  end
37
40
  end
@@ -1,3 +1,4 @@
1
+ # rubocop:disable Style/FrozenStringLiteralComment:
1
2
  require 'net/ping/ping'
2
3
 
3
4
  if File::ALT_SEPARATOR
@@ -6,8 +7,9 @@ end
6
7
 
7
8
  # The Net module serves as a namespace only.
8
9
  module Netchk
9
-
10
- # The Net::Ping::ICMP class encapsulates an icmp ping.
10
+ # Modified version of Net::Ping::ICMP that does
11
+ # not check for root privileges and uses a DGRAM
12
+ # socket instead of a raw socket.
11
13
  class ICMP < ::Net::Ping
12
14
  ICMP_ECHOREPLY = 0 # Echo reply
13
15
  ICMP_ECHO = 8 # Echo request
@@ -24,23 +26,15 @@ module Netchk
24
26
  attr_reader :data_size
25
27
 
26
28
  # Creates and returns a new Ping::ICMP object. This is similar to its
27
- # superclass constructor, but must be created with root privileges (on
28
- # UNIX systems), and the port value is ignored.
29
- #
30
- def initialize(host=nil, port=nil, timeout=5)
31
- if File::ALT_SEPARATOR
32
- unless Win32::Security.elevated_security?
33
- raise 'requires elevated security'
34
- end
35
- end
36
-
29
+ # superclass constructor, and the port value is ignored.
30
+ def initialize(host = nil, port = nil, timeout = 5)
37
31
  @seq = 0
38
32
  @bind_port = 0
39
33
  @bind_host = nil
40
34
  @data_size = 56
41
35
  @data = ''
42
36
 
43
- 0.upto(@data_size){ |n| @data << (n % 256).chr }
37
+ 0.upto(@data_size) { |n| @data << (n % 256).chr }
44
38
 
45
39
  @ping_id = (Thread.current.object_id ^ Process.pid) & 0xffff
46
40
 
@@ -53,7 +47,7 @@ module Netchk
53
47
  def data_size=(size)
54
48
  @data_size = size
55
49
  @data = ''
56
- 0.upto(size){ |n| @data << (n % 256).chr }
50
+ 0.upto(size) { |n| @data << (n % 256).chr }
57
51
  end
58
52
 
59
53
  # Associates the local end of the socket connection with the given
@@ -105,7 +99,7 @@ module Netchk
105
99
  socket.send(msg, 0, saddr) # Send the message
106
100
 
107
101
  begin
108
- Timeout.timeout(@timeout){
102
+ Timeout.timeout(@timeout) {
109
103
  while true
110
104
  io_array = select([socket], nil, nil, timeout)
111
105
 
@@ -149,24 +143,24 @@ module Netchk
149
143
 
150
144
  private
151
145
 
152
- # Perform a checksum on the message. This is the sum of all the short
153
- # words and it folds the high order bits into the low order bits.
154
- #
155
- def checksum(msg)
156
- length = msg.length
157
- num_short = length / 2
158
- check = 0
146
+ # Perform a checksum on the message. This is the sum of all the short
147
+ # words and it folds the high order bits into the low order bits.
148
+ #
149
+ def checksum(msg)
150
+ length = msg.length
151
+ num_short = length / 2
152
+ check = 0
159
153
 
160
- msg.unpack("n#{num_short}").each do |short|
161
- check += short
162
- end
154
+ msg.unpack("n#{num_short}").each do |short|
155
+ check += short
156
+ end
163
157
 
164
- if length % 2 > 0
165
- check += msg[length-1, 1].unpack('C').first << 8
166
- end
158
+ if length % 2 > 0
159
+ check += msg[length - 1, 1].unpack('C').first << 8
160
+ end
167
161
 
168
- check = (check >> 16) + (check & 0xffff)
169
- return (~((check >> 16) + check) & 0xffff)
170
- end
162
+ check = (check >> 16) + (check & 0xffff)
163
+ return (~((check >> 16) + check) & 0xffff)
164
+ end
171
165
  end
172
166
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'icmp'
3
+ require 'net/ping/icmp'
3
4
 
4
5
  class Array
5
6
  def avg
@@ -8,18 +9,18 @@ class Array
8
9
  end
9
10
 
10
11
  module Netchk
11
- class TcpPingVerifier
12
- def initialize
13
- @hosts = %w[1.1.1.1 8.8.8.8]
14
- @count = 20
15
- @interval = 0.2
12
+ class ICMPPingVerifier
13
+ def initialize(**options)
14
+ @hosts = options['hosts'] || %w[1.1.1.1 8.8.8.8]
15
+ @count = options['count'] || 20
16
+ @interval = options['interval'] || 0.2
16
17
  end
17
18
 
18
19
  def verify
19
20
  stats = @hosts.map do |host|
20
21
  host_stats = ping(host, @count)
21
22
 
22
- average = host_stats[:durations].empty? ? "N/A" : (host_stats[:durations].avg * 1000).round(2)
23
+ average = host_stats[:durations].empty? ? 'N/A' : (host_stats[:durations].avg * 1000).round(2)
23
24
  errors = host_stats[:failures].to_f / (host_stats[:failures] + host_stats[:durations].count) * 100
24
25
  puts "Stats for #{host} ping - average: #{average} ms, error rate: #{errors.round(2)}%"
25
26
 
@@ -27,9 +28,9 @@ module Netchk
27
28
  end.to_h
28
29
 
29
30
  all_durations = stats.values.flat_map { |host_stats| host_stats[:durations] }
30
- overall_average = all_durations.empty? ? "N/A" : (all_durations.avg * 1000).round(2)
31
+ overall_average = all_durations.empty? ? 'N/A' : (all_durations.avg * 1000).round(2)
31
32
  overall_errors = stats.values.flat_map { |host_stats| host_stats[:failures].to_f / host_stats[:count] * 100 }.avg
32
- puts "Overall stats for ping - average: #{overall_average} ms, errors: #{overall_errors.round(2)}%"
33
+ puts "Overall stats for ping - average: #{overall_average} ms, error rate: #{overall_errors.round(2)}%"
33
34
  end
34
35
 
35
36
  private
@@ -39,7 +40,9 @@ module Netchk
39
40
  failures: 0,
40
41
  count: count
41
42
  }
42
- ping = ::Netchk::ICMP.new(host, nil, 1)
43
+
44
+ pingClass = /darwin/.match?(RUBY_PLATFORM) ? ::Netchk::ICMP : ::Net::Ping::ICMP
45
+ ping = pingClass.new(host, nil, 1)
43
46
 
44
47
  count.times do
45
48
  sleep @interval
@@ -55,4 +58,3 @@ module Netchk
55
58
  end
56
59
  end
57
60
  end
58
-
@@ -6,12 +6,12 @@ module Netchk
6
6
  def verify
7
7
  socket = Socket.ip_address_list
8
8
  addresses = socket.reject(&:ipv4_loopback?)
9
- .reject(&:ipv6_loopback?)
10
- .filter(&:ipv4?)
11
- .map(&:inspect_sockaddr)
9
+ addresses.reject!(&:ipv6_loopback?)
10
+ addresses.filter!(&:ipv4?)
11
+ addresses.map!(&:inspect_sockaddr)
12
12
 
13
13
  if addresses.empty?
14
- $stderr.puts "No IPv4 address found. Verify your connection to your router."
14
+ $stderr.puts 'No IPv4 address found. Verify your connection to your router.'
15
15
  else
16
16
  puts "Found IP addresses #{addresses.join(', ')}."
17
17
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Netchk
2
- VERSION = "0.0.1.beta"
3
+ VERSION = '0.0.1'
3
4
  end
@@ -1,35 +1,30 @@
1
+ # frozen_string_literal: true
1
2
  require_relative 'lib/netchk/version'
2
3
 
3
4
  Gem::Specification.new do |spec|
4
- spec.name = "netchk"
5
+ spec.name = 'netchk'
5
6
  spec.version = Netchk::VERSION
6
- spec.authors = ["Moray Baruh"]
7
+ spec.authors = ['Moray Baruh']
7
8
 
8
- spec.summary = "Simple internet troubleshooter."
9
- spec.description = <<~EOF
10
- Find issues with your internet connection step by step. This script verifies:
11
- - your computer has at least one IP assigned
12
- - has access to at least one DNS server
13
- - the configured DNS servers are reachable
14
- - the configured DNS server are able to resolve host names
15
-
16
- And finally, pings some hosts to show you average durations and error rates.
17
- EOF
18
- spec.homepage = "https://moraybaruh.com"
19
- spec.license = "MIT"
20
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
9
+ spec.summary = 'Simple internet troubleshooter.'
10
+ spec.description = File.read('README.md')
11
+ spec.homepage = 'https://github.com/moray95/netchk'
12
+ spec.license = 'WTFPL'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
21
14
 
22
- # spec.metadata["homepage_uri"] = spec.homepage
23
- # spec.metadata["source_code_uri"] = "https://moraybaruh.com"
24
- # spec.metadata["changelog_uri"] = "https://moraybaruh.com"
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = spec.homepage
25
17
  # Specify which files should be added to the gem when it is released.
26
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
20
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
21
  end
30
- spec.bindir = "bin"
22
+ spec.bindir = 'bin'
31
23
  spec.executables = ['netchk']
32
- spec.require_paths = ["lib"]
24
+ spec.require_paths = ['lib']
33
25
 
34
26
  spec.add_dependency 'net-ping', '~> 2.0'
27
+
28
+ spec.add_development_dependency 'rubocop'
29
+ spec.add_development_dependency 'rubocop-performance'
35
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netchk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moray Baruh
@@ -24,11 +24,60 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
- description: "Find issues with your internet connection step by step. This script
28
- verifies:\n - your computer has at least one IP assigned \n - has access to at
29
- least one DNS server\n - the configured DNS servers are reachable\n - the configured
30
- DNS server are able to resolve host names\n \nAnd finally, pings some hosts to show
31
- you average durations and error rates.\n"
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-performance
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: "# Netchk\n\nSimple tool to troubleshoot internet connectivity issues.
56
+ This tool verifies:\n\n- your computer has at least one IP address\n- you have at
57
+ least one DNS configured\n- you can reach the configured nameservers\n- the nameservers
58
+ can resolve hosts\n\nFinally, some ICMP ping statistics are presented with average
59
+ durations and error rates. \n\n## Installation\n\n```sh\ngem install netchk\n```\n\n##
60
+ Usage\n\nJust run `netchk` from your terminal and basic diagnosis will start showing
61
+ you progress and\nany error if present.\n\nNote: On Linux system, this gem requires
62
+ `sudo` to perform the ICMP ping operations. On macOS, this is not needed.\n\nYou
63
+ also can configure how netchk verifies your connections by configuring a `~/.netchk.yaml`
64
+ or `~/.netchk.yml` file\nlike below.\n\n```yaml\n# Settings to test DNS server connectivity.\ndns:\n
65
+ \ # Path to resolv.conf file to check presence and connectivity of DNS.\n # Path
66
+ should be absolute to avoid issues when running netchk\n # from different directories.\n
67
+ \ resolv.conf: /etc/resolv.conf\n\n# Settings to test DNS resolution.\nresolv:\n
68
+ \ # Path to resolv.conf file to use for testing DNS resolution.\n # Path should
69
+ be absolute to avoid issues when running netchk\n # from different directories.
70
+ It is advised to be the same\n # as dns.resolv.conf.\n resolv.conf: /etc/resolv.conf\n
71
+ \ # The list of domains to test for DNS resolution.\n domains:\n - google.com\n
72
+ \ - youtube.com\n - facebook.com \n\n# Settings to test icmp ping.\nicmp:\n
73
+ \ # A list of hosts to ping with ICMP. It is advised to use\n # IP addresses instead
74
+ of domains to rule out any issues with\n # DNS resolution, which is tested separately.\n
75
+ \ hosts:\n - 1.1.1.1\n - 8.8.8.8\n # The number of ping to issue each host.\n
76
+ \ count: 20\n # The duration in seconds to wait between each ping.\n # Setting
77
+ this value too low might cause timeouts.\n interval: 0.2\n``` \n\nEach value
78
+ is optional. If one is missing the default value will be used. The file above shows
79
+ the default values.\n\n## Contributing\n\nBug reports and pull requests are welcome
80
+ on GitHub at https://github.com/moray95/netchk.\n"
32
81
  email:
33
82
  executables:
34
83
  - netchk
@@ -36,10 +85,9 @@ extensions: []
36
85
  extra_rdoc_files: []
37
86
  files:
38
87
  - ".gitignore"
39
- - ".idea/$CACHE_FILE$"
40
- - ".idea/workspace.xml"
41
- - ".travis.yml"
88
+ - ".rubocop.yml"
42
89
  - Gemfile
90
+ - Gemfile.lock
43
91
  - LICENSE.txt
44
92
  - README.md
45
93
  - Rakefile
@@ -50,15 +98,16 @@ files:
50
98
  - lib/netchk/dns_resolv_verifier.rb
51
99
  - lib/netchk/dns_server_verifier.rb
52
100
  - lib/netchk/icmp.rb
101
+ - lib/netchk/icmp_ping_verifier.rb
53
102
  - lib/netchk/ip_verifier.rb
54
- - lib/netchk/tcp_ping.rb
55
- - lib/netchk/tcp_ping_verifier.rb
56
103
  - lib/netchk/version.rb
57
104
  - netchk.gemspec
58
- homepage: https://moraybaruh.com
105
+ homepage: https://github.com/moray95/netchk
59
106
  licenses:
60
- - MIT
61
- metadata: {}
107
+ - WTFPL
108
+ metadata:
109
+ homepage_uri: https://github.com/moray95/netchk
110
+ source_code_uri: https://github.com/moray95/netchk
62
111
  post_install_message:
63
112
  rdoc_options: []
64
113
  require_paths:
@@ -70,9 +119,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
119
  version: 2.3.0
71
120
  required_rubygems_version: !ruby/object:Gem::Requirement
72
121
  requirements:
73
- - - ">"
122
+ - - ">="
74
123
  - !ruby/object:Gem::Version
75
- version: 1.3.1
124
+ version: '0'
76
125
  requirements: []
77
126
  rubygems_version: 3.1.2
78
127
  signing_key:
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="NodePackageJsonFileManager">
4
- <packageJsonPaths />
5
- </component>
6
- </project>
@@ -1,162 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ChangeListManager">
4
- <list default="true" id="2567b485-a0a4-477d-9983-3cf1b15b4c80" name="Default Changelist" comment="">
5
- <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
6
- <change afterPath="$PROJECT_DIR$/.idea/$CACHE_FILE$" afterDir="false" />
7
- <change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
8
- <change afterPath="$PROJECT_DIR$/.travis.yml" afterDir="false" />
9
- <change afterPath="$PROJECT_DIR$/Gemfile" afterDir="false" />
10
- <change afterPath="$PROJECT_DIR$/LICENSE.txt" afterDir="false" />
11
- <change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
12
- <change afterPath="$PROJECT_DIR$/Rakefile" afterDir="false" />
13
- <change afterPath="$PROJECT_DIR$/bin/console" afterDir="false" />
14
- <change afterPath="$PROJECT_DIR$/bin/netchk" afterDir="false" />
15
- <change afterPath="$PROJECT_DIR$/bin/setup" afterDir="false" />
16
- <change afterPath="$PROJECT_DIR$/lib/netchk.rb" afterDir="false" />
17
- <change afterPath="$PROJECT_DIR$/lib/netchk/dns_resolv_verifier.rb" afterDir="false" />
18
- <change afterPath="$PROJECT_DIR$/lib/netchk/dns_server_verifier.rb" afterDir="false" />
19
- <change afterPath="$PROJECT_DIR$/lib/netchk/icmp.rb" afterDir="false" />
20
- <change afterPath="$PROJECT_DIR$/lib/netchk/ip_verifier.rb" afterDir="false" />
21
- <change afterPath="$PROJECT_DIR$/lib/netchk/tcp_ping.rb" afterDir="false" />
22
- <change afterPath="$PROJECT_DIR$/lib/netchk/tcp_ping_verifier.rb" afterDir="false" />
23
- <change afterPath="$PROJECT_DIR$/lib/netchk/version.rb" afterDir="false" />
24
- <change afterPath="$PROJECT_DIR$/netchk.gemspec" afterDir="false" />
25
- <change afterPath="$PROJECT_DIR$/test/netchk_test.rb" afterDir="false" />
26
- <change afterPath="$PROJECT_DIR$/test/test_helper.rb" afterDir="false" />
27
- </list>
28
- <option name="SHOW_DIALOG" value="false" />
29
- <option name="HIGHLIGHT_CONFLICTS" value="true" />
30
- <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
31
- <option name="LAST_RESOLUTION" value="IGNORE" />
32
- </component>
33
- <component name="FileTemplateManagerImpl">
34
- <option name="RECENT_TEMPLATES">
35
- <list>
36
- <option value="Ruby Class" />
37
- <option value="Ruby File" />
38
- </list>
39
- </option>
40
- </component>
41
- <component name="Git.Settings">
42
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
43
- </component>
44
- <component name="ProjectId" id="1duf1zfYnsOoG9lsTWCRHRpTQmG" />
45
- <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
46
- <component name="ProjectViewState">
47
- <option name="hideEmptyMiddlePackages" value="true" />
48
- <option name="showLibraryContents" value="true" />
49
- </component>
50
- <component name="PropertiesComponent">
51
- <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
52
- <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
53
- <property name="TERMINAL_CUSTOM_COMMANDS_GOT_IT" value="true" />
54
- <property name="WebServerToolWindowFactoryState" value="false" />
55
- <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
56
- <property name="nodejs_npm_path_reset_for_default_project" value="true" />
57
- <property name="nodejs_package_manager_path" value="npm" />
58
- </component>
59
- <component name="RecentsManager">
60
- <key name="MoveFile.RECENT_KEYS">
61
- <recent name="$PROJECT_DIR$/bin" />
62
- </key>
63
- </component>
64
- <component name="RunManager">
65
- <configuration name="netchk" type="RubyRunConfigurationType" factoryName="Ruby" temporary="true">
66
- <module name="netchk" />
67
- <RUBY_RUN_CONFIG NAME="RUBY_ARGS" VALUE="-I lib" />
68
- <RUBY_RUN_CONFIG NAME="WORK DIR" VALUE="$MODULE_DIR$" />
69
- <RUBY_RUN_CONFIG NAME="SHOULD_USE_SDK" VALUE="true" />
70
- <RUBY_RUN_CONFIG NAME="ALTERN_SDK_NAME" VALUE="ruby-2.7.1-p83" />
71
- <RUBY_RUN_CONFIG NAME="myPassParentEnvs" VALUE="true" />
72
- <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="true" />
73
- <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
74
- <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov">
75
- <COVERAGE_PATTERN ENABLED="true">
76
- <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
77
- </COVERAGE_PATTERN>
78
- </EXTENSION>
79
- <EXTENSION ID="org.jetbrains.plugins.ruby.rails.run.RailsRunConfigurationExtension" SCRATCH_USE_RAILS_RUNNER="false" />
80
- <RUBY_RUN_CONFIG NAME="SCRIPT_PATH" VALUE="$MODULE_DIR$/bin/netchk" />
81
- <RUBY_RUN_CONFIG NAME="SCRIPT_ARGS" VALUE="" />
82
- <method v="2" />
83
- </configuration>
84
- <recent_temporary>
85
- <list>
86
- <item itemvalue="Ruby.netchk" />
87
- </list>
88
- </recent_temporary>
89
- </component>
90
- <component name="SpringUtil" SPRING_PRE_LOADER_OPTION="true" RAKE_SPRING_PRE_LOADER_OPTION="true" RAILS_SPRING_PRE_LOADER_OPTION="true" />
91
- <component name="SvnConfiguration">
92
- <configuration />
93
- </component>
94
- <component name="TaskManager">
95
- <task active="true" id="Default" summary="Default task">
96
- <changelist id="2567b485-a0a4-477d-9983-3cf1b15b4c80" name="Default Changelist" comment="" />
97
- <created>1593279687801</created>
98
- <option name="number" value="Default" />
99
- <option name="presentableId" value="Default" />
100
- <updated>1593279687801</updated>
101
- <workItem from="1593279689105" duration="8923000" />
102
- <workItem from="1593337253458" duration="6021000" />
103
- </task>
104
- <servers />
105
- </component>
106
- <component name="TypeScriptGeneratedFilesManager">
107
- <option name="version" value="2" />
108
- </component>
109
- <component name="WindowStateProjectService">
110
- <state x="744" y="462" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1593282010067">
111
- <screen x="0" y="0" width="2560" height="1600" />
112
- </state>
113
- <state x="744" y="462" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.0.2560.1600@0.0.2560.1600" timestamp="1593282010067" />
114
- <state x="1043" y="424" width="970" height="751" key="#xdebugger.evaluate" timestamp="1593282162463">
115
- <screen x="0" y="0" width="2560" height="1600" />
116
- </state>
117
- <state x="1043" y="424" width="970" height="751" key="#xdebugger.evaluate/0.0.2560.1600@0.0.2560.1600" timestamp="1593282162463" />
118
- <state width="2518" height="460" key="GridCell.Tab.0.bottom" timestamp="1593342482167">
119
- <screen x="0" y="0" width="2560" height="1600" />
120
- </state>
121
- <state width="2518" height="460" key="GridCell.Tab.0.bottom/0.0.2560.1600@0.0.2560.1600" timestamp="1593342482167" />
122
- <state width="2518" height="460" key="GridCell.Tab.0.bottom/0.23.2560.1577@0.23.2560.1577" timestamp="1593342310722" />
123
- <state width="2518" height="460" key="GridCell.Tab.0.center" timestamp="1593342482166">
124
- <screen x="0" y="0" width="2560" height="1600" />
125
- </state>
126
- <state width="2518" height="460" key="GridCell.Tab.0.center/0.0.2560.1600@0.0.2560.1600" timestamp="1593342482166" />
127
- <state width="2518" height="460" key="GridCell.Tab.0.center/0.23.2560.1577@0.23.2560.1577" timestamp="1593342310721" />
128
- <state width="2518" height="460" key="GridCell.Tab.0.left" timestamp="1593342482165">
129
- <screen x="0" y="0" width="2560" height="1600" />
130
- </state>
131
- <state width="2518" height="460" key="GridCell.Tab.0.left/0.0.2560.1600@0.0.2560.1600" timestamp="1593342482165" />
132
- <state width="2518" height="460" key="GridCell.Tab.0.left/0.23.2560.1577@0.23.2560.1577" timestamp="1593342310720" />
133
- <state width="2518" height="460" key="GridCell.Tab.0.right" timestamp="1593342482167">
134
- <screen x="0" y="0" width="2560" height="1600" />
135
- </state>
136
- <state width="2518" height="460" key="GridCell.Tab.0.right/0.0.2560.1600@0.0.2560.1600" timestamp="1593342482167" />
137
- <state width="2518" height="460" key="GridCell.Tab.0.right/0.23.2560.1577@0.23.2560.1577" timestamp="1593342310721" />
138
- <state width="2518" height="526" key="GridCell.Tab.1.bottom" timestamp="1593337783301">
139
- <screen x="0" y="0" width="2560" height="1600" />
140
- </state>
141
- <state width="2518" height="526" key="GridCell.Tab.1.bottom/0.0.2560.1600@0.0.2560.1600" timestamp="1593337783301" />
142
- <state width="2518" height="526" key="GridCell.Tab.1.center" timestamp="1593337783300">
143
- <screen x="0" y="0" width="2560" height="1600" />
144
- </state>
145
- <state width="2518" height="526" key="GridCell.Tab.1.center/0.0.2560.1600@0.0.2560.1600" timestamp="1593337783300" />
146
- <state width="2518" height="526" key="GridCell.Tab.1.left" timestamp="1593337783300">
147
- <screen x="0" y="0" width="2560" height="1600" />
148
- </state>
149
- <state width="2518" height="526" key="GridCell.Tab.1.left/0.0.2560.1600@0.0.2560.1600" timestamp="1593337783300" />
150
- <state width="2518" height="526" key="GridCell.Tab.1.right" timestamp="1593337783301">
151
- <screen x="0" y="0" width="2560" height="1600" />
152
- </state>
153
- <state width="2518" height="526" key="GridCell.Tab.1.right/0.0.2560.1600@0.0.2560.1600" timestamp="1593337783301" />
154
- <state x="945" y="371" width="670" height="676" key="search.everywhere.popup" timestamp="1593343800681">
155
- <screen x="0" y="0" width="2560" height="1600" />
156
- </state>
157
- <state x="945" y="371" width="670" height="676" key="search.everywhere.popup/0.0.2560.1600@0.0.2560.1600" timestamp="1593343800681" />
158
- </component>
159
- <component name="com.intellij.coverage.CoverageDataManagerImpl">
160
- <SUITE FILE_PATH="coverage/netchk@netchk.rcov" NAME="netchk Coverage Results" MODIFIED="1593342318395" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="rcov" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" MODULE_NAME="netchk" />
161
- </component>
162
- </project>
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.1
6
- before_install: gem install bundler -v 2.1.2
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
- module Netchk
3
- def ping(host, count = 1, interval = 1, timeout = 5)
4
-
5
- raise "Count must be an integer" unless count.is_a? Integer
6
- raise "Timeout must be a number" unless timeout.is_a? Numeric
7
-
8
- unless interval.is_a?(Numeric) && interval >= 0.2
9
- raise "Interval must be a decimal greater than or equal to 0.2"
10
- end
11
-
12
- super(host)
13
-
14
- pcmd = ['ping']
15
-
16
- case RbConfig::CONFIG['host_os']
17
- when /linux/i
18
- pcmd += ['-c', count.to_s, '-W', timeout.to_s, host]
19
- pcmd += ['-i', interval.to_s] unless RbConfig::CONFIG['busybox']
20
- when /aix/i
21
- pcmd += ['-c', count.to_s, '-w', timeout.to_s, host]
22
- when /bsd|osx|mach|darwin/i
23
- pcmd += ['-c', count.to_s, '-t', timeout.to_s, host]
24
- when /solaris|sunos/i
25
- pcmd += [host, timeout.to_s]
26
- when /hpux/i
27
- pcmd += [host, "-n#{count.to_s}", '-m', timeout.to_s]
28
- when /win32|windows|msdos|mswin|cygwin|mingw/i
29
- pcmd += ['-n', count.to_s, '-w', (timeout * 1000).to_s, host]
30
- else
31
- pcmd += [host]
32
- end
33
-
34
- begin
35
- Open3.popen3(*pcmd) do |stdin, stdout, stderr, thread|
36
- stdin.close
37
- err = stderr.gets # Can't chomp yet, might be nil
38
-
39
- case thread.value.exitstatus
40
- when 0
41
- info = stdout.read
42
- if info =~ /unreachable/ix # Windows
43
- raise StandardError, "Host unreachable"
44
- else
45
- # ignored
46
- end
47
-
48
- if err & (err =~ /warning/i)
49
- @warning = err.chomp # TODO
50
- end
51
- when 2
52
- raise StandardError, err&.chomp
53
- else
54
- if err
55
- raise StandardError, err.chomp
56
- else
57
- stdout.each_line do |line|
58
- if line =~ /(timed out|could not find host|packet loss)/i
59
- @exception = line.chomp
60
- raise StandardError, line.chomp
61
- end
62
- end
63
- raise StandardError, "Unknown error"
64
- end
65
- end
66
- end
67
- rescue Exception => error
68
- @exception = error.message
69
- end
70
-
71
- end
72
- end