class ScheduleJob::Cron::Table

Public Class Methods

new(user = nil) click to toggle source
# File lib/schedule_job/cron.rb, line 26
def initialize(user = nil)
  @user = user
  load(user)
end

Public Instance Methods

add(job, dry_run = false) click to toggle source
# File lib/schedule_job/cron.rb, line 78
def add(job, dry_run = false)
  if @dry_run
    puts "Would schedule: #{job.to_s}"
  else
    puts "Scheduling: #{job.to_s}"
    install_cron_job(job)
  end

  cron_parser = CronParser.new(job.schedule_spec) rescue nil
  if cron_parser
    puts "Next three runs:"
    first_run_time = cron_parser.next(Time.now)
    second_run_time = cron_parser.next(first_run_time)
    third_run_time = cron_parser.next(second_run_time)

    puts "1. #{first_run_time}"
    puts "2. #{second_run_time}"
    puts "3. #{third_run_time}"
  end
end
empty?() click to toggle source
# File lib/schedule_job/cron.rb, line 31
def empty?
  @environment_vars.empty? && @jobs.empty?
end
install_cron_job(job) click to toggle source
# File lib/schedule_job/cron.rb, line 99
def install_cron_job(job)
  job_spec = job.specification

  new_crontab = [read_crontab(@user).strip, job_spec.strip].reject(&:empty?).join("\n")
  new_crontab << "\n"   # add a trailing newline
  write_crontab(new_crontab)
end
load(user = @user) click to toggle source
# File lib/schedule_job/cron.rb, line 35
def load(user = @user)
  @raw_crontab = read_crontab(user)
  @environment_vars, @jobs = parse_crontab(@raw_crontab)
end
parse_crontab(user_crontab) click to toggle source

returns lines that represent valid cron job specification lines

# File lib/schedule_job/cron.rb, line 57
def parse_crontab(user_crontab)
  parser = TableParser.new(user_crontab)

  return [], [] unless parser.valid?

  environment_vars = parser.environment_vars&.map do |env_directive|
    name = env_directive[:var].to_s
    expr = env_directive[:expr].to_s
    EnvironmentVar.new(name, expr)
  end || []

  jobs = parser.job_specs&.map do |jobspec|
    schedule_spec = jobspec.capture(:schedule_spec).to_s
    command = jobspec.capture(:command).to_s
    line_number = parser.get_line_number(jobspec)
    Job.new(schedule_spec, command, line_number, jobspec.offset)
  end || []

  [environment_vars, jobs]
end
read_crontab(user = @user) click to toggle source
# File lib/schedule_job/cron.rb, line 40
def read_crontab(user = @user)
  command = ["crontab", "-l"]
  command << "-u #{user}" if user
  command = command.join(" ")

  stdout, stderr, exit_status = Open3.capture3(command)
  crontab_output = stdout
  error_output = stderr

  no_crontab = !exit_status.success? && error_output =~ /no crontab/

  raise("Unable to read crontab: #{error_output}") if !exit_status.success? && !no_crontab

  crontab_output
end
remove(job_id, dry_run = false) click to toggle source

because we print the table out with 1-based job IDs, job_id is a 1-based index into @jobs

# File lib/schedule_job/cron.rb, line 108
def remove(job_id, dry_run = false)
  job_index = job_id - 1

  if job_index >= @jobs.size
    puts "The specified job ID does not exist."
    exit(1)
  end

  job = @jobs[job_index]

  if dry_run
    puts "Would remove: #{job}"
  else
    puts "Removing: #{job}"
    new_crontab = @raw_crontab.lines.reject.with_index{|line, line_index| line_index == job.line_number - 1 }.join
    write_crontab(new_crontab)
  end
end
to_s() click to toggle source
# File lib/schedule_job/cron.rb, line 143
def to_s
  s = StringIO.new
  if !@environment_vars.empty?
    s.puts "Environment"
    s.puts @environment_vars.join("\n")
  end
  if !@jobs.empty?
    s.puts "Jobs"
    @jobs.each_with_index do |job, i|
      s.puts "#{i + 1}. #{job}"
    end
  end
  s.string
end
write_crontab(new_crontab, user = @user) click to toggle source
# File lib/schedule_job/cron.rb, line 127
def write_crontab(new_crontab, user = @user)
  # overwrite crontab interactively, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
  command = ["crontab"]
  command << "-u #{user}" if user
  command << "-"
  command = command.join(" ")

  stdout, stderr, exit_status = Open3.capture3(command, stdin_data: new_crontab)
  crontab_output = stdout
  error_output = stderr

  load(user)

  raise("Unable to write to crontab: #{error_output}") unless exit_status.success?
end