diff --git a/README.rdoc b/README.rdoc index a4bf885..ce1588c 100644 --- a/README.rdoc +++ b/README.rdoc @@ -66,7 +66,46 @@ This will create an initial "config/schedule.rb" file you. end More examples on the wiki: http://wiki.github.com/javan/whenever/instructions-and-examples + +== Output redirection + +In your schedule.rb file you can specify the redirection options for your commands at a global or command level by setting the 'output' variable. + + # adds ">> /path/to/file.log 2>&1" to all commands + set :output => '/path/to/file.log' + +Or you can STDOUT and STDERR separately, + + # adds ">> cron.log 2> error.log" to all commands + set :output => {:error => 'error.log', :standard => 'cron.log'} + # adds ">> cron.log" to all commands + set :output => {:standard => 'cron.log'} + + # adds "2> error.log" to all commands + set :output => {:error => 'error.log'} + +Additionally you can set these values at the command level, + + every 3.hours do + runner "MyModel.some_process", :output => 'cron.log' + rake "my:rake:task", :output => {:error => 'error.log', :standard => 'cron.log'} + command "/usr/bin/cmd" + end + +In all cases you can if you explicitly set the value of any output to 'nil' it will add a redirect to /dev/null + + # adds ">> /dev/null 2>&1" to all commands + set :output => nil + set :output => {:error => nil, :standard => nil} + + # adds ">> /dev/null" to all commands + set :output => {:standard => nil} + + # adds "2> /dev/null" to all commands + set :output => {:error => nil} + + == Cron output $ cd /my/rails/app diff --git a/bin/wheneverize b/bin/wheneverize index c92d7f9..fcab238 100644 --- a/bin/wheneverize +++ b/bin/wheneverize @@ -36,7 +36,9 @@ content = <<-FILE # Example: # -# set :cron_log, "/path/to/my/cron_log.log" +# set :output, "/path/to/my/cron_log.log" +# set :output, {:error => '/path/to/error.log', :standard => '/path/to/cron.log'} +# set :output, {:error => '/path/to/error.log', :standard => nil} # # every 2.hours do # command "/usr/bin/some_great_command" diff --git a/lib/job_list.rb b/lib/job_list.rb index 2130b33..b035ca0 100644 --- a/lib/job_list.rb +++ b/lib/job_list.rb @@ -38,7 +38,8 @@ module Whenever end def command(task, options = {}) - options[:cron_log] ||= @cron_log unless options[:cron_log] === false + @output = :unset unless defined?(@output) + options[:output] ||= options.has_key?(:output) ? options[:output] : @output options[:class] ||= Whenever::Job::Default @jobs[@current_time_scope] ||= [] @jobs[@current_time_scope] << options[:class].new(@options.merge(:task => task).merge(options)) @@ -140,7 +141,7 @@ module Whenever @jobs.each do |time, jobs| jobs.each do |job| Whenever::Output::Cron.output(time, job) do |cron| - cron << " >> #{job.cron_log} 2>&1" if job.cron_log + 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 d857923..2ef44c8 100644 --- a/lib/job_types/default.rb +++ b/lib/job_types/default.rb @@ -2,12 +2,12 @@ module Whenever module Job class Default - attr_accessor :task, :at, :cron_log + attr_accessor :task, :at, :redirect def initialize(options = {}) @task = options[:task] @at = options[:at] - @cron_log = options[:cron_log] + @redirect = options[:output] @environment = options[:environment] || :production @path = options[:path] || Whenever.path end @@ -16,8 +16,50 @@ module Whenever 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/test/output_command_test.rb b/test/output_command_test.rb index a971681..e68ed87 100644 --- a/test/output_command_test.rb +++ b/test/output_command_test.rb @@ -17,73 +17,6 @@ class OutputCommandTest < Test::Unit::TestCase end end - context "A command when the cron_log is set" do - setup do - @output = Whenever.cron \ - <<-file - set :cron_log, '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 cron_log is set and the comand overrides it" do - setup do - @output = Whenever.cron \ - <<-file - set :cron_log, 'logfile.log' - every 2.hours do - command "blahblah", :cron_log => 'otherlog.log' - end - file - end - - should "output the command with the log 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 cron_log is set and the comand rejects it" do - setup do - @output = Whenever.cron \ - <<-file - set :cron_log, 'logfile.log' - every 2.hours do - command "blahblah", :cron_log => 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 cron_log is set and is overridden by the :set option" do - setup do - @output = Whenever.cron :set => 'cron_log=otherlog.log', :string => \ - <<-file - set :cron_log, '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 "An every statement with two commands in it" do setup do @output = Whenever.cron \ @@ -100,5 +33,275 @@ 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