DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

conda activate 在终端正常,在 Bash 脚本中却要求 conda init

conda info可运行,普通Bash脚本却无法activate,常见分支是没加载shell函数。单命令用核对过的conda run,多步任务检查hook和激活状态。

同一个 Conda 环境在终端能激活,放进 bash job.sh 却报 shell 没有正确配置,要求执行 conda init;脚本里的 conda info 又能运行。先区分 Conda 可执行程序与当前 shell 中的 conda 函数。

激活需要修改当前 shell 的环境。可执行程序能够显示信息,不代表脚本已经加载了负责激活的 shell 函数。下面针对普通的非交互 Bash 脚本,按 Conda 26.9.2 的接口说明处理;以 sh、登录 shell 或 SSH 启动时,应另查对应的启动规则。

新脚本不会照搬终端的初始化过程

在正常终端和失败脚本中分别检查 type conda,确认选中的安装位置及函数是否存在。不要只看 which conda:PATH 中有一个可执行文件,并不足以判断 shell 函数已经定义。

conda init bash 通常把初始化代码写入 shell 启动文件。普通非交互 Bash 脚本不会默认像交互终端那样读取 .bashrc,因此反复执行 init 或重新打开终端,未必改变脚本的启动条件。

也不要为了激活环境,直接让整个任务强制变成交互 shell。这样可能引入历史记录、提示设置和其他用户启动代码。脚本真正需要的初始化应在它自己的执行范围内明确安排。

只有一条命令时,可以用 conda run

已经核对 Conda 安装入口、现有环境目录和应用工作目录后,可由 conda run 在目标环境里执行命令。下面全部路径都是需要替换的示例,worker.py 是应用原有任务:

/opt/miniconda3/bin/conda run \
  -p /srv/conda/envs/app --cwd /srv/app \
  -- python worker.py

-p 指向现有环境,--cwd 明确工作目录,-- 分隔 Conda 参数和应用命令。用核对过的绝对路径,可以避开机器上另一套 Conda。conda run 通过包装流程准备环境,并返回子命令的退出状态;上层计划任务仍应保留和处理失败状态。

默认会捕获输出。确实需要持续显示任务日志时,可按当前版本使用 --no-capture-output。这与激活是否正确是两件事,不能把暂时没有实时输出判断为程序没有运行。

直接调用环境里的 Python 绝对路径,有时足以运行纯 Python 任务,但不等同于执行了全部 Conda 激活脚本。依赖 activate.d 设置的变量或工具链时,应核对完整环境准备过程。

多步脚本在自己的 Bash 中加载 hook

如果多条命令都需要同一环境,可以在脚本中用可信的 Conda 程序生成 Bash hook,再激活已确认的环境。下面只展示初始化与原任务入口,必须先替换三个路径:

#!/usr/bin/env bash

task_conda=/opt/miniconda3/bin/conda
task_env=/srv/conda/envs/app

task_hook=$("$task_conda" shell.bash hook) || exit 1
eval "$task_hook" || exit 1
conda activate "$task_env" || exit 1

cd /srv/app || exit 1
python worker.py

eval 执行的是自己核对过的本机 Conda 生成的初始化代码,不能换成下载文本或任意外部输入。先检查生成状态,再执行 hook 和 activate;不要用丢弃 stderr 的写法掩盖失败,然后让任务带着另一套 Python 继续运行。hook 自身可能按安装配置激活 base,后面仍需明确选择任务环境。

仅运行 conda shell.bash activate,通常只是打印应由 shell 执行的代码,不能据此判断当前环境已经改变。脚本还应从实际启动入口检查 CONDA_PREFIX 和 Python 路径,以及业务需要的环境变量;不要公开打印完整环境或凭据。

执行脚本只会影响其子 shell,不会把调用它的终端一并切到目标环境。source job.sh 则会在调用者 shell 中执行整份脚本,连同 cd、变量和可能的 exit 都会影响调用者;只有确实需要这种行为且审读过脚本时才采用。

保存任务脚本和计划任务入口,按原运行用户、工作目录及启动方式检查原业务任务,不要只验证交互终端能激活。需要撤回时恢复这些入口及初始化片段;恢复脚本不会撤销任务已经写入的数据或发送的外部请求。

如果激活成功,但编辑器仍找不到已安装模块,继续核对编辑器与 pip 是否使用同一解释器。