☰
CentOS 7下用Miniconda搭建Python与Jupyter环境全攻略
2026/10/11 7:54:23 网站建设 项目流程

最近又帮人搭了一台 CentOS 7 服务器,任务还是老几样:装 Python 环境、把 Jupyter Notebook 跑起来,让写数据分析和脚本的同事能直接在浏览器里干活。这套组合我在 CentOS 7 上装过不下十次,每次都有人说"直接 yum install python3 不就行了",但真上了生产环境就知道,坑都在后面。这篇文章把我现在固定使用的流程完整写出来,包括为什么选 Miniconda、每一步配置背后的原因、以及那些不遇到一次根本不会注意到的细节。

如果你是刚拿到一台 CentOS 7 机器想搭 Python 开发环境,或者之前用源码编译或者 yum 装过 Python 但被各种依赖问题折腾过,这篇应该能帮你少走很多弯路。文章以 CentOS 7.9 为例,命令在腾讯云、阿里云、VMware 虚拟机上我都实测过,结果一致。

1. 为什么绕开 yum 和源码编译,直接选 Miniconda

1.1 CentOS 7 自带的 Python 动不得

CentOS 7 系统默认的 Python 是 2.7.5,这一点是整套环境的出发点。很多人上来就想着把系统 Python 升级到 Python 3,或者直接删掉重装,这是最危险的操作。CentOS 7 里的 yum、firewall-cmd、甚至是一些系统管理脚本,底层都在调用/usr/bin/python。你把系统默认 Python 一替换,轻则 yum 不能用,重则系统工具集体罢工。

我见过最典型的案例:有人把/usr/bin/python软链接直接指到了 Python 3,结果 yum 一执行就报错,连安装软件包都做不了,最后只能靠救援模式恢复。所以第一条原则:系统自带的 Python 2.7 永远不要动。我们要做的,是在旁边安装一套独立的全新 Python 环境,互不干扰。

1.2 yum 源里的 Python 版本简直是开盲盒

CentOS 7 官方源里的 Python 3 版本停留在 Python 3.6 左右,这个版本在今天跑很多新库已经有兼容问题。用 SCL(Software Collections)确实能装到更新一点的版本,但 SCL 的环境目录结构、启动方式都和普通 Python 不太一样,团队协同时容易搞晕。而且依赖包的版本同样老旧,pip 装个新包经常需要先升级一大串底层依赖,改起来很痛苦。

当然也可以编译安装 Python 3.11 之类的源码版。这个过程本身不复杂:configure、make、make install,但我遇到的麻烦几乎都藏在编译依赖里。最常见的是在 CentOS 7 上编译 Python,openssl 版本不够新,导致编译出来的 Python 的ssl模块用不了。结果就是你装好了 Python 3,然后发现 pip 连 HTTPS 源都连不上,或者 Jupyter 启动时报 SSL 相关的错误。编译前要装 zlib-devel、bzip2-devel、openssl-devel、libffi-devel、sqlite-devel 这一堆东西,少一个,后面用着用着就冒一个幺蛾子。

1.3 Miniconda 正好规避了以上所有问题

Miniconda 是一个 Python 发行版管理工具,它不是简单的"安装一个 Python",而是连带着把依赖隔离、环境管理也一起解决了。它的几个好处非常精准地命中上面的痛点:

  • 自带一个相对较新的 Python 3 解释器,装好就能直接用,不需要自己编译。
  • 环境隔离做得干净,装在独立目录里,不碰/usr/bin/python。
  • conda 命令可以创建、切换不同 Python 版本的环境,项目隔离很方便。
  • 后续安装 Jupyter、numpy、pandas 这些数据科学常用库,conda 能直接解析二进制依赖,省去编译环节,安装速度比 pip 源码编译快得多。

所以我的固定路线就是:装 Miniconda -> 换国内源 -> 用 conda 装 Jupyter -> 配置远程访问 -> 用 systemd 驻留服务。

2. 从镜像站拉取 Miniconda 并完成基础环境激活

2.1 下载安装脚本

Miniconda 官方安装脚本托管在 Anaconda 官网和对应的镜像站上,服务器在国内的话,直接访问官方源经常很慢甚至超时。我一般直接走清华 TUNA 镜像站:

cd /root wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py311_24.1.2-0-Linux-x86_64.sh

注意文件名里的版本号,py311表示默认 Python 版本是 3.11,后面的日期是构建版本。镜像站目录里通常还会有Miniconda3-latest-Linux-x86_64.sh这种 latest 版本,如果你不确定选哪个,直接用 latest 也行,它默认带的 Python 版本通常比较新。

下载完先看一眼文件大小,一般 90MB 左右,如果只有几十 KB,大概率是下载到了错误页面,删掉重新下载。

2.2 静默安装到公共目录

安装脚本的用法很简单,但我建议用静默模式,避免交互式安装时出现一些默认选项误导你。安装到哪个目录也有讲究。我自己习惯装到/usr/local/miniconda3,服务器上所有普通用户都能引用;如果你只是自己一个人用,装到/root/miniconda3也可以。

bash Miniconda3-py311_24.1.2-0-Linux-x86_64.sh -b -p /usr/local/miniconda3

-b是静默安装模式,不会询问yes/no的问题;-p指定安装路径。整个安装过程大概一两分钟,看到installation finished.就完成了。

注意:静默安装模式下,脚本不会自动帮你配置 PATH。你需要手动执行一次 conda init。

/usr/local/miniconda3/bin/conda init bash

这条命令会把 conda 的初始化逻辑写进~/.bashrc。执行完后重新登录 shell,或者手动执行source ~/.bashrc,命令行提示符前面会出现一个(base)前缀,说明已经进入 conda 默认环境。

2.3 验证环境安装结果

建议安装完成后立刻做一次验证:

which python python --version which conda conda --version

正常的输出应该是:

/usr/local/miniconda3/bin/python Python 3.11.9 /usr/local/miniconda3/bin/conda conda 24.1.2

这一步特别关键。如果你执行which python得到的还是/usr/bin/python,说明 PATH 环境变量没有生效,最常见的原因是修改~/.bashrc之后没有重新登录,或者当前 shell 不是通过 bash 启动的。另外不要轻易删/usr/bin/python软链,我们的目标是让新环境优先被使用,而不是把旧环境抹掉。

安装完 Miniconda 后有一步很多人会忽略,就是把 conda 自带的 base 环境更新到较新状态:

conda update -n base conda

这一步在还没有换源之前先别急着做,因为 conda update 需要去官方源下载元数据,速度很难看,等换完源之后再执行会舒服很多。

2.4 顺手搞定的系统网络问题

热搜词里有"centos7 无法 ping 通百度",如果你在装 Miniconda 之前就发现 wget 根本下载不了东西,说明服务器的 DNS 或者网关有问题。可以先确认:

cat /etc/resolv.conf ping -c 3 223.5.5.5

如果 IP 能 ping 通但域名 ping 不通,基本就是 DNS 没配好。往/etc/resolv.conf里加上nameserver 223.5.5.5和nameserver 114.114.114.114通常能解决。另外确认一下 yum 源可用,建议顺手把 yum 源换成国内源,这个我放在后面章节一起讲,因为它影响的是整个机器的下载体验。

3. conda 和 pip 换源:这一步直接决定你后面的心情

3.1 conda 国内源配置

conda 默认的官方源在国外,服务器在国内的话,执行conda install时经常卡在 "Solving environment" 阶段半天不动,或者下载到一半超时。这个体验太致命了,所以换源是装完 Miniconda 之后第一个要做的配置。

新建或编辑用户根目录下的~/.condarc:

vi ~/.condarc

写入以下内容:

channels: - defaults show_channel_urls: true default_channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 custom_channels: conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud

保存后执行conda clean -i清理一下索引缓存,然后跑:

conda update -n base conda

这时候你会发现下载速度从几 KB/s 变成了几 MB/s。如果清华的源偶尔抽风,也可以换中科大源:

conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/

配完之后,用conda config --show channels确认一下当前生效的 channel 列表。

3.2 pip 源配置

装完 Python 之后,pip 是绕不开的。Pip 同样优先走国外源,默认的情况下安装一个稍微大点的包都可能卡住。建议直接写到全局 pip 配置文件/etc/pip.conf,这台机器上所有用户都能受益:

[global] index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com timeout = 120

这里我习惯用阿里云的 PyPI 镜像,感觉速度和稳定性在高峰期比清华稍好一点。也可以用清华:

[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn

测试一下:

pip install requests

如果看到秒装完成,说明 pip 源已经生效。

3.3 yum 源的一并处理

前面提到 CentOS 7 的 yum 依赖系统 Python,虽然我们不会去动系统 Python,但 yum 源本身如果还是官方的 CentOS 镜像,速度同样很感人。建议顺手把 yum 的 base、extras、updates 源都切到国内镜像。以阿里云为例:

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo yum clean all yum makecache

这里注意,CentOS 7 已经进入维护周期的末期,有些镜像站对 7 的仓库已经做了 EOL 处理,如果配置后yum makecache报 404,可以换个镜像站,或者启用 vault 仓库。总之这一个步骤是为了后续安装 systemd 相关组件和系统包时别卡在半路。

4. 安装 Jupyter Notebook 并配置密码登录

4.1 用 conda 安装 Jupyter

换完源之后,安装 Jupyter 就非常轻松了。我在 base 环境直接装:

conda install -n base jupyter notebook

如果想装 JupyterLab(新版界面更现代化,功能也更强),可以:

conda install -n base jupyterlab

这两者可以共存,不冲突。我个人是两者都装,但日常用 JupyterLab 多一些。不过为了照顾团队里老一辈写脚本的习惯,本文以经典 Notebook 为例来写配置,JupyterLab 的配置方式基本相同。

安装完成后验证一下:

jupyter --version

能列出 notebook、jupyter-core 之类的组件版本号,说明安装成功。

4.2 生成密码哈希

Jupyter Notebook 的默认访问方式是通过启动时生成的 token(一串随机字符串),每次启动都变,用起来很烦。更好的方式是设置一个固定的登录密码。生成密码哈希需要用到 notebook.auth 模块:

python -c "from notebook.auth import passwd; print(passwd())"

执行后会提示你输入密码两次,然后输出一个类似这样的字符串:

argon2:$argon2id$v=19$m=10240,t=10,p=8$...

注意这串字符要完整复制保存,一会儿要写进配置文件里。如果你用的是 JupyterLab 相关的较新版本,也有可能是sha1:...开头的输出,都没问题,配置文件都认。

这里有个小提醒:别设太简单的密码。Jupyter 一旦对外开放端口,整个服务器上能访问到的文件对登录用户来说几乎是全开放的,密码强度太弱等于把服务器裸奔在网络里。

4.3 修改 Jupyter 配置文件

先生成一份默认配置:

jupyter notebook --generate-config

执行后会在~/.jupyter/jupyter_notebook_config.py生成一个拥有大量默认配置项的 Python 文件。接下来编辑它:

vi ~/.jupyter/jupyter_notebook_config.py

改动以下几个关键行(没有就追加):

c.NotebookApp.ip = '0.0.0.0' c.NotebookApp.port = 8899 c.NotebookApp.open_browser = False c.NotebookApp.password = 'argon2:$argon2id$v=19$m=10240,t=10,p=8$...' c.NotebookApp.allow_root = True c.NotebookApp.notebook_dir = '/data/jupyter'

逐项解释一下:

  • ip = '0.0.0.0':监听所有网卡地址,允许远程访问。
  • port = 8899:默认端口是 8888,但这个端口在公网上被扫描得很厉害,改成其他端口能少一些无聊的探测流量。
  • open_browser = False:服务器上根本没有浏览器,不关的话启动会报错。
  • password:刚才生成的那一串哈希。
  • allow_root = True:如果当前运行用户是 root,需要这一行;如果是普通用户运行可以不加。
  • notebook_dir:Jupyter 文件列表默认打开的目录,一般指向数据存放目录。这里要先把目录创建好:
mkdir -p /data/jupyter

补充一点:新版 Jupyter 的配置项可能用c.ServerApp.*替代c.NotebookApp.*,但c.NotebookApp在目前版本中依然被兼容。我习惯两个都写上,反正多余的配置项不会被理会,关键是别写错值。

4.4 启动并验证本地能访问

先手动启动一下,看看配置有没有问题:

jupyter notebook

正常情况下终端会输出http://0.0.0.0:8899/之类的信息,不会报错。然后本机就可以用curl验证端口是否在监听:

curl -I http://127.0.0.1:8899

看到返回HTTP/1.1 302就说明 Jupyter 服务已正常响应(302 是因为没登录被重定向到了登录页)。这时候按 Ctrl+C 停掉,我们接下来把它注册成 systemd 守护进程。

5. 用 systemd 守护 Jupyter,告别 SSH 一断服务就挂

5.1 为什么需要 systemd

如果只是手动执行jupyter notebook启动,那么当你关闭 SSH 连接时,进程就会被挂断,下次还得重新登录再启动,非常不方便。更别谈服务崩溃之后自动恢复这些事了。用 systemd 来管理是最标准的做法。

写一个专门的 service 文件:

vi /etc/systemd/system/jupyter.service

内容如下:

[Unit] Description=Jupyter Notebook Server After=network.target [Service] Type=simple User=dev Group=dev WorkingDirectory=/data/jupyter Environment="PATH=/usr/local/miniconda3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" ExecStart=/usr/local/miniconda3/bin/jupyter-notebook --config=/root/.jupyter/jupyter_notebook_config.py --no-browser --ip=0.0.0.0 --port=8899 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target

有几个细节需要特别说明:

  • User=dev和Group=dev:我建议建一个专用普通用户来跑 Jupyter,不要用 root。生产环境的服务尽量遵循最小权限原则。如果确实想用 root,就把这两行删掉,同时配置里的allow_root必须为 True。
  • ExecStart里的 Python 路径,强烈建议写绝对路径/usr/local/miniconda3/bin/jupyter-notebook。因为 systemd 的环境和你的交互式 shell 环境不一样,不写绝对路径很容易出现"我明明执行 jupyter 可以,systemd 启动却报 not found"的问题。
  • Environment="PATH=...":如果 Jupyter 后续需要调用 Python 或者外部命令,这个 PATH 列表保证了它能找到正确版本的解释器。

然后执行:

systemctl daemon-reload systemctl enable jupyter systemctl start jupyter

查看状态:

systemctl status jupyter

看到active (running)并且没有报错信息,说明服务已经正常驻留。以后即使 SSH 断开、或者服务器重启,Jupyter 都会自动启动。

查看 Jupyter 日志的常用方式:

journalctl -u jupyter -f

这个命令非常有用,排查问题时第一个想到的应该是它。

5.2 防火墙与安全组的放行

CentOS 7 默认使用 firewalld。如果你刚装完系统,防火墙可能是开启状态,需要放行端口:

firewall-cmd --zone=public --add-port=8899/tcp --permanent firewall-cmd --reload

但这里还有一个更大的坑:云服务器。如果你用的是阿里云、腾讯云等云主机,光改系统防火墙没用,云控制台的安全组也要放行对应端口。我见过很多人在服务器上折腾半天,curl 本机端口通,外部还是无法访问,最后发现是安全组规则没加。这点务必提一嘴。

查看端口是否已经对外监听:

netstat -tlnp | grep 8899

如果能看到tcp 0 0 0.0.0.0:8899 0.0.0.0:* LISTEN,说明进程已经在监听所有地址。

5.3 远程访问的几种姿势

配置好之后,远程访问主要有三种方式:

方式一,直接浏览器访问:

http://服务器IP:8899

输入你设置的密码即可。这种方式最简单,但前提是你在防火墙上把端口开放了。

方式二,SSH 隧道方式(更安全):

ssh -L 8899:127.0.0.1:8899 user@服务器IP

然后本地浏览器访问http://127.0.0.1:8899。这个方式下 Jupyter 服务本身甚至可以不监听0.0.0.0,只监听127.0.0.1就够了,SSH 加密通道帮你把数据传输保护好。适合对安全性要求高的场景。

方式三,Nginx 反向代理加 HTTPS。如果你有域名和证书,用 Nginx 把jupyter.example.com转发到本机 8899 端口,体验是最接近生产环境的。这一项涉及 Nginx 配置,这部分暂时不展开,等后续可以单独写。

6. 高频问题排查:启动失败、token 丢失、默认目录错乱

不知道是不是 Jupyter 的用户群体太大,网上关于它的问题五花八门。我把自己在 CentOS 7 上遇到过的、以及热搜词里大家最揪心的几个问题集中排查一遍。

6.1 jupyter 命令找不到

典型报错:bash: jupyter: command not found。

原因几乎都是 PATH 没有包含 Miniconda 的 bin 目录。执行:

export PATH=/usr/local/miniconda3/bin:$PATH

然后重新which jupyter,如果能找到,说明你当前 shell 的 PATH 配置有问题,检查~/.bashrc里是否有:

. /usr/local/miniconda3/etc/profile.d/conda.sh

以及 git 提示符相关的初始化。没有就重新执行一次/usr/local/miniconda3/bin/conda init bash,再做一次source ~/.bashrc。

还有一个容易碰到的场景是:用 systemd 启动时报Executable /usr/local/miniconda3/bin/jupyter-notebook not found,那是确认一下 conda 环境是在这台机器装的,路径没错;但如果你用的是pip install jupyter而且which jupyter在/usr/local/bin/jupyter,那 ExecStart 里就要改成/usr/local/bin/jupyter-notebook,不要想当然。

6.2 浏览器访问出现 password or token 是什么情况

这是新款 Jupyter 在登录界面常显示的一句话:"Password or token: ..."。很多人被这里搞懵。

原因很简单:Jupyter 的鉴权要么用 password(你在配置里设置的哈希),要么用 token(启动时自动生成的一长串)。如果你没有显式设置密码哈希,它默认使用 token 认证。所以访问时想用密码登录,必须先把 password 配置项写上;如果配了 password 但浏览器还提示 token,可能是配置没生效,或者服务没重启。

查看当前 token 的办法:

jupyter notebook list

输出会显示当前运行实例的 URL,其中就有token=xxxxxxxx;拿这个值直接粘贴到登录页的 Token 输入框就能进去。如果确认已经设置了密码但不想看到 token 提示,可以在配置文件里加上:

c.NotebookApp.token = ''

清空 token 后,就只要求密码登录了。注意修改配置后要重启服务:

systemctl restart jupyter

6.3 启动时提示找不到指定的程序

这个报错在 Windows 上双击启动脚本时特别常见(通常是脚本里写的 python 路径不存在或者环境变量混乱),但在 CentOS 7 上如果也见到类似字眼,比如jupyter-notebook: No such file or directory,多半不是文件真的不存在,而是脚本头部指定的 shebang 解释器缺失了。

解决办法很简单:直接用绝对路径执行:

/usr/local/miniconda3/bin/jupyter-notebook --version

如果绝对路径能跑而直接敲jupyter不行,说明 PATH 有问题;如果绝对路径也报No such file or directory,那可能是安装包损坏,用 conda 强制重装:

conda install -n base jupyter notebook --force-reinstall

6.4 默认打开的目录不是自己想要的那个

Jupyter 打开后文件列表落在别的目录,核心原因是notebook_dir配置没有生效,或者你启动时用了--notebook-dir覆盖了。检查顺序:

  • 配置文件里c.NotebookApp.notebook_dir = '/data/jupyter'是否被注释。
  • systemd 服务文件里的WorkingDirectory是否和 notebook_dir 一致。
  • 启动命令里有没有显式传--notebook-dir/--notebook-dir=/path参数,如果有,它的优先级高于配置文件。

我就是因为这个吃了亏:配置文件里明明设了/data/jupyter,但 service 文件里 ExecStart 带了一个--notebook-dir=/root参数,结果怎么改都不生效。后来删掉 ExecStart 里的参数,保留配置文件为准,问题解决。

6.5 网络仍然不通的排查顺序

如果你这时候发现装完 Jupyter 后服务器拉包慢、或者根本无法访问外网,按这个顺序排查:

  1. 先ping -c 3 223.5.5.5,不通说明网络链路或网关有问题,检查/etc/sysconfig/network-scripts/ifcfg-eth0的网关配置。
  2. 能 ping 通 IP 但 ping 不通域名,查/etc/resolv.conf的 DNS 配置,并确认该 DNS 没有被安全策略拦截。
  3. 端口访问不了,依次检查:Jupyter 是否在监听 -> 本机 firewall 端口是否放行 -> 云安全组是否放行 -> 路由器/NAT 是否有映射问题。

这个排查顺序基本覆盖了我遇到过的所有"外部访问不了"问题。每跳一步就能定位一层故障,避免瞎猜。

写在最后的一点体会

这套环境装完之后,日常用起来最舒服的地方是:不管哪个同事要跑数据分析,我只要给他一个 URL 和密码,他打开浏览器就能开始写代码,完全不用管背后的 Python 版本、依赖冲突这些问题。而对我来说,真正的教训只有一句话:配置一切从简,能用绝对路径就不用相对路径,能统一到一个配置文件里就不要在启动参数里层层传值。你在 systemd、Jupyter、SSH 隧道这些环节里看到的很多诡异问题,追根溯源都是 PATH 不统一或者参数优先级混乱造成的。

另外个人建议,Miniconda 装好之后给 base 环境起个别名,比如加进~/.bashrc:

alias py3='conda activate base'

这算是个小小提速技巧,省得每次都要敲完整命令。如果你照着这篇文章搭完还有没覆盖到的问题,优先去看/var/log/messages和journalctl -u jupyter -f里的日志,大部分答案其实都写在上面。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询