Skip to content

Commit

Permalink
Guard launching duplicated fluentd with same configuration
Browse files Browse the repository at this point in the history
Before:

  If you launch multiple Fluentd instance with same
  configuration file, it causes a disaster with inconsistency
  processed buffer or pos file.

After:

  Detect fluentd service's main process and fetch FLUENT_CONF.
  if configuration is same as spawned process, abort it.

  It can block the following conditions are met:

  * fluentd is launched via systemd (fluent-package)
    configuration file is specified via FLUENT_CONF.
  * manually try to launch fluentd  with same configuration file as
    fluentd user with -c option.

  Thus running fluentd service and manually try to launch normal
  user case can't be detected.

NOTE: Windows is out of scope in this PR.

Signed-off-by: Kentaro Hayashi <hayashi@clear-code.com>
  • Loading branch information
kenhys committed Feb 14, 2024
1 parent 175d866 commit 9110af4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lib/fluent/command/fluentd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require 'fluent/log'
require 'fluent/env'
require 'fluent/version'
require 'fluent/process'

$fluentdargv = Marshal.load(Marshal.dump(ARGV))

Expand Down Expand Up @@ -340,6 +341,16 @@
early_exit = true
end

begin
running_fluentd_conf = Fluent::ProcessDetector.running_fluentd_conf
if opts[:config_path] and opts[:config_path] == running_fluentd_conf
puts "Error: can't start duplicate Fluentd instance with same #{opts[:config_path]}"
exit 2
end
rescue Errno::EACCES
# e.g. unprivileged access error, can't detect duplicated instance from command line parameter.
end

if start_service
Service.start(opts[:winsvc_name])
end
Expand Down
24 changes: 24 additions & 0 deletions lib/fluent/process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,32 @@
#

require 'fluent/compat/detach_process_mixin'
require 'fluent/env'

module Fluent
DetachProcessMixin = Fluent::Compat::DetachProcessMixin
DetachMultiProcessMixin = Fluent::Compat::DetachMultiProcessMixin

class ProcessDetector
def self.running_fluentd_conf
# Detect if same configuration is used
unless Fluent.windows?
IO.popen(["/usr/bin/ps", "-e", "-o", "uid,pid,ppid,cmd"]) do |_io|
_io.readlines.each do |line|
uid, pid, ppid, cmd = line.split(' ', 4)
# skip self and supervisor process
next if Process.pid == pid.to_i or Process.pid == ppid.to_i
if cmd and cmd.chomp.include?("fluentd") and ppid.to_i == 1
# under systemd control
File.open("/proc/#{pid.to_i}/environ") do |file|
conf = file.read.split("\u0000").select { |entry| entry.include?("FLUENT_CONF") }
return conf.first.split('=').last unless conf.empty?
end
end
end
end
end
return nil
end
end
end

0 comments on commit 9110af4

Please sign in to comment.