Class: LogStash::Inputs::Exec

Inherits:
Base
  • Object
show all
Includes:
PluginMixins::Scheduler
Defined in:
lib/logstash/inputs/exec.rb

Overview

Periodically run a shell command and capture the whole output as an event.

Notes:

  • The ‘command` field of this event will be the command run.

  • The ‘message` field of this event will be the entire stdout of the command.

Instance Method Summary collapse

Instance Method Details

#execute(queue) ⇒ Object

Execute a given command

Parameters:

  • queue

    the LS queue to append events to



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/logstash/inputs/exec.rb', line 73

def execute(queue)
  start = Time.now
  output = exit_status = nil
  begin
    @logger.debug? && @logger.debug("Running exec", :command => @command)
    output, exit_status = run_command()
  rescue StandardError => e
    @logger.error("Error while running command",
      :command => @command, :exception => e, :backtrace => e.backtrace)
  rescue Exception => e
    @logger.error("Exception while running command",
      :command => @command, :exception => e, :backtrace => e.backtrace)
  end
  duration = Time.now.to_r - start.to_r
  @logger.debug? && @logger.debug("Command completed", :command => @command, :duration => duration.to_f)
  if output
    @codec.decode(output) do |event|
      decorate(event)
      event.set(@host_name_field, @hostname) unless event.include?(@host_name_field)
      event.set(@process_command_line_field, @command) unless event.include?(@process_command_line_field)
      event.set(@process_exit_code_field, exit_status) unless event.include?(@process_exit_code_field)
      event.set(@process_elapsed_time_field, to_nanos(duration)) if @process_elapsed_time_field
      event.set(@legacy_duration_field, duration.to_f) if @legacy_duration_field
      queue << event
    end
  end
  duration
end

#registerObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/logstash/inputs/exec.rb', line 39

def register
  @hostname = Socket.gethostname.freeze

  if (@interval.nil? && @schedule.nil?) || (@interval && @schedule)
    raise LogStash::ConfigurationError, "exec input: either 'interval' or 'schedule' option must be defined."
  end

  @host_name_field =            ecs_select[disabled: 'host',                     v1: '[host][name]']
  @process_command_line_field = ecs_select[disabled: 'command',                  v1: '[process][command_line]']
  @process_exit_code_field =    ecs_select[disabled: '[@metadata][exit_status]', v1: '[process][exit_code]']
  
  # migrate elapsed time tracking to whole nanos, from legacy floating-point fractional seconds
  @process_elapsed_time_field = ecs_select[disabled: nil,                        v1: '[@metadata][input][exec][process][elapsed_time]'] # in nanos
  @legacy_duration_field =      ecs_select[disabled: '[@metadata][duration]',    v1: nil] # in seconds
end

#run(queue) ⇒ Object

def register



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/logstash/inputs/exec.rb', line 55

def run(queue)
  if @schedule
    scheduler.cron(@schedule) { execute(queue) }
    scheduler.join
  else
    while !stop?
      duration = execute(queue)
      wait_until_end_of_interval(duration)
    end # loop
  end
end

#stopObject

def run



67
68
69
# File 'lib/logstash/inputs/exec.rb', line 67

def stop
  close_out_and_in
end