Cornelius Roemer
Cornelius Roemer

Reputation: 8286

Expanding variables in crontab PATH doesn't work

I've got the following 3 lines at the top of my crontab (created with crontab -e) on a system where I'm not a superuser:

SHELL=/usr/bin/bash
HOME=/mycluster/home/mygroup/myuser
PATH=$HOME/miniconda3/envs/py310simple/bin:$HOME/miniconda3/envs/py310simple/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/

I've actually got many items starting with $HOME on my path, this is shortened for readability.

Now, within a cronjob, it seems that the $HOME variable is not expanded, causing things inside $HOME/miniconda3/envs/py310simple/bin to not actually be on the path.

Why is that? And how can I work around this? I don't want to have to manually expand (and maintain) HOME for each directory I want to put on my path.

Upvotes: 0

Views: 50

Answers (2)

xpusostomos
xpusostomos

Reputation: 1647

The crontab file is not a shell script, it is a crontab file.

The ability to set environement variables in a crontab file is a bit of a hack in so far as it looks a bit like shell syntax, but isn't really shell, thus $HOME isn't expanded, nor are other shell substitutions.

Only the part after the time specification is passed to the shell.

So your options are....

  1. expand HOME yourself in the crontab
PATH=/home/miniconda3/envs/py310simple/bin:/home/miniconda3/envs/py310simple/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/

0 10 * * *  my-command with my-args here
  1. put the shell variable on the execution line:
0 10 * * * PATH=$HOME/miniconda3/envs/py310simple/bin:$HOME/miniconda3/envs/py310simple/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ my-command with my-args here
  1. Make a launching script separately
#!/bin/sh 
#my-launch-script
export PATH=$HOME/miniconda3/envs/py310simple/bin:$HOME/miniconda3/envs/py310simple/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ 
exec my-command with my-args here
0 10 * * * my-launch-script
  1. Put the variables in a separate source file:
#my-source-script:
export PATH=$HOME/miniconda3/envs/py310simple/bin:$HOME/miniconda3/envs/py310simple/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ 
0 10 * * * source my-source-script ; my-command with my-args here

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 204446

A crontab is a list of instructions for cron, it's not a shell script (a list of instructions for bash or other shell), so I was actually surprised to read at Why would one include ". ./.profile" in a crontab entry in Unix? that you can set environment variables in a crontab at all.

With that caveat in mind, in my experience to set a bunch of shell variables and then call some command bar from cron I'd either:

  1. Create a shell script named foo that sets those variables then calls bar and then call foo instead of bar from cron, or
  2. Use bash -c 'SHELL=...; HOME=...; PATH=...; bar' directly in the crontab so I'm calling bash from cron, setting the shell variables in that bash shell, then calling bar from that same shell.

Upvotes: 2

Related Questions