fluentd 1.9.3 → 1.11.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/issue-auto-closer.yml +12 -0
  3. data/CHANGELOG.md +182 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +4 -0
  6. data/docs/SECURITY_AUDIT.pdf +0 -0
  7. data/lib/fluent/command/debug.rb +1 -0
  8. data/lib/fluent/command/fluentd.rb +25 -1
  9. data/lib/fluent/config.rb +1 -0
  10. data/lib/fluent/daemonizer.rb +88 -0
  11. data/lib/fluent/log.rb +45 -6
  12. data/lib/fluent/match.rb +1 -1
  13. data/lib/fluent/msgpack_factory.rb +13 -6
  14. data/lib/fluent/plugin/buffer.rb +2 -2
  15. data/lib/fluent/plugin/in_dummy.rb +3 -3
  16. data/lib/fluent/plugin/in_forward.rb +2 -2
  17. data/lib/fluent/plugin/in_gc_stat.rb +16 -0
  18. data/lib/fluent/plugin/in_http.rb +146 -75
  19. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  20. data/lib/fluent/plugin/in_syslog.rb +4 -4
  21. data/lib/fluent/plugin/in_tail.rb +40 -31
  22. data/lib/fluent/plugin/in_tail/position_file.rb +23 -6
  23. data/lib/fluent/plugin/in_unix.rb +77 -77
  24. data/lib/fluent/plugin/out_copy.rb +1 -1
  25. data/lib/fluent/plugin/out_file.rb +1 -1
  26. data/lib/fluent/plugin/out_forward.rb +25 -22
  27. data/lib/fluent/plugin/out_forward/handshake_protocol.rb +4 -0
  28. data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
  29. data/lib/fluent/plugin/out_http.rb +15 -2
  30. data/lib/fluent/plugin/parser_multiline.rb +1 -1
  31. data/lib/fluent/plugin/parser_syslog.rb +303 -62
  32. data/lib/fluent/plugin/sd_file.rb +1 -0
  33. data/lib/fluent/plugin/sd_srv.rb +135 -0
  34. data/lib/fluent/plugin_helper/cert_option.rb +15 -2
  35. data/lib/fluent/plugin_helper/child_process.rb +3 -2
  36. data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
  37. data/lib/fluent/plugin_helper/server.rb +3 -1
  38. data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
  39. data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
  40. data/lib/fluent/plugin_helper/socket.rb +20 -2
  41. data/lib/fluent/plugin_helper/socket_option.rb +21 -3
  42. data/lib/fluent/supervisor.rb +21 -9
  43. data/lib/fluent/system_config.rb +2 -1
  44. data/lib/fluent/test/filter_test.rb +2 -2
  45. data/lib/fluent/test/output_test.rb +3 -3
  46. data/lib/fluent/version.rb +1 -1
  47. data/test/command/test_fluentd.rb +71 -12
  48. data/test/config/test_system_config.rb +2 -0
  49. data/test/helper.rb +2 -2
  50. data/test/plugin/in_tail/test_fifo.rb +121 -0
  51. data/test/plugin/in_tail/test_io_handler.rb +132 -0
  52. data/test/plugin/in_tail/test_position_file.rb +25 -1
  53. data/test/plugin/out_forward/test_handshake_protocol.rb +10 -1
  54. data/test/plugin/out_forward/test_load_balancer.rb +46 -0
  55. data/test/plugin/test_buf_file.rb +3 -1
  56. data/test/plugin/test_buffer.rb +20 -0
  57. data/test/plugin/test_compressable.rb +7 -4
  58. data/test/plugin/test_in_dummy.rb +12 -14
  59. data/test/plugin/test_in_forward.rb +2 -2
  60. data/test/plugin/test_in_gc_stat.rb +24 -1
  61. data/test/plugin/test_in_http.rb +57 -0
  62. data/test/plugin/test_in_syslog.rb +16 -1
  63. data/test/plugin/test_in_tail.rb +43 -20
  64. data/test/plugin/test_in_unix.rb +128 -73
  65. data/test/plugin/test_out_forward.rb +39 -3
  66. data/test/plugin/test_out_http.rb +38 -0
  67. data/test/plugin/test_out_null.rb +1 -1
  68. data/test/plugin/test_output_as_buffered_retries.rb +12 -4
  69. data/test/plugin/test_output_as_buffered_secondary.rb +9 -1
  70. data/test/plugin/test_parser_syslog.rb +106 -46
  71. data/test/plugin/test_sd_file.rb +17 -0
  72. data/test/plugin/test_sd_srv.rb +230 -0
  73. data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
  74. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  75. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  76. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  77. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  78. data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
  79. data/test/plugin_helper/http_server/test_app.rb +1 -1
  80. data/test/plugin_helper/http_server/test_route.rb +1 -1
  81. data/test/plugin_helper/test_cert_option.rb +2 -0
  82. data/test/plugin_helper/test_child_process.rb +20 -3
  83. data/test/plugin_helper/test_http_server_helper.rb +2 -2
  84. data/test/plugin_helper/test_record_accessor.rb +41 -0
  85. data/test/plugin_helper/test_server.rb +1 -1
  86. data/test/plugin_helper/test_service_discovery.rb +37 -4
  87. data/test/plugin_helper/test_socket.rb +131 -0
  88. data/test/test_daemonizer.rb +91 -0
  89. data/test/test_log.rb +44 -0
  90. data/test/test_msgpack_factory.rb +18 -0
  91. metadata +28 -2
@@ -85,6 +85,7 @@ module Fluent
85
85
  fetch_server_info
86
86
  rescue => e
87
87
  @log.error("sd_file: #{e}")
88
+ return
88
89
  end
89
90
 
90
91
  if s.nil?
@@ -0,0 +1,135 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'resolv'
18
+
19
+ require 'fluent/plugin_helper'
20
+ require 'fluent/plugin/service_discovery'
21
+
22
+ module Fluent
23
+ module Plugin
24
+ class SrvServiceDiscovery < ServiceDiscovery
25
+ include PluginHelper::Mixin
26
+
27
+ Plugin.register_sd('srv', self)
28
+
29
+ helpers :timer
30
+
31
+ desc 'Service without underscore in RFC2782'
32
+ config_param :service, :string
33
+ desc 'Proto without underscore in RFC2782'
34
+ config_param :proto, :string, default: 'tcp'
35
+ desc 'Name in RFC2782'
36
+ config_param :hostname, :string
37
+ desc 'hostname of DNS server to request the SRV record'
38
+ config_param :dns_server_host, :string, default: nil
39
+ desc 'interval of requesting to DNS server'
40
+ config_param :interval, :integer, default: 60
41
+ desc "resolve hostname to IP addr of SRV's Target"
42
+ config_param :dns_lookup, :bool, default: true
43
+ desc 'The shared key per server'
44
+ config_param :shared_key, :string, default: nil, secret: true
45
+ desc 'The username for authentication'
46
+ config_param :username, :string, default: ''
47
+ desc 'The password for authentication'
48
+ config_param :password, :string, default: '', secret: true
49
+
50
+ def initialize
51
+ super
52
+ @target = nil
53
+ end
54
+
55
+ def configure(conf)
56
+ super
57
+
58
+ @target = "_#{@service}._#{@proto}.#{@hostname}"
59
+ @dns_resolve =
60
+ if @dns_server_host.nil?
61
+ Resolv::DNS.new
62
+ elsif @dns_server_host.include?(':') # e.g. 127.0.0.1:8600
63
+ host, port = @dns_server_host.split(':', 2)
64
+ Resolv::DNS.new(nameserver_port: [[host, port.to_i]])
65
+ else
66
+ Resolv::DNS.new(nameserver: @dns_server_host)
67
+ end
68
+
69
+ @services = fetch_srv_record
70
+ end
71
+
72
+ def start(queue)
73
+ timer_execute(:"sd_srv_record_#{@target}", @interval) do
74
+ refresh_srv_records(queue)
75
+ end
76
+
77
+ super()
78
+ end
79
+
80
+ private
81
+
82
+ def refresh_srv_records(queue)
83
+ s = begin
84
+ fetch_srv_record
85
+ rescue => e
86
+ @log.error("sd_srv: #{e}")
87
+ return
88
+ end
89
+
90
+ if s.nil? || s.empty?
91
+ return
92
+ end
93
+
94
+ diff = []
95
+ join = s - @services
96
+ # Need service_in first to guarantee that server exist at least one all time.
97
+ join.each do |j|
98
+ diff << ServiceDiscovery.service_in_msg(j)
99
+ end
100
+
101
+ drain = @services - s
102
+ drain.each do |d|
103
+ diff << ServiceDiscovery.service_out_msg(d)
104
+ end
105
+
106
+ @services = s
107
+
108
+ diff.each do |a|
109
+ queue.push(a)
110
+ end
111
+ end
112
+
113
+ def fetch_srv_record
114
+ adders = @dns_resolve.getresources(@target, Resolv::DNS::Resource::IN::SRV)
115
+
116
+ services = []
117
+
118
+ adders.each do |addr|
119
+ host = @dns_lookup ? dns_lookup!(addr.target) : addr.target
120
+ services << [
121
+ addr.priority,
122
+ Service.new(:srv, host.to_s, addr.port.to_i, addr.target.to_s, addr.weight, false, @username, @password, @shared_key)
123
+ ]
124
+ end
125
+
126
+ services.sort_by(&:first).flat_map { |s| s[1] }
127
+ end
128
+
129
+ def dns_lookup!(host)
130
+ # may need to cache the result
131
+ @dns_resolve.getaddress(host) # get first result for now
132
+ end
133
+ end
134
+ end
135
+ end
@@ -36,7 +36,7 @@ module Fluent
36
36
  end
37
37
 
38
38
  if conf.client_cert_auth
39
- ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
39
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
40
40
  end
41
41
 
42
42
  ctx.ca_file = conf.ca_path
@@ -45,6 +45,16 @@ module Fluent
45
45
  if extra && !extra.empty?
46
46
  ctx.extra_chain_cert = extra
47
47
  end
48
+ if conf.cert_verifier
49
+ sandbox = Class.new
50
+ ctx.verify_callback = if File.exist?(conf.cert_verifier)
51
+ verifier = File.read(conf.cert_verifier)
52
+ sandbox.instance_eval(verifier, File.basename(conf.cert_verifier))
53
+ else
54
+ sandbox.instance_eval(conf.cert_verifier)
55
+ end
56
+ end
57
+
48
58
  Fluent::TLS.set_version_to_context(ctx, version, conf.min_version, conf.max_version)
49
59
 
50
60
  ctx
@@ -171,9 +181,12 @@ module Fluent
171
181
 
172
182
  def cert_option_certificates_from_file(path)
173
183
  data = File.read(path)
174
- pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\n(?:[^-]*\n)+-+END CERTIFICATE-+\n?', Regexp::MULTILINE)
184
+ pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\r?\n(?:[^-]*\r?\n)+-+END CERTIFICATE-+\r?\n?', Regexp::MULTILINE)
175
185
  list = []
176
186
  data.scan(pattern){|match| list << OpenSSL::X509::Certificate.new(match) }
187
+ if list.length == 0
188
+ log.warn "cert_path does not contain a valid certificate"
189
+ end
177
190
  list
178
191
  end
179
192
  end
@@ -259,6 +259,9 @@ module Fluent
259
259
 
260
260
  if !mode.include?(:stderr) && !mode.include?(:read_with_stderr)
261
261
  spawn_opts[:err] = IO::NULL if stderr == :discard
262
+ if !mode.include?(:read) && !mode.include?(:read_with_stderr)
263
+ spawn_opts[:out] = IO::NULL
264
+ end
262
265
  writeio, readio, wait_thread = *Open3.popen2(*spawn_args, spawn_opts)
263
266
  elsif mode.include?(:read_with_stderr)
264
267
  writeio, readio, wait_thread = *Open3.popen2e(*spawn_args, spawn_opts)
@@ -275,8 +278,6 @@ module Fluent
275
278
  if mode.include?(:read) || mode.include?(:read_with_stderr)
276
279
  readio.set_encoding(external_encoding, internal_encoding, **encoding_options)
277
280
  readio_in_use = true
278
- else
279
- readio.reopen(IO::NULL) if readio
280
281
  end
281
282
  if mode.include?(:stderr)
282
283
  stderrio.set_encoding(external_encoding, internal_encoding, **encoding_options)
@@ -41,9 +41,11 @@ module Fluent
41
41
  else
42
42
  mcall = method(:call_dig)
43
43
  mdelete = method(:delete_nest)
44
+ mset = method(:set_nest)
44
45
  singleton_class.module_eval do
45
46
  define_method(:call, mcall)
46
47
  define_method(:delete, mdelete)
48
+ define_method(:set, mset)
47
49
  end
48
50
  end
49
51
  end
@@ -75,6 +77,18 @@ module Fluent
75
77
  nil
76
78
  end
77
79
 
80
+ def set(r, v)
81
+ r[@keys] = v
82
+ end
83
+
84
+ # set_nest doesn't create intermediate object. If key doesn't exist, no effect.
85
+ # See also: https://bugs.ruby-lang.org/issues/11747
86
+ def set_nest(r, v)
87
+ r.dig(*@dig_keys)&.[]=(@last_key, v)
88
+ rescue
89
+ nil
90
+ end
91
+
78
92
  def self.parse_parameter(param)
79
93
  if param.start_with?('$.')
80
94
  parse_dot_notation(param)
@@ -243,7 +243,7 @@ module Fluent
243
243
  :protocol, :version, :min_version, :max_version, :ciphers, :insecure,
244
244
  :ca_path, :cert_path, :private_key_path, :private_key_passphrase, :client_cert_auth,
245
245
  :ca_cert_path, :ca_private_key_path, :ca_private_key_passphrase,
246
- :generate_private_key_length,
246
+ :cert_verifier, :generate_private_key_length,
247
247
  :generate_cert_country, :generate_cert_state, :generate_cert_state,
248
248
  :generate_cert_locality, :generate_cert_common_name,
249
249
  :generate_cert_expiration, :generate_cert_digest,
@@ -281,6 +281,8 @@ module Fluent
281
281
  config_param :ca_private_key_path, :string, default: nil
282
282
  config_param :ca_private_key_passphrase, :string, default: nil, secret: true
283
283
 
284
+ config_param :cert_verifier, :string, default: nil
285
+
284
286
  # Options for generating certs by private CA certs or self-signed
285
287
  config_param :generate_private_key_length, :integer, default: 2048
286
288
  config_param :generate_cert_country, :string, default: 'US'
@@ -43,6 +43,13 @@ module Fluent
43
43
  super
44
44
  end
45
45
 
46
+ %i[after_start stop before_shutdown shutdown after_shutdown close terminate].each do |mth|
47
+ define_method(mth) do
48
+ @discovery_manager&.__send__(mth)
49
+ super()
50
+ end
51
+ end
52
+
46
53
  private
47
54
 
48
55
  # @param title [Symbol] the thread name. this value should be unique.
@@ -60,6 +60,14 @@ module Fluent
60
60
  end
61
61
  end
62
62
 
63
+ %i[after_start stop before_shutdown shutdown after_shutdown close terminate].each do |mth|
64
+ define_method(mth) do
65
+ @discoveries.each do |d|
66
+ d.__send__(mth)
67
+ end
68
+ end
69
+ end
70
+
63
71
  def run_once
64
72
  # Don't care race in this loop intentionally
65
73
  s = @queue.size
@@ -145,9 +145,16 @@ module Fluent
145
145
  context.ciphers = ciphers
146
146
  context.verify_mode = OpenSSL::SSL::VERIFY_PEER
147
147
  context.cert_store = cert_store
148
- context.verify_hostname = true if verify_fqdn && fqdn && context.respond_to?(:verify_hostname=)
149
- context.cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) if cert_path
148
+ context.verify_hostname = verify_fqdn && fqdn
150
149
  context.key = OpenSSL::PKey::read(File.read(private_key_path), private_key_passphrase) if private_key_path
150
+
151
+ if cert_path
152
+ certs = socket_certificates_from_file(cert_path)
153
+ context.cert = certs.shift
154
+ unless certs.empty?
155
+ context.extra_chain_cert = certs
156
+ end
157
+ end
151
158
  end
152
159
  Fluent::TLS.set_version_to_context(context, version, min_version, max_version)
153
160
 
@@ -186,6 +193,17 @@ module Fluent
186
193
  end
187
194
  end
188
195
 
196
+ def socket_certificates_from_file(path)
197
+ data = File.read(path)
198
+ pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\r?\n(?:[^-]*\r?\n)+-+END CERTIFICATE-+\r?\n?', Regexp::MULTILINE)
199
+ list = []
200
+ data.scan(pattern) { |match| list << OpenSSL::X509::Certificate.new(match) }
201
+ if list.length == 0
202
+ log.warn "cert_path does not contain a valid certificate"
203
+ end
204
+ list
205
+ end
206
+
189
207
  def self.tls_verify_result_name(code)
190
208
  case code
191
209
  when OpenSSL::X509::V_OK then 'V_OK'
@@ -21,6 +21,8 @@ require 'fcntl'
21
21
  module Fluent
22
22
  module PluginHelper
23
23
  module SocketOption
24
+ # ref: https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-linger
25
+ FORMAT_STRUCT_LINGER_WINDOWS = 'S!S!' # { u_short l_onoff; u_short l_linger; }
24
26
  FORMAT_STRUCT_LINGER = 'I!I!' # { int l_onoff; int l_linger; }
25
27
  FORMAT_STRUCT_TIMEVAL = 'L!L!' # { time_t tv_sec; suseconds_t tv_usec; }
26
28
 
@@ -49,9 +51,25 @@ module Fluent
49
51
  if nonblock
50
52
  sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
51
53
  end
52
- if linger_timeout
53
- optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER)
54
- socket_option_set_one(sock, :SO_LINGER, optval)
54
+ if Fluent.windows?
55
+ # To prevent closing socket forcibly on Windows,
56
+ # this options shouldn't be set up when linger_timeout equals to 0 (including nil).
57
+ # This unintended behavior always ocurrs on Windows when linger_timeout.to_i == 0.
58
+ # This unintented behavior causes "Errno::ECONNRESET: An existing connection was forcibly
59
+ # closed by the remote host." on Windows.
60
+ if linger_timeout.to_i > 0
61
+ if linger_timeout >= 2**16
62
+ log.warn "maximum linger_timeout is 65535(2^16 - 1). Set to 65535 forcibly."
63
+ linger_timeout = 2**16 - 1
64
+ end
65
+ optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER_WINDOWS)
66
+ socket_option_set_one(sock, :SO_LINGER, optval)
67
+ end
68
+ else
69
+ if linger_timeout
70
+ optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER)
71
+ socket_option_set_one(sock, :SO_LINGER, optval)
72
+ end
55
73
  end
56
74
  if recv_timeout
57
75
  optval = [recv_timeout.to_i, 0].pack(FORMAT_STRUCT_TIMEVAL)
@@ -301,6 +301,7 @@ module Fluent
301
301
 
302
302
  log_level = params['log_level']
303
303
  suppress_repeated_stacktrace = params['suppress_repeated_stacktrace']
304
+ ignore_repeated_log_interval = params['ignore_repeated_log_interval']
304
305
 
305
306
  log_path = params['log_path']
306
307
  chuser = params['chuser']
@@ -308,7 +309,7 @@ module Fluent
308
309
  log_rotate_age = params['log_rotate_age']
309
310
  log_rotate_size = params['log_rotate_size']
310
311
 
311
- log_opts = {suppress_repeated_stacktrace: suppress_repeated_stacktrace}
312
+ log_opts = {suppress_repeated_stacktrace: suppress_repeated_stacktrace, ignore_repeated_log_interval: ignore_repeated_log_interval}
312
313
  logger_initializer = Supervisor::LoggerInitializer.new(
313
314
  log_path, log_level, chuser, chgroup, log_opts,
314
315
  log_rotate_age: log_rotate_age,
@@ -345,6 +346,7 @@ module Fluent
345
346
  chgroup: chgroup,
346
347
  chumask: 0,
347
348
  suppress_repeated_stacktrace: suppress_repeated_stacktrace,
349
+ ignore_repeated_log_interval: ignore_repeated_log_interval,
348
350
  daemonize: daemonize,
349
351
  rpc_endpoint: params['rpc_endpoint'],
350
352
  counter_server: params['counter_server'],
@@ -439,9 +441,10 @@ module Fluent
439
441
  self
440
442
  end
441
443
 
442
- def apply_options(format: nil, time_format: nil, log_dir_perm: nil)
444
+ def apply_options(format: nil, time_format: nil, log_dir_perm: nil, ignore_repeated_log_interval: nil)
443
445
  $log.format = format if format
444
446
  $log.time_format = time_format if time_format
447
+ $log.ignore_repeated_log_interval = ignore_repeated_log_interval if ignore_repeated_log_interval
445
448
 
446
449
  if @path && log_dir_perm
447
450
  File.chmod(log_dir_perm || 0755, File.dirname(@path))
@@ -468,6 +471,7 @@ module Fluent
468
471
  root_dir: nil,
469
472
  suppress_interval: 0,
470
473
  suppress_repeated_stacktrace: true,
474
+ ignore_repeated_log_interval: nil,
471
475
  without_source: nil,
472
476
  use_v1_config: true,
473
477
  strict_config_value: nil,
@@ -507,7 +511,7 @@ module Fluent
507
511
  @cl_opt = opt
508
512
  @conf = nil
509
513
 
510
- log_opts = { suppress_repeated_stacktrace: opt[:suppress_repeated_stacktrace] }
514
+ log_opts = {suppress_repeated_stacktrace: opt[:suppress_repeated_stacktrace], ignore_repeated_log_interval: opt[:ignore_repeated_log_interval]}
511
515
  @log = LoggerInitializer.new(
512
516
  @log_path, opt[:log_level], @chuser, @chgroup, log_opts,
513
517
  log_rotate_age: @log_rotate_age,
@@ -552,7 +556,7 @@ module Fluent
552
556
  end
553
557
 
554
558
  if dry_run
555
- $log.info 'finsihed dry run mode'
559
+ $log.info 'finished dry run mode'
556
560
  exit 0
557
561
  else
558
562
  supervise
@@ -589,7 +593,10 @@ module Fluent
589
593
 
590
594
  main_process do
591
595
  create_socket_manager if @standalone_worker
592
- ServerEngine::Privilege.change(@chuser, @chgroup) if @standalone_worker
596
+ if @standalone_worker
597
+ ServerEngine::Privilege.change(@chuser, @chgroup)
598
+ File.umask(0)
599
+ end
593
600
  MessagePackFactory.init(enable_time_support: @system_config.enable_msgpack_time_support)
594
601
  Fluent::Engine.init(@system_config)
595
602
  Fluent::Engine.run_configure(@conf)
@@ -628,6 +635,7 @@ module Fluent
628
635
  format: @system_config.log.format,
629
636
  time_format: @system_config.log.time_format,
630
637
  log_dir_perm: @system_config.dir_permission,
638
+ ignore_repeated_log_interval: @system_config.ignore_repeated_log_interval
631
639
  )
632
640
 
633
641
  $log.info :supervisor, 'parsing config file is succeeded', path: @config_path
@@ -690,6 +698,7 @@ module Fluent
690
698
  'root_dir' => @system_config.root_dir,
691
699
  'log_level' => @system_config.log_level,
692
700
  'suppress_repeated_stacktrace' => @system_config.suppress_repeated_stacktrace,
701
+ 'ignore_repeated_log_interval' => @system_config.ignore_repeated_log_interval,
693
702
  'rpc_endpoint' => @system_config.rpc_endpoint,
694
703
  'enable_get_dump' => @system_config.enable_get_dump,
695
704
  'counter_server' => @system_config.counter_server,
@@ -882,7 +891,11 @@ module Fluent
882
891
  RUBY_ENCODING_OPTIONS_REGEX = %r{\A(-E|--encoding=|--internal-encoding=|--external-encoding=)}.freeze
883
892
 
884
893
  def build_spawn_command
885
- fluentd_spawn_cmd = [ServerEngine.ruby_bin_path]
894
+ if ENV['TEST_RUBY_PATH']
895
+ fluentd_spawn_cmd = [ENV['TEST_RUBY_PATH']]
896
+ else
897
+ fluentd_spawn_cmd = [ServerEngine.ruby_bin_path]
898
+ end
886
899
 
887
900
  rubyopt = ENV['RUBYOPT']
888
901
  if rubyopt
@@ -897,10 +910,9 @@ module Fluent
897
910
 
898
911
  # Adding `-h` so that it can avoid ruby's command blocking
899
912
  # e.g. `ruby -Eascii-8bit:ascii-8bit` will block. but `ruby -Eascii-8bit:ascii-8bit -h` won't.
900
- cmd = fluentd_spawn_cmd.join(' ')
901
- _, e, s = Open3.capture3("#{cmd} -h")
913
+ _, e, s = Open3.capture3(*fluentd_spawn_cmd, "-h")
902
914
  if s.exitstatus != 0
903
- $log.error('Invalid option is passed to RUBYOPT', command: cmd, error: e)
915
+ $log.error('Invalid option is passed to RUBYOPT', command: fluentd_spawn_cmd, error: e)
904
916
  exit s.exitstatus
905
917
  end
906
918