Discussion:
Working with Cron under Solaris 10
Forrest Aldrich
2011-01-14 22:32:44 UTC
Permalink
I ran into an unfortunate problem with cron recently, where I had "assumed" that a HUP signal would cause it to re-read a new crontab entry. The result was a script was run that deleted some data.

Turns out, the code shows SIGHUP, SIG_IGN. I was not happy.

In any case, I want to understand the best way to manage this service. The manpage doesn't really specify what it responds to. So here we go...

The simplest way I can find is:

# /etc/init.d/cron stop (then start)

But this is Solaris, so we might use:

svcadm restart -t system/cron:default

but it's not clear whether "restart" or "refresh" will do the trick. "refresh" seems to be used to re-read the *service* configuration (xml), but does that cause it to re-read the crontabs?

Running crontab -e is not applicable to what I'm doing here. I experimented with it and it turns out you can't use that functionality in a scripted environment, it doesn't work. I have a script that edits a line of a crontab, either commented out or not. Then it needs to tell cron to re-read the tabs.

Pointers appreciated. Thanks.
--
This message posted from opensolaris.org
Mike Gerdts
2011-01-15 01:14:47 UTC
Permalink
Running crontab -e is not applicable to what I'm doing here.  I experimented with it and it turns out you can't use that functionality in a scripted environment, it doesn't work.    I have a script that edits a line of a crontab, either commented out or not.  Then it needs to tell cron to re-read the tabs.
How about:

tmpfile=`mktemp`
crontab -l > $tmpfile
... # munge the file here or in a pipeline with the previous command
crontab $tmpfile
rm -f $tmpfile

Before I knew about that approach, I also did things like setting
EDITOR (be sure VISUAL is unset) to the name of a script that knows
how to munge it. That is, something like the following:

env -i PATH=$PATH EDITOR=/my/script crontab -e

And if you already edited it in place (I advise against it...)

env -i PATH=$PATH EDITOR=touch crontab -e
--
Mike Gerdts
http://mgerdts.blogspot.com/
Edward Ned Harvey
2011-01-15 14:14:15 UTC
Permalink
Post by Forrest Aldrich
I ran into an unfortunate problem with cron recently, where I had
"assumed"
Post by Forrest Aldrich
that a HUP signal would cause it to re-read a new crontab entry. The
result
Post by Forrest Aldrich
was a script was run that deleted some data.
When you modify a crontab entry, there is no need to HUP anything. You just
wait for the next minute that the script is supposed to run (under some
circumstances you have to wait for the 2nd minute) and that's it.
Post by Forrest Aldrich
# /etc/init.d/cron stop (then start)
svcadm restart -t system/cron:default
Why would you want to do that?
Post by Forrest Aldrich
Running crontab -e is not applicable to what I'm doing here. I
experimented
Post by Forrest Aldrich
with it and it turns out you can't use that functionality in a scripted
environment, it doesn't work. I have a script that edits a line of a
crontab,
Post by Forrest Aldrich
either commented out or not. Then it needs to tell cron to re-read the
tabs.

Sure you can script that. In fact, I do. You just set your EDITOR to
something you control... EDITOR will be launched with the name of the temp
file as an argument, so it can edit that file and save it and exit. And
then crontab will save that file as the crontab entry (assuming it passes
syntax.)
Ron Halstead
2011-01-16 21:13:20 UTC
Permalink
Cron only reads the crontab file when it starts. Man cron and search for 'examines'. As you found out, sending a HUP doesn't work. Since cron runs as a SMF controlled service in Solaris 10, killing the process will cause SMF to restart it. The crontab file will then be read and changes, if any, will be implemented. I used the following to test it:

pgrep -fl cron
508 /usr/sbin/cron

sudo kill 508 # or sudo pkill cron

pgrep -fl cron
1368 /usr/sbin/cron # new process ID 1368 means it was restarted.

I hope this helps.

--ron
--
This message posted from opensolaris.org
Chris Ridd
2011-01-16 21:46:35 UTC
Permalink
Post by Ron Halstead
Cron only reads the crontab file when it starts. Man cron and search for 'examines'.
*And* when the crontab/at commands are run.

---
cron only examines crontab or at command files during its
own process initialization phase and when the crontab or at
command is run. This reduces the overhead of checking for
new or changed files at regularly scheduled intervals.
---

Cheers,

Chris
Ron Halstead
2011-01-16 22:10:43 UTC
Permalink
<*And* when the crontab/at commands are run.>

Which restarts cron unless there were no changes made, it which case crontab is not read

--ron.
--
This message posted from opensolaris.org
Brandon Hume
2011-01-18 19:33:53 UTC
Permalink
Post by Ron Halstead
Post by Chris Ridd
*And* when the crontab/at commands are run.
Which restarts cron unless there were no changes
made, it which case crontab is not read
No, crontab signals cron through /etc/cron.d/FIFO, which then re-reads the crontab. cron is not restarted. This is easily verifiable through truss, and the code is visible on src.opensolaris.org.

Are you sure you're talking about Solaris 10 cron?
--
This message posted from opensolaris.org
Brian Ruthven - Solaris Network Sustaining - Oracle UK
2011-01-20 15:12:58 UTC
Permalink
Post by Ron Halstead
pgrep -fl cron
508 /usr/sbin/cron
sudo kill 508 # or sudo pkill cron
As a general rule for SMF-controlled processes, the first command only
works if the service is configured to ignore signals (which cron is).
Specifically, kill will succeed in sending the signal, but this may put
the service into maintenance mode if the "startd/ignore_error" property
does not specify "signal".

The second command is dangerous in the presence of zones when run from
the global zone, as it will send the -TERM signal to all crons in all
zones. Probably not what you wanted.

Actually, the first command can also be dangerous in the presence of
zones. How do you know which zone each cron is running in? ps -Z will
tell you, but it's an additional step, and more to get wrong.

The correct (and quite easy) way to restart a service in the current
zone only is:
svcadm restart svc:/system/cron:default
(or "svcadm restart cron" will suffice)

This will also take care of running the stop method to clean up any
state, etc. However, as others have noted, there is no need for this on
Solaris as long as you use the crontab(1M) interface and are not
hand-editing the underlying /var/spool/cron/crontabs/* files directly
(which I would recommend against as it bypasses the initial
syntax/format checking that crontab(1m) performs).

Personally, I maintain a separate file with my crontab entries. Then I
can edit it and "upload" the new version to cron using "crontab
crontabfile". This then also helps protect me from the somewhat
irritating "crontab -r" instead of "crontab -e". Oh how many times I've
removed my crontab instead of editing it by slipping off the 'e' key and
hitting return before my brain caught up.


Regards,
Brian
--
Brian Ruthven
Solaris Network RPE (Sustaining)
Oracle UK
Continue reading on narkive:
Loading...