我在 Debian 12 上设置了以下 cron 作业:
/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}"
当它运行时,它会将以下内容写入/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
如您所见,$PATH
变量未被保留exec
。
这是我实际问题的一个简化示例,即从 cron 作业运行pyenvcron.d
。如果我将文件更改为以下内容:
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
然后我将其写入输出文件:
/opt/pyenv/libexec/pyenv-exec: line 24: pyenv-version-name: command not found
它正确执行了/opt/pyenv/shims/python
。那只是一个运行的 bash 脚本pyenv exec python --version
。它正确执行了/opt/pyenv/bin/pyenv
,这是一个指向的符号链接/opt/pyenv/libexec/pyenv
,这是一个修改$PATH
为包含的bash 脚本/opt/pyenv/libexec
(是的,它确实导出了它!)并执行了/opt/pyenv/libexec/pyenv-exec
,这是另一个 bash 脚本,它试图PYENV_VERSION="$(pyenv-version-name)"
在第 24 行执行,这导致了上面的错误,因为/opt/pyenv/libexec
不在$PATH
。我把它缩小到上面的简化示例。当不从 cron 运行时,仅使用环境变量且没有 shell 集成的完全相同的pyenv
设置也可以正常工作。
仅供参考,这里没有sudo
任何地方,我也可以像其他用户一样重现它。所以它似乎与secure_path
无关/etc/sudoers
。