sensu 0.23.3 → 0.24.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/lib/sensu/api/process.rb +184 -90
- data/lib/sensu/api/validators.rb +37 -0
- data/lib/sensu/cli.rb +3 -0
- data/lib/sensu/client/process.rb +34 -6
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +67 -30
- data/lib/sensu/server/filter.rb +2 -2
- data/lib/sensu/server/handle.rb +12 -12
- data/lib/sensu/server/mutate.rb +4 -4
- data/lib/sensu/server/process.rb +218 -213
- data/sensu.gemspec +5 -5
- metadata +15 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf29524e586ad648f83f891749f04ed9bb41d1f5
|
4
|
+
data.tar.gz: 651104b216bbc218bebfc51ec19e46563a32c093
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee318b81fcda3b1b714052000cad8c7fede926803f31f96dd52f33a461e42b4b840addce01b950139feca58f6583cc65ee9dd1e3e42dea257a94182ec0df2f50
|
7
|
+
data.tar.gz: cfeee1f970ae412bd090004b6f977026382f7806c2e520363c11731885fd3a8f218c2aa4c19214d4035fec22fd6b54de6c97d0f6f9c4eaaafe6c2e0cd99b29a2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,61 @@
|
|
1
|
+
## 0.24.0 - TBD
|
2
|
+
|
3
|
+
### Important
|
4
|
+
|
5
|
+
Sensu check ["Aggregates 2.0"](https://github.com/sensu/sensu/issues/1218)
|
6
|
+
breaks the existing Sensu API aggregate endpoints.
|
7
|
+
|
8
|
+
Sensu API GET /health endpoint, failed health checks now respond with a
|
9
|
+
`412` (preconditions failed) instead of a `503`.
|
10
|
+
|
11
|
+
### Features
|
12
|
+
|
13
|
+
Persistent Sensu event IDs, event occurrences for a client/check pair will
|
14
|
+
now have the same event ID until the event is resolved.
|
15
|
+
|
16
|
+
Added a CLI option/argument to cause the Sensu service to validate its
|
17
|
+
compiled configuration settings and exit with the appropriate exit
|
18
|
+
code, e.g. `2` for invalid. The CLI option is `--validate_config`. This
|
19
|
+
feature is now used when restarting a Sensu service to first validate the
|
20
|
+
new configuration before stopping the running service.
|
21
|
+
|
22
|
+
Improved tracking of in progress check result processing, no longer
|
23
|
+
potentially losing check results when restarting the Sensu server service.
|
24
|
+
|
25
|
+
Event data check type now explicitly defaults to "standard".
|
26
|
+
|
27
|
+
Check results for proxy clients (a.k.a JIT clients) will now have a check
|
28
|
+
"origin" set to the client name of the result producer.
|
29
|
+
|
30
|
+
Configurable Sensu Spawn concurrent child process limit (checks, mutators,
|
31
|
+
& pipe handlers). The default limit is still `12` and the EventMachine
|
32
|
+
threadpool size is automatically adjusted to accommodate a larger limit.
|
33
|
+
|
34
|
+
Sensu check ["Aggregates 2.0"](https://github.com/sensu/sensu/issues/1218).
|
35
|
+
|
36
|
+
Sensu client token substitution is now supported in every check definition
|
37
|
+
attribute value, no longer just the check command.
|
38
|
+
|
39
|
+
### Other
|
40
|
+
|
41
|
+
Sensu API GET /health endpoint, failed health check now responds with a
|
42
|
+
`412` (preconditions failed) instead of a `503`.
|
43
|
+
|
44
|
+
Sensu API POST /clients endpoint can now create clients in the registry
|
45
|
+
that are expected to produce keepalives, and validates clients with the
|
46
|
+
Sensu Settings client definition validator.
|
47
|
+
|
48
|
+
Updated Thin (used by Sensu API) to the latest version, 1.6.4.
|
49
|
+
|
50
|
+
JrJackson is now used to parse JSON when Sensu is running on JRuby.
|
51
|
+
|
52
|
+
The Sensu API now listens immediately on service start, even before it has
|
53
|
+
successfully connected to Redis and the Sensu Transport. It will now
|
54
|
+
respond with a `500` response, with a descriptive error message, when it
|
55
|
+
has not yet initialized its connections or it is reconnecting to either
|
56
|
+
Redis or the Sensu Transport. The API /info and /health endpoints will
|
57
|
+
still respond normally while reconnecting.
|
58
|
+
|
1
59
|
## 0.23.3 - 2016-05-26
|
2
60
|
|
3
61
|
### Fixes
|
data/lib/sensu/api/process.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require "sensu/daemon"
|
2
|
+
require "sensu/api/validators"
|
2
3
|
|
3
4
|
gem "sinatra", "1.4.6"
|
4
5
|
gem "async_sinatra", "1.2.0"
|
5
6
|
|
6
7
|
unless RUBY_PLATFORM =~ /java/
|
7
|
-
gem "thin", "1.6.
|
8
|
+
gem "thin", "1.6.4"
|
8
9
|
require "thin"
|
9
10
|
end
|
10
11
|
|
@@ -22,10 +23,9 @@ module Sensu
|
|
22
23
|
bootstrap(options)
|
23
24
|
setup_process(options)
|
24
25
|
EM::run do
|
25
|
-
setup_connections
|
26
|
-
|
27
|
-
|
28
|
-
end
|
26
|
+
setup_connections
|
27
|
+
start
|
28
|
+
setup_signal_traps
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -84,8 +84,8 @@ module Sensu
|
|
84
84
|
def stop
|
85
85
|
@logger.warn("stopping")
|
86
86
|
stop_server do
|
87
|
-
settings.redis.close if settings.redis
|
88
|
-
settings.transport.close if settings.transport
|
87
|
+
settings.redis.close if settings.respond_to?(:redis)
|
88
|
+
settings.transport.close if settings.respond_to?(:transport)
|
89
89
|
super
|
90
90
|
end
|
91
91
|
end
|
@@ -124,11 +124,18 @@ module Sensu
|
|
124
124
|
env["rack.input"].rewind
|
125
125
|
end
|
126
126
|
|
127
|
-
def
|
128
|
-
if settings.
|
129
|
-
|
130
|
-
|
131
|
-
|
127
|
+
def connected?
|
128
|
+
if settings.respond_to?(:redis) && settings.respond_to?(:transport)
|
129
|
+
unless ["/info", "/health"].include?(env["REQUEST_PATH"])
|
130
|
+
unless settings.redis.connected?
|
131
|
+
not_connected!("not connected to redis")
|
132
|
+
end
|
133
|
+
unless settings.transport.connected?
|
134
|
+
not_connected!("not connected to transport")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
else
|
138
|
+
not_connected!("redis and transport connections not initialized")
|
132
139
|
end
|
133
140
|
end
|
134
141
|
|
@@ -140,6 +147,22 @@ module Sensu
|
|
140
147
|
@auth.credentials == [settings.api[:user], settings.api[:password]]
|
141
148
|
end
|
142
149
|
|
150
|
+
def protected!
|
151
|
+
if settings.api[:user] && settings.api[:password]
|
152
|
+
return if authorized?
|
153
|
+
headers["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
|
154
|
+
unauthorized!
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def error!(body="")
|
159
|
+
throw(:halt, [500, body])
|
160
|
+
end
|
161
|
+
|
162
|
+
def not_connected!(message)
|
163
|
+
error!(Sensu::JSON.dump(:error => message))
|
164
|
+
end
|
165
|
+
|
143
166
|
def bad_request!
|
144
167
|
ahalt 400
|
145
168
|
end
|
@@ -152,8 +175,8 @@ module Sensu
|
|
152
175
|
ahalt 404
|
153
176
|
end
|
154
177
|
|
155
|
-
def
|
156
|
-
ahalt
|
178
|
+
def precondition_failed!
|
179
|
+
ahalt 412
|
157
180
|
end
|
158
181
|
|
159
182
|
def created!(response)
|
@@ -306,6 +329,7 @@ module Sensu
|
|
306
329
|
settings.cors.each do |header, value|
|
307
330
|
headers["Access-Control-Allow-#{header}"] = value
|
308
331
|
end
|
332
|
+
connected?
|
309
333
|
protected! unless env["REQUEST_METHOD"] == "OPTIONS"
|
310
334
|
end
|
311
335
|
|
@@ -342,27 +366,27 @@ module Sensu
|
|
342
366
|
healthy << (info[:keepalives][:messages] <= max_messages)
|
343
367
|
healthy << (info[:results][:messages] <= max_messages)
|
344
368
|
end
|
345
|
-
healthy.all? ? no_content! :
|
369
|
+
healthy.all? ? no_content! : precondition_failed!
|
346
370
|
end
|
347
371
|
else
|
348
|
-
|
372
|
+
precondition_failed!
|
349
373
|
end
|
350
374
|
end
|
351
375
|
|
352
376
|
apost "/clients/?" do
|
353
|
-
|
354
|
-
:
|
355
|
-
:address => {:type => String, :nil_ok => false},
|
356
|
-
:subscriptions => {:type => Array, :nil_ok => false}
|
357
|
-
}
|
358
|
-
read_data(rules) do |data|
|
359
|
-
data[:keepalives] = false
|
377
|
+
read_data do |data|
|
378
|
+
data[:keepalives] = data.fetch(:keepalives, false)
|
360
379
|
data[:version] = VERSION
|
361
380
|
data[:timestamp] = Time.now.to_i
|
362
|
-
|
363
|
-
|
364
|
-
|
381
|
+
validator = Validators::Client.new
|
382
|
+
if validator.valid?(data)
|
383
|
+
settings.redis.set("client:#{data[:name]}", Sensu::JSON.dump(data)) do
|
384
|
+
settings.redis.sadd("clients", data[:name]) do
|
385
|
+
created!(Sensu::JSON.dump(:name => data[:name]))
|
386
|
+
end
|
365
387
|
end
|
388
|
+
else
|
389
|
+
bad_request!
|
366
390
|
end
|
367
391
|
end
|
368
392
|
end
|
@@ -582,102 +606,172 @@ module Sensu
|
|
582
606
|
end
|
583
607
|
|
584
608
|
aget "/aggregates/?" do
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
609
|
+
settings.redis.smembers("aggregates") do |aggregates|
|
610
|
+
aggregates.map! do |aggregate|
|
611
|
+
{:name => aggregate}
|
612
|
+
end
|
613
|
+
body Sensu::JSON.dump(aggregates)
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
aget %r{^/aggregates/([\w\.-]+)/?$} do |aggregate|
|
618
|
+
response = {
|
619
|
+
:clients => 0,
|
620
|
+
:checks => 0,
|
621
|
+
:results => {
|
622
|
+
:ok => 0,
|
623
|
+
:warning => 0,
|
624
|
+
:critical => 0,
|
625
|
+
:unknown => 0,
|
626
|
+
:total => 0,
|
627
|
+
:stale => 0
|
628
|
+
}
|
629
|
+
}
|
630
|
+
settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
631
|
+
unless aggregate_members.empty?
|
632
|
+
clients = []
|
633
|
+
checks = []
|
634
|
+
results = []
|
635
|
+
aggregate_members.each_with_index do |member, index|
|
636
|
+
client_name, check_name = member.split(":")
|
637
|
+
clients << client_name
|
638
|
+
checks << check_name
|
639
|
+
result_key = "result:#{client_name}:#{check_name}"
|
640
|
+
settings.redis.get(result_key) do |result_json|
|
641
|
+
unless result_json.nil?
|
642
|
+
results << Sensu::JSON.load(result_json)
|
643
|
+
else
|
644
|
+
settings.redis.srem("aggregates:#{aggregate}", member)
|
593
645
|
end
|
594
|
-
|
595
|
-
:
|
596
|
-
:
|
597
|
-
|
598
|
-
|
599
|
-
|
646
|
+
if index == aggregate_members.length - 1
|
647
|
+
response[:clients] = clients.uniq.length
|
648
|
+
response[:checks] = checks.uniq.length
|
649
|
+
max_age = integer_parameter(params[:max_age])
|
650
|
+
if max_age
|
651
|
+
result_count = results.length
|
652
|
+
timestamp = Time.now.to_i - max_age
|
653
|
+
results.reject! do |result|
|
654
|
+
result[:executed] < timestamp
|
655
|
+
end
|
656
|
+
response[:results][:stale] = result_count - results.length
|
657
|
+
end
|
658
|
+
response[:results][:total] = results.length
|
659
|
+
results.each do |result|
|
660
|
+
severity = (SEVERITIES[result[:status]] || "unknown")
|
661
|
+
response[:results][severity.to_sym] += 1
|
662
|
+
end
|
600
663
|
body Sensu::JSON.dump(response)
|
601
664
|
end
|
602
665
|
end
|
603
666
|
end
|
604
667
|
else
|
605
|
-
|
668
|
+
not_found!
|
606
669
|
end
|
607
670
|
end
|
608
671
|
end
|
609
672
|
|
610
|
-
|
611
|
-
settings.redis.smembers("aggregates
|
612
|
-
|
613
|
-
aggregates
|
614
|
-
|
615
|
-
|
616
|
-
end
|
617
|
-
age = integer_parameter(params[:age])
|
618
|
-
if age
|
619
|
-
timestamp = Time.now.to_i - age
|
620
|
-
aggregates.reject! do |issued|
|
621
|
-
issued > timestamp
|
673
|
+
adelete %r{^/aggregates/([\w\.-]+)/?$} do |aggregate|
|
674
|
+
settings.redis.smembers("aggregates") do |aggregates|
|
675
|
+
if aggregates.include?(aggregate)
|
676
|
+
settings.redis.srem("aggregates", aggregate) do
|
677
|
+
settings.redis.del("aggregates:#{aggregate}") do
|
678
|
+
no_content!
|
622
679
|
end
|
623
680
|
end
|
624
|
-
body Sensu::JSON.dump(pagination(aggregates))
|
625
681
|
else
|
626
682
|
not_found!
|
627
683
|
end
|
628
684
|
end
|
629
685
|
end
|
630
686
|
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
687
|
+
aget %r{^/aggregates/([\w\.-]+)/clients/?$} do |aggregate|
|
688
|
+
response = Array.new
|
689
|
+
settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
690
|
+
unless aggregate_members.empty?
|
691
|
+
clients = Hash.new
|
692
|
+
aggregate_members.each do |member|
|
693
|
+
client_name, check_name = member.split(":")
|
694
|
+
clients[client_name] ||= []
|
695
|
+
clients[client_name] << check_name
|
638
696
|
end
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
697
|
+
clients.each do |client_name, checks|
|
698
|
+
response << {
|
699
|
+
:name => client_name,
|
700
|
+
:checks => checks
|
701
|
+
}
|
643
702
|
end
|
703
|
+
body Sensu::JSON.dump(response)
|
644
704
|
else
|
645
705
|
not_found!
|
646
706
|
end
|
647
707
|
end
|
648
708
|
end
|
649
709
|
|
650
|
-
aget %r{^/aggregates
|
651
|
-
|
652
|
-
settings.redis.
|
653
|
-
unless
|
654
|
-
|
655
|
-
|
656
|
-
|
710
|
+
aget %r{^/aggregates/([\w\.-]+)/checks/?$} do |aggregate|
|
711
|
+
response = Array.new
|
712
|
+
settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
713
|
+
unless aggregate_members.empty?
|
714
|
+
checks = Hash.new
|
715
|
+
aggregate_members.each do |member|
|
716
|
+
client_name, check_name = member.split(":")
|
717
|
+
checks[check_name] ||= []
|
718
|
+
checks[check_name] << client_name
|
657
719
|
end
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
720
|
+
checks.each do |check_name, clients|
|
721
|
+
response << {
|
722
|
+
:name => check_name,
|
723
|
+
:clients => clients
|
724
|
+
}
|
725
|
+
end
|
726
|
+
body Sensu::JSON.dump(response)
|
727
|
+
else
|
728
|
+
not_found!
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
aget %r{^/aggregates/([\w\.-]+)/results/([\w\.-]+)/?$} do |aggregate, severity|
|
734
|
+
response = Array.new
|
735
|
+
if SEVERITIES.include?(severity)
|
736
|
+
settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
737
|
+
unless aggregate_members.empty?
|
738
|
+
summaries = Hash.new
|
739
|
+
max_age = integer_parameter(params[:max_age])
|
740
|
+
current_timestamp = Time.now.to_i
|
741
|
+
aggregate_members.each_with_index do |member, index|
|
742
|
+
client_name, check_name = member.split(":")
|
743
|
+
result_key = "result:#{client_name}:#{check_name}"
|
744
|
+
settings.redis.get(result_key) do |result_json|
|
745
|
+
unless result_json.nil?
|
746
|
+
result = Sensu::JSON.load(result_json)
|
747
|
+
if SEVERITIES[result[:status]] == severity &&
|
748
|
+
(max_age.nil? || result[:executed] >= (current_timestamp - max_age))
|
749
|
+
summaries[check_name] ||= {}
|
750
|
+
summaries[check_name][result[:output]] ||= {:total => 0, :clients => []}
|
751
|
+
summaries[check_name][result[:output]][:total] += 1
|
752
|
+
summaries[check_name][result[:output]][:clients] << client_name
|
753
|
+
end
|
754
|
+
end
|
755
|
+
if index == aggregate_members.length - 1
|
756
|
+
summaries.each do |check_name, outputs|
|
757
|
+
summary = outputs.map do |output, output_summary|
|
758
|
+
{:output => output}.merge(output_summary)
|
759
|
+
end
|
760
|
+
response << {
|
761
|
+
:check => check_name,
|
762
|
+
:summary => summary
|
763
|
+
}
|
764
|
+
end
|
765
|
+
body Sensu::JSON.dump(response)
|
669
766
|
end
|
670
|
-
response[:outputs] = outputs
|
671
767
|
end
|
672
768
|
end
|
673
|
-
|
674
|
-
|
675
|
-
end
|
676
|
-
body Sensu::JSON.dump(response)
|
769
|
+
else
|
770
|
+
not_found!
|
677
771
|
end
|
678
|
-
else
|
679
|
-
not_found!
|
680
772
|
end
|
773
|
+
else
|
774
|
+
bad_request!
|
681
775
|
end
|
682
776
|
end
|
683
777
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "sensu/settings/rules"
|
2
|
+
require "sensu/settings/validators/client"
|
3
|
+
|
4
|
+
module Sensu
|
5
|
+
module API
|
6
|
+
module Validators
|
7
|
+
# The error class for validation.
|
8
|
+
class Invalid < RuntimeError; end
|
9
|
+
|
10
|
+
class Client
|
11
|
+
# Include Sensu Settings rules and client validator.
|
12
|
+
include Sensu::Settings::Rules
|
13
|
+
include Sensu::Settings::Validators::Client
|
14
|
+
|
15
|
+
# Determine if a client definition is valid.
|
16
|
+
#
|
17
|
+
# @param client [Hash]
|
18
|
+
# @return [TrueClass, FalseClass]
|
19
|
+
def valid?(client)
|
20
|
+
validate_client(client)
|
21
|
+
true
|
22
|
+
rescue Invalid
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# This method is called when `validate_client()` encounters an
|
29
|
+
# invalid definition object. This method raises an exception
|
30
|
+
# to be caught by `valid?()`.
|
31
|
+
def invalid(*arguments)
|
32
|
+
raise Invalid
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/sensu/cli.rb
CHANGED
@@ -26,6 +26,9 @@ module Sensu
|
|
26
26
|
opts.on("-d", "--config_dir DIR[,DIR]", "DIR or comma-delimited DIR list for Sensu JSON config files") do |dir|
|
27
27
|
options[:config_dirs] = dir.split(",")
|
28
28
|
end
|
29
|
+
opts.on("--validate_config", "Validate the compiled configuration and exit") do
|
30
|
+
options[:validate_config] = true
|
31
|
+
end
|
29
32
|
opts.on("-P", "--print_config", "Print the compiled configuration and exit") do
|
30
33
|
options[:print_config] = true
|
31
34
|
end
|
data/lib/sensu/client/process.rb
CHANGED
@@ -99,12 +99,40 @@ module Sensu
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
+
# Perform token substitution for an object. String values are
|
103
|
+
# passed to `substitute_tokens()`, arrays and sub-hashes are
|
104
|
+
# processed recursively. Numeric values are ignored.
|
105
|
+
#
|
106
|
+
# @param object [Object]
|
107
|
+
# @return [Array] containing the updated object with substituted
|
108
|
+
# values and an array of unmatched tokens.
|
109
|
+
def object_substitute_tokens(object)
|
110
|
+
unmatched_tokens = []
|
111
|
+
case object
|
112
|
+
when Hash
|
113
|
+
object.each do |key, value|
|
114
|
+
object[key], unmatched = object_substitute_tokens(value)
|
115
|
+
unmatched_tokens.push(*unmatched)
|
116
|
+
end
|
117
|
+
when Array
|
118
|
+
object.map! do |value|
|
119
|
+
value, unmatched = object_substitute_tokens(value)
|
120
|
+
unmatched_tokens.push(*unmatched)
|
121
|
+
value
|
122
|
+
end
|
123
|
+
when String
|
124
|
+
object, unmatched_tokens = substitute_tokens(object, @settings[:client])
|
125
|
+
end
|
126
|
+
[object, unmatched_tokens.uniq]
|
127
|
+
end
|
128
|
+
|
102
129
|
# Execute a check command, capturing its output (STDOUT/ERR),
|
103
130
|
# exit status code, execution duration, timestamp, and publish
|
104
131
|
# the result. This method guards against multiple executions for
|
105
|
-
# the same check. Check
|
106
|
-
# associated client attribute values
|
107
|
-
#
|
132
|
+
# the same check. Check attribute value tokens are substituted
|
133
|
+
# with the associated client attribute values, via
|
134
|
+
# `object_substitute_tokens()`. If there are unmatched check
|
135
|
+
# attribute value tokens, the check will not be executed,
|
108
136
|
# instead a check result will be published reporting the
|
109
137
|
# unmatched tokens.
|
110
138
|
#
|
@@ -113,11 +141,11 @@ module Sensu
|
|
113
141
|
@logger.debug("attempting to execute check command", :check => check)
|
114
142
|
unless @checks_in_progress.include?(check[:name])
|
115
143
|
@checks_in_progress << check[:name]
|
116
|
-
|
144
|
+
check, unmatched_tokens = object_substitute_tokens(check)
|
117
145
|
if unmatched_tokens.empty?
|
118
|
-
check[:executed] = Time.now.to_i
|
119
146
|
started = Time.now.to_f
|
120
|
-
|
147
|
+
check[:executed] = started.to_i
|
148
|
+
Spawn.process(check[:command], :timeout => check[:timeout]) do |output, status|
|
121
149
|
check[:duration] = ("%.3f" % (Time.now.to_f - started)).to_f
|
122
150
|
check[:output] = output
|
123
151
|
check[:status] = status
|