Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I run a cron command with existing environmental variables?

If I am at a shell prompt I can type echo $ORACLE_HOME and get a path. This is one of my environmental variables that gets set in my ~/.profile. However, it seems that ~/.profile does not get loaded fron cron scripts and so my scripts fail because the $ORACLE_HOME variable is not set.

In this question the author mentions creating a ~/.cronfile profile which sets up variables for cron, and then he does a workaround to load all his cron commands into scripts he keeps in his ~/Cron directory. A file like ~/.cronfile sounds like a good idea, but the rest of the answer seems a little cumbersome and I was hoping someone could tell me an easier way to get the same result.

I suppose at the start of my scripts I could add something like source ~/.profile but that seems like it could be redundant.

So how can I get make my cron scripts load the variables from my interactive-shell profile?

share|improve this question
    
How is adding source ~/.profile to a program redundant? Programs inherit their environment from the calling program. If that calling program is not your shell, then how will the decendant program get the environment that you want? –  Arcege Dec 21 '11 at 5:08

8 Answers 8

up vote 24 down vote accepted

In the crontab, before you command, add . $HOME/.profile. For example:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

Cron knows nothing about your shell; it is started by the system, so it has a minimal environment. If you want anything, you need to have that brought in yourself.

share|improve this answer
2  
What does the . before the script do? (not sure how I would man that). Why is this different from source? –  cwd Dec 21 '11 at 19:26
1  
The . command is the original command for source. They are equivalent within the shell and a bit easier to type, especially within a crontab. To get more info, type help . or search for ^SHELL BUILTIN COMMANDS in the man page for bash or at the top of man zshbuiltins. Running type .` will tell you that the command is a builtin. –  Arcege Dec 21 '11 at 19:38
4  
Depending on Linux distributions, you may need to change .profile by .bash_profile. Check which .profile file exists in the user's home directory. –  Frosty Z May 17 '13 at 12:37

Bad idea. The general practice is to specifically set all required environmental variables in a script that is to be run from a cron job.

share|improve this answer
    
I agree with @fpmurphy, that ways it also ensure the secured process environment. If you want to set only few variables from cron you can use /usr/bin/env command to set the variables and then can act as the environment process for the cronjob. –  Nikhil Mulley Dec 21 '11 at 6:24
    
daemontools' envdir comes to mind, too. –  sr_ Dec 21 '11 at 9:42
3  
I am all for security, but perhaps I can create a file ~/.cronvars and include that in the profile and also in my cron scripts. I don't want to hard code environmental variables in each of the scripts I run because when paths change hard coded paths in each file are not easy to maintain. Seems like that would allow a centralized place for the needed variables and still keep other variables from being loaded. –  cwd Dec 21 '11 at 23:21

This syntax definitely helps you. I do not understand the syntax, but it works. Oracle uses this syntax, when deploys Oracle Configuration Manager to crontab, hence, I believe that this is a right solution.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters
share|improve this answer

Another option, which I find easier, is to run the script with cron and have the environment in the script.

In crontab -e file:

SHELL=/bin/bash

*/1 * * * * $HOME/cron_job.sh

In cron_job.sh file:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

Any command after the source of .bash_profile will have your environment as if you logged in.

share|improve this answer

Another option, which I find easier, is to run the script with cron and tell bash to login (hence using /etc/profile.d/... environment definitions)

In crontab -e file:

*/1 * * * * bash -l -c './cron_job.sh'
*/1 * * * * bash -l -c 'php -f ./cron_job.php'

Any command after the source of .bash_profile will have your environment as if you logged in.

share|improve this answer

The solution, which worked for me, is described here.

You create a wrapper script, which calls . ~/.cronfile, and then does the things you want. This script is launched by cron.

In ~/.cronfile you specify the environment for your cron jobs.

share|improve this answer

I put . ~/.dbus/session-bus/* at the top of my desired script :)

share|improve this answer
1  
Welcome to U & L SE. Please expand your answer more so that it will benefit the readers. –  Ramesh Sep 20 at 15:25

Yes, you can using "well known workarounds" (a couple of which have been listed). This is another way of saying that everyone knows it's crappy, though some people will refer to this as a "security feature" because they have spent at least as much tripping over this fail(ure) as you have, and would like to think their wasted time wasn't for naught. It's the cron equivalent of the QWERTY keyboard.

I suspect the original reason may have been for performance, such that scripts run once a minute wouldn't spend the time to read rc scripts. Also originally cron wasn't really configurable at all, so a default was really the only option.

There is no added security by not having some simple configuration or method to have cron just take on the environment of your interactive shell instead of users having to perform stupid shell gymnastics. On a modern machine there is generally no perceptible performance gain unless you have a vast quantity of jobs running every minute.

Unix culture fail. In my "humble" opinion. :-)

share|improve this answer
    
"There is no added security." That is not true. Take a look at CVE-2011-1095, CVE-2008-4304, and CVE-2010-3847. –  paraxor Jul 26 '13 at 2:20
    
I downvoted your answer, by the way. I usually try to avoid downvoting newcomers' answers but security is important to me. Please don't take the downvote the wrong way. Besides the part about security, your answer is excellent and would deserve an upvote. You can edit your answer here if you would like. –  paraxor Jul 26 '13 at 2:33
    
None of those have the slightest thing to do with having cron use a shell with the interactive flag set. This is pure FUD. Unfortunately I can't downvote your downvote. This may seem like a flame, but it's very frustrating when people think a vehicle with three wheels is better because there's a security issue to put a fourth wheel on. It isn't. People have just ridden a tricycle so long they've forgotten it's possible to add a fourth wheel. –  Austin S. Jul 26 '13 at 16:43
    
Put another way: if any of the intended extra hoops the other answerers suggested are used, how do they not also gain access to any of the holes you mention? "* * * * * exec bash -i -c LOCALE=......." –  Austin S. Jul 26 '13 at 16:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.