0

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.

Sridhar Sarnobat
  • 1,802
  • 20
  • 27
  • 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 '21 at 22:24
  • ...unless you have multiple crontab entries running JVM programs ;) Hello microservices. – Sridhar Sarnobat Mar 23 '21 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 '21 at 05:03

2 Answers2

1

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

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

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.

fra-san
  • 10,205
  • 2
  • 22
  • 43
  • 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). – Sridhar Sarnobat Mar 23 '21 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 '21 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. – Sridhar Sarnobat Mar 23 '21 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. – Sridhar Sarnobat Mar 23 '21 at 22:45
  • Actually the ~/.profile approach seems to be the "real" solution (maybe that should be marked 3.). I just need to make sure I copy it each time I reinstall Ubuntu and not wonder why my restored cronjobs aren't working.. – Sridhar Sarnobat Mar 23 '21 at 22:49
  • 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 '21 at 22:56
  • Note that neither the Bourne shell nor the POSIX specification of sh support a -l option. A few modern implementations of POSIX sh do though. Not all will read .profile with that option though. – Stéphane Chazelas Mar 25 '21 at 14:54
0

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? – Sridhar Sarnobat Mar 23 '21 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. – Stéphane Chazelas Mar 25 '21 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. – Stéphane Chazelas Mar 25 '21 at 14:41
  • Oh I didn't realize that. Good to know. I should probably stop using Bourne shell for scripts too then – Sridhar Sarnobat Mar 25 '21 at 22:05