Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have written various scripts to launch Java server applications, which are typically run for 24 hours before being shut down (by invoking the same script with a different parameter).

The script relies on environment variables defined in a file: ~/<user>.env, which I source from .bashrc.

This works fine when invoking the script from the command line but if I want to add the script as a crontab entry I run into the problem where .bashrc isn't read.

My question: What is the best practice approach for solving this problem? I realise I could define a crontab entry such as:

* * * * 1-5 /usr/bin/bash -c '. /home/myuser/myuser.env && /home/myuser/scripts/myscript.sh'

... but this seems plain ugly. Alternatively I could source myuser.env at the beginning of every script, but this would become a nightmare to maintain.

Any help appreciated.

share|improve this question
    
Those are the two options I would suggest. –  einstiien Feb 19 '10 at 17:35

6 Answers 6

The only other thing I can think of would be based on:

bash -i --rcfile 'init' -c 'script'

which is probably less attractive.

share|improve this answer
    
I actually tried this and it doesn't work. According to the GNU bash manual, --rcfile "Execute commands from filename (instead of ~/.bashrc) in an interactive shell.", and as I'm not running an interactive shell I presume this is why it's failing. –  Adamski Feb 25 '10 at 10:56
    
@Adamski: The -i makes the shell think it's interactive. –  Dennis Williamson Feb 25 '10 at 13:38

An alternative (although not necessarily better) option would be to add these into root's crontab, and have the entry use su with a dash to become the user in question. The environment variables would then be pulled in automatically via the user's default shell environment in ~/.bashrc, or the like. eg:

* * * * 1-5 su - scriptuser '/home/myuser/scripts/myscript.sh' This would run the job as scriptuser, with all the environment variables of a proper login. The downside is that scriptuser himself couldn't set this job up -- it would require root privileges to do that.

share|improve this answer

I usually address this with a short cron wrapper script:

#!/bin/bash
[ -r $HOME/.bashrc ] && . $HOME/.bashrc
[ -r $HOME/.profile ] && . $HOME/.profile
exec "$@"

Then just prefix the command in crontab with your wrapper:

* * * * 1-5 ~/scripts/cron-wrapper ~/scripts/myscript.sh
* * * * 1-5 ~/scripts/cron-wrapper ~/scripts/myotherscript.sh

Some versions of cron allow you to set variables directly in crontab. Unfortunately, I don't get to use those at work.

share|improve this answer
up vote 5 down vote accepted

I actually discovered a fairly elegant solution by adding the '-l' (--login) flag to my bash command, which causes it to source all login files, including .bashrc. Hence my crontab command is simply:

* * * * 1-5 /usr/bin/bash -lc '/mnt/group/core/deploy/scripts/test.sh' > /dev/null 2>&1
share|improve this answer

cron-wrapper solution worked for me with one modification, I needed to replace the $HOME with the absolute path to the user home folder, in this case it was:

#!/bin/bash
[ -r /root/.bashrc ] && . /root/.bashrc
[ -r /root/.profile ] && . /root/.profile
exec "$@"
share|improve this answer

Recent versions of cron allow you to set arbitrary environment variables before running jobs. So you could add this to your crontab:

CRON=1

Then in your .bash_login do something like this:

[ -n "$CRON" ] && . .bashrc

share|improve this answer

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.