切换Python3.9为默认解释器后,自定义Ubuntu 20.04 AMI的EC2实例初始无法SSH及后续遇apt_pkg模块缺失问题
看起来你遇到的问题根源在于Ubuntu 20.04的系统工具(比如cloud-init、command-not-found)深度依赖默认的Python 3.8环境,直接把python和python3全局替换为Python3.9会破坏这些工具的正常运行,进而导致SSH初始化失败和后续的模块缺失错误。下面拆解问题并给出针对性的解决方案:
一、初始SSH无法连接的原因与修复
cloud-init是EC2实例启动时负责配置SSH密钥、网络等关键初始化任务的核心组件,它默认调用系统的python3命令执行脚本。当你把python3指向Python3.9后,cloud-init会使用这个未预装其依赖的版本运行,导致初始化流程中断,SSH服务的配置(比如密钥注入)没完成,所以第一次启动连不上;重启后cloud-init不会重复执行初始化,SSH服务已经正常启动,所以能连上。
修复方案:让cloud-init使用原Python3.8
你可以选择两种方式调整配置,避免破坏cloud-init的运行环境:
调整update-alternatives配置,保留系统默认python3指向
只修改python命令指向3.9,保留python3原有的Python3.8指向:- name: Setup Python3.9 As Default Python Interpreter shell: | sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1 # 注释掉修改python3默认指向的命令,保留系统原有的Python3.8 # sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 2强制cloud-init使用Python3.8(若一定要修改python3指向)
如果必须把python3也指向3.9,那么修改cloud-init的配置文件,指定它使用原Python路径:- name: Configure cloud-init to use Python3.8 replace: path: /usr/bin/cloud-init regexp: '#!/usr/bin/env python3' replace: '#!/usr/bin/python3.8'这个操作直接修改cloud-init主脚本的解释器指定,让它强制用Python3.8运行,不受全局python3指向的影响。
二、解决apt_pkg模块缺失错误
这个错误是因为apt_pkg是针对Python3.8编译的系统模块,默认只存在于Python3.8的dist-packages目录中,Python3.9不会自动加载这个路径。可以用以下两种方式修复:
方案1:为Python3.9创建软链接指向Python3.8的apt_pkg
- name: Fix apt_pkg missing for Python3.9 shell: | # 获取Python3.8的系统模块目录 PY38_MODULE_DIR=$(python3.8 -c "import sys; print([p for p in sys.path if 'dist-packages' in p][0])") # 为Python3.9创建指向apt_pkg模块的软链接 ln -s $PY38_MODULE_DIR/apt_pkg.cpython-38-x86_64-linux-gnu.so /usr/lib/python3.9/site-packages/apt_pkg.so # 同时修复CommandNotFound模块的路径问题 ln -s $PY38_MODULE_DIR/CommandNotFound /usr/lib/python3.9/site-packages/CommandNotFound
方案2:编译安装Python3.9版本的python3-apt模块
Ubuntu官方仓库没有直接提供Python3.9版本的python3-apt包,所以可以手动编译安装:
- name: Install dependencies for compiling python3-apt apt: name: - python3.9-dev - libapt-pkg-dev - gcc - make - git state: present - name: Compile and install python3-apt for Python3.9 shell: | git clone https://git.launchpad.net/ubuntu/+source/python-apt cd python-apt git checkout ubuntu/focal ./configure --with-python3=/usr/bin/python3.9 make sudo make install
三、打包AMI前的收尾操作
在Packer完成Ansible配置后,建议清理cloud-init的状态,避免AMI携带旧的实例数据:
- name: Clean cloud-init state for AMI shell: | sudo cloud-init clean --logs sudo rm -rf /var/lib/cloud/instances
这样生成的AMI在启动EC2实例时,cloud-init能正常完成SSH配置,Python3.9也能作为默认python命令正常使用,同时系统工具不会再出现模块缺失的问题。
备注:内容来源于stack exchange,提问作者droritzz

