Quote:
Originally Posted by Dain_Bramage
I have two cron jobs in my (not root) crontab.
Code:
0 2 * * * /home/mike/Scripts/rsync.sh
0 19 * * * /home/mike/Scripts/zfs.sh 2>&1 /tmp/testlog.log
The first one works, the second one does not.
If I run
Code:
/home/mike/Scripts/zfs.sh
in terminal it works. How can this be? Both scripts are owned by me.
|
Permissions are not the problem.
If you wanted to send the output of zfs.sh into that log file in /tmp, I'd use the crontab entry:
Code:
0 19 * * * /home/mike/Scripts/zfs.sh >/tmp/testlog.log 2>&1
Note the ">". Without the redirection how would the output make it into that file? I suspect that cron is just silently skipping the job as it doesn't understand the command. If the log file name was an argument ($1) to the script, I cannot predict what it would do if it saw "2>&1" in that location on the command line.
Another reason scripts will work on the command line but not when run under cron is your environment. Scripts run via cron do not run your .bashrc, .profile, or whatever other files you're sourcing to configure your interactive environment. A lot of the time cron jobs fail because of the PATH not being correct. Again, whatever you do in your account's profile setup is not being done when running under cron so if you have amended your PATH to include locations not in the system-wide default PATH and your script needs to know about those, your script will fail. NOTE: I can't recall
not getting an email with a "file not found"-type error message in those cases. You can define/recreate your interactive PATH with a "PATH=" line near the top of your crontab; no need to 'export' it.
I dealt with this years ago by writing my .profile to have a section for things I wanted set up when working interactively, a section for non-interactive sessions, and a session for either. (I hesitate to even mention this, though, as it generated a mini flame war on another forum many, many moons ago when I mentioned it in response to someone's cron problems.) Anyhoo, the key was defining:
Code:
INTERACTIVE=$( false )
if [ -t 0 ]; then # Is stdin connected to a terminal/keyboard?
INTERACTIVE=$( true )
fi
For example, I wouldn't need my aliases to be defined unless I'm at a real terminal ( if $INTERACTIVE then source aliases and do other niceties like colored prompt, etc. ). Then I'd source my .profile in cron scripts to do all of the environment configuration---if I set up my .profile correctly, I had the same necessities in either console or cron. (A major driver for this at the time was my desire to have standardized message formats emitted from my scripts and I enforced that by using a set of shell messaging functions that I sourced in .profile; when issued non-interactively, the functions ensured that the messages were time stamped. I should note that I don't do this so much any more though I still do source the messaging functions directly.)
HTH.
Cheers...