Sample Header Ad - 728x90

Why does exec in bash script run by cron not preserve $PATH?

2 votes
1 answer
116 views
I have the following cron job setup on Debian 12: /etc/cron.d/jonathan-test:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

* * * * * jonathan /home/jonathan/test1.sh >> /home/jonathan/test.log 2>&1
/home/jonathan/test1.sh:
#!/usr/bin/env bash

export PATH="/home/jonathan/mytestdir:${PATH}"
echo "test1.sh -> PATH=${PATH}"
export PAAATH="this_is_a_test"
echo "test1.sh -> PAAATH=${PAAATH}"
exec "${HOME}/test2.sh"
/home/jonathan/test2.sh:
#!/usr/bin/env bash

echo "test2.sh -> PATH=${PATH}"
echo "test2.sh -> PAAATH=${PAAATH}"
When it runs, it writes the following to /home/jonathan/test.log:
test1.sh -> PATH=/home/jonathan/mytestdir:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
test1.sh -> PAAATH=this_is_a_test
test2.sh -> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
test2.sh -> PAAATH=this_is_a_test
As you can see, the $PATH variable is not preserved by exec. This is a contrived, simplified example of my actual problem, which is with running [pyenv](https://github.com/pyenv/pyenv) from a cron job. If I change my cron.d file to this:
SHELL=/bin/bash
PYENV_ROOT=/opt/pyenv
PATH=/opt/pyenv/shims:/opt/pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

* * * * * jonathan python --version >> /home/jonathan/test.log 2>&1
Then I get this written to the output file:
/opt/pyenv/libexec/pyenv-exec: line 24: pyenv-version-name: command not found
It correctly executes /opt/pyenv/shims/python. That's just a bash script that runs pyenv exec python --version. It correctly executes /opt/pyenv/bin/pyenv, which is a symlink to /opt/pyenv/libexec/pyenv, which is a bash script that modifies $PATH to include /opt/pyenv/libexec (and yes, it does export it!) and executes /opt/pyenv/libexec/pyenv-exec, which is another bash script that tries to do PYENV_VERSION="$(pyenv-version-name)" on line 24 which results in the error above, because /opt/pyenv/libexec isn't in $PATH. I've narrowed it down to the simplified example above. The exact same pyenv setup with only environment variables and without the shell integration works just fine when not run from cron. FYI, there's no sudo anywhere in this, and I can reproduce it as other users too. So it doesn't seem to be related to secure_path in /etc/sudoers.
Asked by jnrbsn (189 rep)
Nov 25, 2024, 01:26 AM
Last activity: Nov 27, 2024, 03:30 PM