Cron jobs, runner and methods. How to?


#1

I want to execute a method in a controller at scheduled intervals
throughout
the day. Can others provide examples of how they do this?

The excerpt below from the wiki page "
http://wiki.rubyonrails.org/rails/pages/HowToRunBackgroundJobsInRails/versions/1"
is basically what I want to do, but I can’t find enough other
information to
fill in the gaps:

Use cron or the like to run ruby code (a helper to your app).

You could have a cron job launch your “escalate_bugs” script.

For info regarding accessing your data from a ruby script see
HowToPopulateYourDbFromScripthttp://wiki.rubyonrails.org/rails/pages/HowToPopulateYourDbFromScriptand
how
to access your Rails environment from a
script.http://wiki.rubyonrails.org/rails/pages/HowToRunBackgroundJobsInRails/versions/Environments#script

You can have cron call script/runner to execute a one line command such
as:

          • /path/to/app/script/runner -e production
            “User.clean_up_expired()”
I have had difficulty finding documentation on how to use script/runner. I am also a newbie to cron jobs.

My goal is to run a method in controller/products called “updatePrices”
4
times a day using a cron job. Can someone provide sample code to do
that.

I will post any solution on the above wiki page.

Thanks very much,

Steve


#2

On Dec 11, 2005, at 8:40 AM, Steve O. wrote:

          • /path/to/app/script/runner -e production

Thanks very much,

Steve

Hey Steve-

Ok lets get this running for you. So 4 times a day is every 6 hours.

We will make your job run at 2 minutes after the hour every six
hours. This way we wont conflict with other scheduled hourly tasks.
So our cron entry will look like this:

02 6 * * * /path/to/app/script/runner -e production
“Product.update_prices”

I already know you are running debian so you will want to put this

line in /etc/cron/daily . But you don’t usually do this directly. On
debian you run this command:

crontab -e

Then paste in
02 4 * * * /path/to/app/script/runner -e production “Product.
update_prices”
then save and exit the editor

Change production to development if you need to. And you will want

to make the update_prices method in your Product Model instead of
your controller. Usually jobs like this will interact with your data
model and not need to use your controller. So you need to define a
class method in your Product model like this:

Product < AR::Base

def self. update_prices
# update prices and do whatever else is needed
end

end

Hopefully that should get you going.

Cheers-

-Ezra Z.
WebMaster
Yakima Herald-Republic Newspaper
removed_email_address@domain.invalid
509-577-7732


#3

Not knowing much about how your app is organized, i would suggest that
what
you describe would make more sense on the Product model. You could still
have a method on the Products controller that would delegate to that
method,
if you needed a way to fire it from your web interface. You could then
run


    ./script/runner 'Product.UpdatePrices()'

as a cron job.

If you need help setting up the cron job, please add some information
about
your server – what OS are you running, is it hosted, do you have shell
access?

Lee


#4

Ezra Z. wrote:

Ok lets get this running for you. So 4 times a day is every 6 hours. We
will make your job run at 2 minutes after the hour every six hours. This
way we wont conflict with other scheduled hourly tasks. So our cron
entry will look like this:

02 6 * * * /path/to/app/script/runner -e production
“Product.update_prices”|

This will run the job at 6:02. To run every 6 hours you need:

02 */6 * * * /path/to/app/script/runner -e production
“Product.update_prices”

or

02 0,6,12,18 * * * /path/to/app/script/runner -e production
“Product.update_prices”

either of which will run the job at 0:02, 6:02, 12:02, and 18:02. Both
should be on one line.

crontab -e

Then paste in
02 4 * * * /path/to/app/script/runner -e production
“Product.update_prices”

This runs once at 4:02. Change as above.

Ray


#5

On Dec 11, 2005, at 6:30 PM, Ray B. wrote:

Ray
Ahh my bad. Thanks Ray.

-Ezra Z.
WebMaster
Yakima Herald-Republic Newspaper
removed_email_address@domain.invalid
509-577-7732


#6

Thanks for all the help guys.

I cheated a bit and used my webmin cron job interface to set it up. I
did
use crontab -e to check it and it seems to be input correctly:
4 0,4,8,12,16,20 * * * /home/steve/myappname/script/runner -e
development "
Product.update_all"

crontab actually seems pretty easy to easy. Ezra is going to make me a
bash/command line guy yet ; )

If I test it and run it right now I get the following error:

/home/steve/myappname/script/runner: Permission denied

I tried running it as both root and my user name.

Any ideas?
Steve


#7

You likely have to chmod +x script/runner

Yes, that was my problem.

Now, one last problem. The suggestion was to move my method I wanted to
call
with a cron job to my model:

And you will want to make theupdate_prices method in your Product Model

instead of your controller. Usually jobs like this will interact with your
data model

However, in that method I need to do things like perform some
calculations,
determine whether I need to update the prices are not, and preprocess
and
call and Amazon library. Here is an example of
submethods that are being called:

def calculate_required_update(rank)
time = case rank
when 0…10000 then 1.hours.from_now
when 10001…200000 then 24.hours.from_now
else 96.hours.from_now
end
end

It doesn’t seem like these kinds of things belong in my model. I don’t
think
I can call controller or helper methods from my model (or at least I’m
getting errors when I do).

So my question is: Can I have the cron job call a method in my
controller?

Thanks,

Steve


#8

You likely have to chmod +x script/runner

-Nb

 Nathaniel S. H. Brown                           http://nshb.net

#9

Hi Harrison,

I went the wget route. Putting all that stuff in my model didn’t seem
right.

I’d be curious what you ultimately decide to do.

Steve
http://www.smarkets.net


#10

Any more insight to the best way to handle this?

wget with methods in the controller?

or

script/runner with methids in the model?

-stirman


#11

or rails_cron with methods in the model.

http://tinyurl.com/k994k


– Tom M.


#12

So my question is: Can I have the cron job call a method in my controller?
Thanks,Steve

Steve - don’t know if you resolved this yet, but I am/was in the same
position
as you were. I want to run some maintenance tasks on a daily basis.
These
tasks originally were controller actions. There seems to be two
approaches to
handling this at this:

  1. Run wget http://yoursite/yourcontroller/youraction via cron

  2. Convert your controller actions to model methods as described above,
    and use
    script/runner via cron (or kyle maxwell’s rails_cron) to run them.

I’m currently testing each approach to figure out which is best. The
wget
approach may be a little quick/dirty whereas using script/runner
probably is
more legit.

When I converted the maintenance actions to model methods, I also ran
into the
problem you did about not being able to access helper methods in the
model, so I
converted those to new model methods as well (using self.).
It’s
not that big of deal, but I wonder why you can’t use helper methods in
the model?

Now I’m wondering if it matters that I have 1000 new lines of code in my
model
that used to be in controllers and view templates, i.e. if it will
somehow be a
performance issue.

As for the more straightforward wget approach, I’ve heard that there may
be
timeout issues when running this for longer processes versus using
script/runner.

Any more comments would be appreciated.