我想让一个cron作业使用已经存在的名为my_env的anaconda python环境执行python脚本。 我唯一能想到做的就是让 cron 作业运行一个名为 my_script.bash
的脚本,该脚本反过来激活 env,然后运行 python 脚本。
#!/bin/bash
source activate my_env
python ~/my_project/main.py
尝试从命令行执行此脚本不起作用:
$ sh scripts/my_script.bash
scripts/my_script.bash: 9: scripts/my_script.bash: source: not found
我需要做什么来确保激活正确的环境。可以像我 5 岁一样向我解释。
我最近从 canopy 切换到 Anaconda 正是为了摆脱在 cron 作业中激活 env 的麻烦。Anaconda基于PATH环境变量使这变得非常简单。(我使用的是miniconda而不是完整的Anaconds安装,但我相信anaconda应该以同样的方式工作(
我测试过两种不同的方法;
-
在python脚本中添加一个shebang,main.py
#!/home/users/user_name/miniconda2/envs/my_env/bin/python
-
将 PATH 添加到 crontab 的顶部
PATH=/home/users/user_name/miniconda2/envs/my_env/bin
更新:
杰罗姆的回答和巴里克的评论是正确的。 我刚刚在需要pynco,
需要完整 conda nco
环境的 Conda 环境中使用上述方法被烧毁,例如通过从 cron 运行调用 conda 激活的 bash 脚本来解决ncks, ncrcat.
。
经过大量的摆弄,我crontab
用conda activate my_env
激活我的 conda 环境,并在该环境中运行 Python 解释器。
注意我使用的是 Ubuntu 18.04。
背景
-
当 Anaconda 安装程序初始化 conda 时,它会在
~/.bashrc
文件的末尾附加一个代码段。每次用户以交互方式打开bash
时,都会执行此文件。该代码段允许用户从bash
运行conda
命令(即conda activate my_env
(。 -
Anaconda 安装程序 v2020.02 在
~/.bashrc
中附加了以下conda
片段:
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/opt/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/opt/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
- 路径
/opt/anaconda3/
替换为正确的引用:通常/home/USERNAME/anaconda3/
。
问题所在
在crontab -e
中采购~/.bashrc
是行不通的(至少在 Ubuntu 上是行不通的(。
解释:
- 在 Ubuntu 上,
~/.bashrc
文件开头有以下(或类似(行:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
- 这意味着如果我们尝试在
crontab
中获取~/.bashrc
文件,.bashrc
文件的其余部分将不会执行,因为crontab
没有交互式运行(请参阅有关此主题的另一篇文章(。这意味着即使我们获取~/.bashrc
,上面提到的conda
片段也永远不会被crontab
执行。
_________ 工作解决方案 _________
我找到的解决方案是将conda
片段复制到单独的文件中。
1. 将conda
代码段从~/.bashrc
复制到~/.bashrc_conda
将上面提到的代码片段复制到另一个文件,例如 ~/.bashrc_conda
.
确保:
- 运行 cronjob 的用户有权读取此文件。
- 其他用户无法写入此文件(安全风险(。
2. 在crontab -e
插入 2 行以运行bash
而不是sh
并获取~/.bashrc_conda
运行crontab -e
并在 cronjob 之前添加以下 2 行:
SHELL=/bin/bash
BASH_ENV=~/.bashrc_conda
解释:
SHELL=/bin/bash
意味着crontab
将通过bash
而不是sh
(默认(运行 cronjobs。见帖子。BASH_ENV=~/.bashrc_conda
获取conda
代码段,bash
由chrontab
运行。请参阅帖子和帖子。
3. 在crontab -e
在所需的.py
脚本执行之前插入 cronjob 行conda activate my_env;
在所需的 conda 环境中每天中午 12:30 执行的脚本的条目示例:
30 12 * * * conda activate my_env; python /path/to/script.py
请注意conda activate my_env;
在运行 Python 解释器的命令之前。
___
瞧,它奏效了。
有什么缺点吗?如果.bashrc
中的conda
代码段通过conda
更新进行更新,它当然不会反映在单独的.bashrc_conda
文件中。可能需要不时检查更新。
也可以在该 cronjob 的末尾附加; conda deactivate
,但这可能是多余的。
不要叫sh
,而是bash
。 source
是一个 bash 命令。
- sh scripts/my_script.bash
+ bash scripts/my_script.bash
或者只是
chmod +x scripts/my_script.bash
./scripts/my_script.bash
既然你加了巴什谢邦。
就我而言,当我运行这行 shell 脚本时,我遇到了此错误:source activate my_env
activate: No such file or directory
所以我把source activate my_env
改成了source /path/to/conda/bin/activate my_env
.然后它开始工作。
使用完整路径来连接 conda
对我有用的一个简单的解决方案是在 crontab 条目中指定 conda 的完整路径,并使用 conda run -n <env>
选项在所需的环境中执行命令。就我而言,我想在启动时启动一个命令,所以我的 crontab 条目如下所示:
@reboot ~/miniconda3/bin/conda run -n <env> <command>
其中<env>
和<command>
根据您自己的要求进行替换。
> 截至 2022 年 5 月,我只需使用 Windows 10 中的.bat
来激活myenv
,然后启动我的localhost
或您需要的任何脚本:
@echo off
set CONDAPATH=C:UsersMyNameanaconda3
set ENVNAME=myenv
if %ENVNAME%==base (set ENVPATH=%CONDAPATH%) else (set ENVPATH=%CONDAPATH%envs%ENVNAME%)
call %CONDAPATH%Scriptsactivate.bat %ENVPATH%
call cd /d d:/mysite
python manage.py runserver 0.0.0.0:8000
<</div>
div class="one_answers"> 在某些情况下,这种方法可能更简单、更简洁:
查找 conda 环境的路径
conda env list
将其添加为 crontab 文件顶部的"PATH":
PATH=/Users/your_user_name/opt/anaconda3/envs/your_env/bin
有关更多详细信息,请查看此内容教程(来源(
我认为 conda 已经改变,所以这些解决方案都不再适合我,除了 @James 发布的用于在 crontab 中指定 conda 完整路径的解决方案。
但是,有时我想从 crontab 运行一个完整的 bash 脚本,并在整个脚本中激活一个 conda 环境。为此,有效的解决方案是 采购conda.sh
,正如@effecor在这里发布的那样:https://stackoverflow.com/a/65183109/1676378。
对我来说,这意味着将以下行添加到由 cron 调用的 bash 脚本的顶部:
source /home/chris/miniconda3/etc/profile.d/conda.sh
您的 conda.sh 可能位于其他地方。
根本问题解释如下:https://github.com/conda/conda/issues/7980正如nehaljwani所写:"默认情况下,函数不会导出以在子shell中可用.">
U只需要添加PATH并使用conda run -n命令
PATH=/root/miniconda3/envs/my_env/bin:/root/miniconda3/bin:/root/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
5 0 * * * conda run -n my_env python ~/my_project/main.py
简单的解决方案