I set JAVA_HOME in .zshrc:

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/

which is fine for interactive programs. But I have JVM programs running via cron, which uses Bourne shell. The bourne shell programs keep giving me this:

groovy: JAVA_HOME is not defined correctly, can not execute: /usr/lib/jvm/default-java/bin/java

What's the neatest way to solve this? I don't remember having to worry about this before. Currently I'm setting JAVA_HOME on every crontab entry which is burdensome and redundant.

  • You know you can set environment variables in the crontab on lines saying just VARIABLE=value, right? You don't have to set the variable for each and every crontab entry.
    – Kusalananda
    Mar 23, 2021 at 22:24
  • ...unless you have multiple crontab entries running JVM programs ;) Hello microservices. Mar 23, 2021 at 22:57
  • What do you mean by "crontab entry"? Do you mean separate crotabs, or separate schedules in a single crontab? You only need to set JAVA_HOME once in a crontab file.
    – Kusalananda
    Mar 24, 2021 at 5:03

2 Answers 2


Assuming you are referring to your own user's crontab, to avoid duplicating the definition of JAVA_HOME you can export the variable in ~/.zshenv (instead of ~/.zshrc), which is read even in non-interactive, non-login shells, and run zsh -c 'sh /path/to/script' in your cron job (replacing sh, based on what the program called "Bourne shell" in your question actually is, if appropriate).

Alternatively, if you are fine with defining JAVA_HOME in multiple places and if your sh implementation supports this1, you may export it in ~/.profile and invoke sh as a login shell by either appending -l to the script's shebang or changing the cron job's command into sh -l /path/to/script.

Though, in the end, the most convenient solution is probably to simply add


as a line at the top of your crontab (unless you have distinct cron jobs that need distinct values of JAVA_HOME, of course).

1 Your sh, which is unlikely to be a "true" Bourne shell, may have a -l option if it is actually a link to (for instance) bash or dash. As Stéphane Chazelas pointed out in a comment, 1) it does not have it if it is the Bourne shell or an implementation of POSIX sh (e.g., sh has no -l option on {Free,Net,Open}BSD); and 2) not all the implementations that support -l will read ~/.profile when given that option.

  • Hmmm, if I have to make a modification like this to crontab, I might as well just create a file called ~/.zshrc-java since I have a lot of dotfiles, organized by functionality (~/.zshrc-git, ~/.zshrc-p4, ~/.zshrc-work, ~/.zshrc-home). Mar 23, 2021 at 22:01
  • 1
    ... or add JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/ at the top of your crontab, instead of setting it for each job. The point of this answer is to avoid duplicating the definition of a variable (since you asked about "sharing") and, given that there is no profile/initialization file that both sh and zsh read by default, a clean way to do that is by letting zsh define the environment for the cron job.
    – fra-san
    Mar 23, 2021 at 22:10
  • I didn't realize you could do that. That's the simplest solution, though I need to use that sparingly. Self-contained single lines are easier to debug. Mar 23, 2021 at 22:44
  • I'll mark this answer correct though I'll just add an extra line to your answer. Hope you don't mind. Mar 23, 2021 at 22:45
  • 1
    I removed the numbered list to make clear that the three paragraphs correspond to three distinct solutions. I'd guess the "best" approach is ultimately a matter of taste.
    – fra-san
    Mar 23, 2021 at 22:56

You can set that in both systemwide configfiles respectively /etc/bash.bashrc (/etc/bashrc on non-Debian systems) and /etc/zsh/zshenv (/etc/zshenv

As the syntax is the same, you can just copy-paste

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/

that in both files

  • Will Bourne Shell (/bin/sh) read ~/.bashrc? Mar 23, 2021 at 21:59
  • export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/ is not valid syntax in the Bourne shell, but I doubt @SridharSarnobat's sh is a Bourne shell. I don't think any currently maintained OS still use that shell now that Solaris 10 is end-of-life. Mar 25, 2021 at 14:38
  • In any case, bashrc is for the bash shell, not sh (Bourne or not), and only read by bash for interactive shells (and in some builds of bash and under some conditions when invoked over ssh/rsh), and not when running as sh. Mar 25, 2021 at 14:41
  • Oh I didn't realize that. Good to know. I should probably stop using Bourne shell for scripts too then Mar 25, 2021 at 22:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .