From 295cabe56ca75667c68d4dc6b6f27b84e0fd2ebf Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Tue, 20 Oct 2009 11:52:09 -0400 Subject: [PATCH] added new output redirection features, moved most of it into a new class. --- lib/job_list.rb | 9 +- lib/job_types/default.rb | 54 +---- lib/outputs/cron.rb | 14 +- lib/outputs/cron/output_redirection.rb | 54 +++++ lib/whenever.rb | 1 + test/output_command_test.rb | 270 ----------------------- test/output_redirection_test.rb | 289 +++++++++++++++++++++++++ 7 files changed, 366 insertions(+), 325 deletions(-) create mode 100644 lib/outputs/cron/output_redirection.rb create mode 100644 test/output_redirection_test.rb diff --git a/lib/job_list.rb b/lib/job_list.rb index b035ca0..f893340 100644 --- a/lib/job_list.rb +++ b/lib/job_list.rb @@ -38,9 +38,11 @@ module Whenever end def command(task, options = {}) - @output = :unset unless defined?(@output) - options[:output] ||= options.has_key?(:output) ? options[:output] : @output - options[:class] ||= Whenever::Job::Default + # :cron_log was an old option for output redirection, it remains for backwards compatibility + options[:output] = (options[:cron_log] || @cron_log) if defined?(@cron_log) || options.has_key?(:cron_log) + # :output is the newer, more flexible option. + options[:output] = @output if defined?(@output) && !options.has_key?(:output) + options[:class] ||= Whenever::Job::Default @jobs[@current_time_scope] ||= [] @jobs[@current_time_scope] << options[:class].new(@options.merge(:task => task).merge(options)) end @@ -141,7 +143,6 @@ module Whenever @jobs.each do |time, jobs| jobs.each do |job| Whenever::Output::Cron.output(time, job) do |cron| - cron << job.redirect_output cron << "\n\n" if cron.starts_with?("@") diff --git a/lib/job_types/default.rb b/lib/job_types/default.rb index 2ef44c8..7b7af8f 100644 --- a/lib/job_types/default.rb +++ b/lib/job_types/default.rb @@ -2,64 +2,22 @@ module Whenever module Job class Default - attr_accessor :task, :at, :redirect + attr_accessor :task, :at, :output, :output_redirection def initialize(options = {}) - @task = options[:task] - @at = options[:at] - @redirect = options[:output] - @environment = options[:environment] || :production - @path = options[:path] || Whenever.path + @task = options[:task] + @at = options[:at] + @output_redirection = options.has_key?(:output) ? options[:output] : :not_set + @environment = options[:environment] || :production + @path = options[:path] || Whenever.path end def output task end - def redirect_output - case @redirect - when String - redirect_from_string - when Hash - redirect_from_hash - when NilClass - " >> /dev/null 2>&1" - else - '' - end - end - protected - def stdout - return unless @redirect.has_key?(:standard) - @redirect[:standard].nil? ? '/dev/null' : @redirect[:standard] - end - - def stderr - return unless @redirect.has_key?(:error) - @redirect[:error].nil? ? '/dev/null' : @redirect[:error] - end - - def redirect_from_hash - case - when stdout == '/dev/null' && stderr == '/dev/null' - " >> /dev/null 2>&1" - when stdout && stderr - " >> #{stdout} 2> #{stderr}" - when stderr - " 2> #{stderr}" - when stdout - " >> #{stdout}" - else - '' - end - end - - def redirect_from_string - " >> #{@redirect} 2>&1" - end - def path_required raise ArgumentError, "No path available; set :path, '/your/path' in your schedule file" if @path.blank? end diff --git a/lib/outputs/cron.rb b/lib/outputs/cron.rb index 54b36ea..0217e7a 100644 --- a/lib/outputs/cron.rb +++ b/lib/outputs/cron.rb @@ -5,10 +5,11 @@ module Whenever attr_accessor :time, :task - def initialize(time = nil, task = nil, at = nil) + def initialize(time = nil, task = nil, at = nil, output_redirection = nil) @time = time @task = task @at = at.is_a?(String) ? (Chronic.parse(at) || 0) : (at || 0) + @output_redirection = output_redirection end def self.enumerate(item) @@ -24,11 +25,14 @@ module Whenever def self.output(times, job) enumerate(times).each do |time| enumerate(job.at).each do |at| - out = new(time, job.output, at) - yield "#{out.time_in_cron_syntax} #{out.task}" + yield new(time, job.output, at, job.output_redirection).output end end end + + def output + [time_in_cron_syntax, task, output_redirection].compact.join(' ').strip + end def time_in_cron_syntax case @time @@ -37,6 +41,10 @@ module Whenever else parse_time end end + + def output_redirection + OutputRedirection.new(@output_redirection).to_s unless @output_redirection == :not_set + end protected diff --git a/lib/outputs/cron/output_redirection.rb b/lib/outputs/cron/output_redirection.rb new file mode 100644 index 0000000..34dd2f8 --- /dev/null +++ b/lib/outputs/cron/output_redirection.rb @@ -0,0 +1,54 @@ +module Whenever + module Output + class Cron + class OutputRedirection + + def initialize(output) + @output = output + end + + def to_s + return '' unless defined?(@output) + case @output + when String then redirect_from_string + when Hash then redirect_from_hash + when NilClass then ">> /dev/null 2>&1" + else '' + end + end + + protected + + def stdout + return unless @output.has_key?(:standard) + @output[:standard].nil? ? '/dev/null' : @output[:standard] + end + + def stderr + return unless @output.has_key?(:error) + @output[:error].nil? ? '/dev/null' : @output[:error] + end + + def redirect_from_hash + case + when stdout == '/dev/null' && stderr == '/dev/null' + ">> /dev/null 2>&1" + when stdout && stderr + ">> #{stdout} 2> #{stderr}" + when stderr + "2> #{stderr}" + when stdout + ">> #{stdout}" + else + '' + end + end + + def redirect_from_string + ">> #{@output} 2>&1" + end + + end + end + end +end diff --git a/lib/whenever.rb b/lib/whenever.rb index 933fe22..748fabc 100644 --- a/lib/whenever.rb +++ b/lib/whenever.rb @@ -32,5 +32,6 @@ job_types/default job_types/rake_task job_types/runner outputs/cron +outputs/cron/output_redirection command_line }.each { |file| require File.expand_path(File.dirname(__FILE__) + "/#{file}") } \ No newline at end of file diff --git a/test/output_command_test.rb b/test/output_command_test.rb index e68ed87..fff6baf 100644 --- a/test/output_command_test.rb +++ b/test/output_command_test.rb @@ -33,275 +33,5 @@ class OutputCommandTest < Test::Unit::TestCase assert_match "0 * * * * second", @output end end - - context "A command when the output is set to nil" do - setup do - @output = Whenever.cron \ - <<-file - set :output, nil - every 2.hours do - command "blahblah" - end - file - end - should "output the command with the log syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2>&1$/, @output - end - end - - - context "A command when the output is set" do - setup do - @output = Whenever.cron \ - <<-file - set :output, 'logfile.log' - every 2.hours do - command "blahblah" - end - file - end - - should "output the command with the log syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> logfile.log 2>&1$/, @output - end - end - - context "A command when the error and standard output is set by the command" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:standard => 'dev_null', :error => 'dev_err'} - end - file - end - - should "output the command without the log syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output - end - end - - context "A command when the output is set and the comand overrides it" do - setup do - @output = Whenever.cron \ - <<-file - set :output, 'logfile.log' - every 2.hours do - command "blahblah", :output => 'otherlog.log' - end - file - end - - should "output the command with the command syntax appended" do - assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output - assert_match /^.+ .+ .+ .+ blahblah >> otherlog.log 2>&1$/, @output - end - end - - context "A command when the output is set and the comand overrides with standard and error" do - setup do - @output = Whenever.cron \ - <<-file - set :output, 'logfile.log' - every 2.hours do - command "blahblah", :output => {:error => 'dev_err', :standard => 'dev_null' } - end - file - end - - should "output the command with the overridden redirection syntax appended" do - assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output - assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output - end - end - - context "A command when the output is set and the comand rejects it" do - setup do - @output = Whenever.cron \ - <<-file - set :output, 'logfile.log' - every 2.hours do - command "blahblah", :output => false - end - file - end - - should "output the command without the log syntax appended" do - assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output - assert_match /^.+ .+ .+ .+ blahblah$/, @output - end - end - - context "A command when the output is set and is overridden by the :set option" do - setup do - @output = Whenever.cron :set => 'output=otherlog.log', :string => \ - <<-file - set :output, 'logfile.log' - every 2.hours do - command "blahblah" - end - file - end - - should "output the otherlog.log as the log file" do - assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output - assert_match /^.+ .+ .+ .+ blahblah >> otherlog.log 2>&1/, @output - end - end - - context "A command when the error and standard output is set" do - setup do - @output = Whenever.cron \ - <<-file - set :output, {:error => 'dev_err', :standard => 'dev_null' } - every 2.hours do - command "blahblah" - end - file - end - - should "output the command without the redirection syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output - end - end - - context "A command when error output is set" do - setup do - @output = Whenever.cron \ - <<-file - set :output, {:error => 'dev_null'} - every 2.hours do - command "blahblah" - end - file - end - - should "output the command without the standard errror syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah 2> dev_null$/, @output - end - end - - context "A command when the standard output is set" do - setup do - @output = Whenever.cron \ - <<-file - set :output, {:standard => 'dev_out'} - every 2.hours do - command "blahblah" - end - file - end - - should "output the command with standard output syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> dev_out$/, @output - end - end - - context "A command when error output is set by the command" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:error => 'dev_err'} - end - file - end - - should "output the command without the log syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah 2> dev_err$/, @output - end - end - - context "A command when standard output is set by the command" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:standard => 'dev_out'} - end - file - end - - should "output the command without the log syntax appended" do - assert_match /^.+ .+ .+ .+ blahblah >> dev_out$/, @output - end - end - - context "A command when standard output is set to nil" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:standard => nil} - end - file - end - - should "output the command with stdout directed to /dev/null" do - assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null$/, @output - end - end - - context "A command when standard error is set to nil" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:error => nil} - end - file - end - - should "output the command with stderr directed to /dev/null" do - assert_match /^.+ .+ .+ .+ blahblah 2> \/dev\/null$/, @output - end - end - - context "A command when standard output and standard error is set to nil" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:error => nil, :standard => nil} - end - file - end - - should "output the command with stderr directed to /dev/null" do - assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2>&1$/, @output - end - end - - context "A command when standard output is set and standard error is set to nil" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:error => nil, :standard => 'my.log'} - end - file - end - - should "output the command with stderr directed to /dev/null" do - assert_match /^.+ .+ .+ .+ blahblah >> my.log 2> \/dev\/null$/, @output - end - end - - context "A command when standard output is nil and standard error is set" do - setup do - @output = Whenever.cron \ - <<-file - every 2.hours do - command "blahblah", :output => {:error => 'my_error.log', :standard => nil} - end - file - end - - should "output the command with stderr directed to /dev/null" do - assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2> my_error.log$/, @output - end - end - - end \ No newline at end of file diff --git a/test/output_redirection_test.rb b/test/output_redirection_test.rb new file mode 100644 index 0000000..cb5d00f --- /dev/null +++ b/test/output_redirection_test.rb @@ -0,0 +1,289 @@ +require File.expand_path(File.dirname(__FILE__) + "/test_helper") + +class OutputRedirectionTest < Test::Unit::TestCase + + context "A command when the output is set to nil" do + setup do + @output = Whenever.cron \ + <<-file + set :output, nil + every 2.hours do + command "blahblah" + end + file + end + + should "output the command with the log syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2>&1$/, @output + end + end + + + context "A command when the output is set" do + setup do + @output = Whenever.cron \ + <<-file + set :output, 'logfile.log' + every 2.hours do + command "blahblah" + end + file + end + + should "output the command with the log syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> logfile.log 2>&1$/, @output + end + end + + context "A command when the error and standard output is set by the command" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:standard => 'dev_null', :error => 'dev_err'} + end + file + end + + should "output the command without the log syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output + end + end + + context "A command when the output is set and the comand overrides it" do + setup do + @output = Whenever.cron \ + <<-file + set :output, 'logfile.log' + every 2.hours do + command "blahblah", :output => 'otherlog.log' + end + file + end + + should "output the command with the command syntax appended" do + assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output + assert_match /^.+ .+ .+ .+ blahblah >> otherlog.log 2>&1$/, @output + end + end + + context "A command when the output is set and the comand overrides with standard and error" do + setup do + @output = Whenever.cron \ + <<-file + set :output, 'logfile.log' + every 2.hours do + command "blahblah", :output => {:error => 'dev_err', :standard => 'dev_null' } + end + file + end + + should "output the command with the overridden redirection syntax appended" do + assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output + assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output + end + end + + context "A command when the output is set and the comand rejects it" do + setup do + @output = Whenever.cron \ + <<-file + set :output, 'logfile.log' + every 2.hours do + command "blahblah", :output => false + end + file + end + + should "output the command without the log syntax appended" do + assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output + assert_match /^.+ .+ .+ .+ blahblah$/, @output + end + end + + context "A command when the output is set and is overridden by the :set option" do + setup do + @output = Whenever.cron :set => 'output=otherlog.log', :string => \ + <<-file + set :output, 'logfile.log' + every 2.hours do + command "blahblah" + end + file + end + + should "output the otherlog.log as the log file" do + assert_no_match /.+ .+ .+ .+ blahblah >> logfile.log 2>&1/, @output + assert_match /^.+ .+ .+ .+ blahblah >> otherlog.log 2>&1/, @output + end + end + + context "A command when the error and standard output is set" do + setup do + @output = Whenever.cron \ + <<-file + set :output, {:error => 'dev_err', :standard => 'dev_null' } + every 2.hours do + command "blahblah" + end + file + end + + should "output the command without the redirection syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> dev_null 2> dev_err$/, @output + end + end + + context "A command when error output is set" do + setup do + @output = Whenever.cron \ + <<-file + set :output, {:error => 'dev_null'} + every 2.hours do + command "blahblah" + end + file + end + + should "output the command without the standard errror syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah 2> dev_null$/, @output + end + end + + context "A command when the standard output is set" do + setup do + @output = Whenever.cron \ + <<-file + set :output, {:standard => 'dev_out'} + every 2.hours do + command "blahblah" + end + file + end + + should "output the command with standard output syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> dev_out$/, @output + end + end + + context "A command when error output is set by the command" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:error => 'dev_err'} + end + file + end + + should "output the command without the log syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah 2> dev_err$/, @output + end + end + + context "A command when standard output is set by the command" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:standard => 'dev_out'} + end + file + end + + should "output the command without the log syntax appended" do + assert_match /^.+ .+ .+ .+ blahblah >> dev_out$/, @output + end + end + + context "A command when standard output is set to nil" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:standard => nil} + end + file + end + + should "output the command with stdout directed to /dev/null" do + assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null$/, @output + end + end + + context "A command when standard error is set to nil" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:error => nil} + end + file + end + + should "output the command with stderr directed to /dev/null" do + assert_match /^.+ .+ .+ .+ blahblah 2> \/dev\/null$/, @output + end + end + + context "A command when standard output and standard error is set to nil" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:error => nil, :standard => nil} + end + file + end + + should "output the command with stderr directed to /dev/null" do + assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2>&1$/, @output + end + end + + context "A command when standard output is set and standard error is set to nil" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:error => nil, :standard => 'my.log'} + end + file + end + + should "output the command with stderr directed to /dev/null" do + assert_match /^.+ .+ .+ .+ blahblah >> my.log 2> \/dev\/null$/, @output + end + end + + context "A command when standard output is nil and standard error is set" do + setup do + @output = Whenever.cron \ + <<-file + every 2.hours do + command "blahblah", :output => {:error => 'my_error.log', :standard => nil} + end + file + end + + should "output the command with stderr directed to /dev/null" do + assert_match /^.+ .+ .+ .+ blahblah >> \/dev\/null 2> my_error.log$/, @output + end + end + + context "A command when the deprecated :cron_log is set" do + setup do + @output = Whenever.cron \ + <<-file + set :cron_log, "cron.log" + every 2.hours do + command "blahblah" + end + file + end + + should "output the command with with the stdout and stderr going to the log" do + assert_match /^.+ .+ .+ .+ blahblah >> cron.log 2>&1$/, @output + end + end +end \ No newline at end of file