CentOS7 源码编译安装 Python 3.8.10,开启 SSL 功能

背景

CentOS7 自带的 Python3,或者通过 yum 安装的 Python3,可能会有无法使用 ssl 的问题:

$ python3
Python 3.8.10 (default, Jun 13 2023, 14:51:15) 
[GCC 11.2.1 20220127 (Red Hat 11.2.1-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/python3/python3.8.10/lib/python3.8/ssl.py", line 100, in <module>
    from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION
ImportError: cannot import name 'OPENSSL_VERSION_NUMBER' from '_ssl' (unknown location)
>>> 

而使用 pip3 安装依赖项,需要用到 ssl;所以我们需要源码编译 Python3,并开启 ssl 功能。

源码编译安装 openssl

下载 openssl 源码

登录 https://www.openssl.org/source/ 下载最合适版本的 openssl。

首先尝试使用 https://www.openssl.org/source/openssl-3.1.1.tar.gz,然后源码编译 Python-3.8.10时,报出如下问题:

......
Python build finished successfully!
......

Could not build the ssl module!
Python requires an OpenSSL 1.0.2 or 1.1 compatible libssl with X509_VERIFY_PARAM_set1_host().
LibreSSL 2.6.4 and earlier do not provide the necessary APIs, https://github.com/libressl-portable/portable/issues/381

......

如上信息提示我们,需要使用 openssl 1.0.2 或 1.1 版本。于是重新安装  https://www.openssl.org/source/openssl-1.1.1u.tar.gz :

$ cd /usr/local/src

$ wget https://www.openssl.org/source/openssl-1.1.1u.tar.gz

$ tar zxvf openssl-1.1.1u.tar.gz

$ cd openssl-1.1.1u

$ ./config --prefix=/usr/local/openssl/openssl1.1.1

$ make

$ sudo make install

至此,openssl就被安装到了 /usr/local/openssl/openssl1.1.1:

$ ll /usr/local/openssl/openssl1.1.1
total 0
drwxr-xr-x 2 root root  37 Jun 13 16:36 bin
drwxr-xr-x 3 root root  21 Jun 13 16:36 include
drwxr-xr-x 4 root root 159 Jun 13 16:36 lib
drwxr-xr-x 4 root root  28 Jun 13 16:37 share
drwxr-xr-x 5 root root 140 Jun 13 16:36 ssl

将 openssl 的 lib 添加到动态链接库

查看动态链接库文件配置

$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf

$ cd /etc/ld.so.conf.d

$ ls
bind-export-x86_64.conf                  kernel-3.10.0-1160.el7.x86_64.conf  mariadb-x86_64.conf
dyninst-x86_64.conf                      libiscsi-x86_64.conf                qt-x86_64.conf
kernel-3.10.0-1160.88.1.el7.x86_64.conf  

$ cat mariadb-x86_64.conf 
/usr/lib64/mysql

如上,可以看到,所谓添加动态链接库,就是在 /etc/ld.so.conf.d 目录中创建一个 .conf 文件,其中填写 lib.so 文件所在的目录即可。
上一步将 openssl 安装到了 /usr/local/openssl/openssl1.1.1,可以看到其中的 lib目录包含了相关的 lib*.so 文件:

$ ll /usr/local/openssl/openssl1.1.1/lib/
total 10440
drwxr-xr-x 2 root root      39 Jun 13 16:36 engines-1.1
-rw-r--r-- 1 root root 5603958 Jun 13 16:36 libcrypto.a
lrwxrwxrwx 1 root root      16 Jun 13 16:36 libcrypto.so -> libcrypto.so.1.1
-rwxr-xr-x 1 root root 3362560 Jun 13 16:36 libcrypto.so.1.1
-rw-r--r-- 1 root root 1027122 Jun 13 16:36 libssl.a
lrwxrwxrwx 1 root root      13 Jun 13 16:36 libssl.so -> libssl.so.1.1
-rwxr-xr-x 1 root root  689720 Jun 13 16:36 libssl.so.1.1
drwxr-xr-x 2 root root      61 Jun 13 16:36 pkgconfig

创建动态链接库配置

那么在 /etc/ld.so.conf.d 中创建 openssl-1.1.1.conf 文件,并填写 /usr/local/openssl/openssl1.1.1/lib 即可:

$ cat /etc/ld.so.conf.d/openssl-1.1.1.conf 
/usr/local/openssl/openssl1.1.1/lib

重新加载动态链接库

# 需要 root 权限
$ sudo ldconfig

配置 openssl 环境变量

$ sudo vim /etc/bashrc:
# 添加如下内容

OPENSSL_VERSION=1.1.1
OPENSSL_PATH=/usr/local/openssl
OPENSSL_BIN=${OPENSSL_PATH}/openssl${OPENSSL_VERSION}/bin
export PATH=${OPENSSL_BIN}:${PATH}


$ source /etc/bashrc 

查看安装结果

$ openssl version
OpenSSL 1.1.1u  30 May 2023

至此,openssl 相关环境就完全配置完毕了。

源码编译安装 python3.8.10

下载 python3.8.10 源码

$ cd /usr/local/src

$ wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz

$ tar zxvf Python-3.8.10.tgz

$ cd Python-3.8.10

编辑 Modules/Setup

编辑 /usr/local/src/Python-3.8.10/Modules/Setup

SSL=/usr/local/openssl 处的注释解除,并修改SSL为刚才安装的 openssl 路径

$ vim Modules/Setup
# 编辑后的内容如下:
SSL=/usr/local/openssl/openssl1.1.1
_ssl _ssl.c \
        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
        -L$(SSL)/lib -lssl -lcrypto

配置 Python3.8.10

/usr/local/src/Python-3.8.10 目录下执行如下命令进行配置;

--prefix 参数用于指定后续的 make install 命令会将 Python 安装到哪个目录;

--with-openssl 参数用于指定编译出来的 Python 开启 ssl 功能,并指定 openssl 相关库文件的位置。

$ ./configure --prefix=/usr/local/python3/python3.8.10 --with-openssl=/usr/local/openssl/openssl1.1.1

......
checking for openssl/ssl.h in /usr/local/openssl/openssl1.1.1... yes
checking whether compiling and linking against OpenSSL works... yes
checking for X509_VERIFY_PARAM_set1_host in libssl... yes
checking for --with-ssl-default-suites... python
......

编译 Python3.8.10

$ make

......
The following modules found by detect_modules() in setup.py, have been
built by the Makefile instead, as configured by the Setup files:
_abc                  _ssl                  atexit
pwd                   time

running build_scripts
creating build/scripts-3.8
copying and adjusting /usr/local/src/python_src/Python-3.8.10/Tools/scripts/pydoc3 -> build/scripts-3.8
copying and adjusting /usr/local/src/python_src/Python-3.8.10/Tools/scripts/idle3 -> build/scripts-3.8
copying and adjusting /usr/local/src/python_src/Python-3.8.10/Tools/scripts/2to3 -> build/scripts-3.8
changing mode of build/scripts-3.8/pydoc3 from 664 to 775
changing mode of build/scripts-3.8/idle3 from 664 to 775
changing mode of build/scripts-3.8/2to3 from 664 to 775
renaming build/scripts-3.8/pydoc3 to build/scripts-3.8/pydoc3.8
renaming build/scripts-3.8/idle3 to build/scripts-3.8/idle3.8
renaming build/scripts-3.8/2to3 to build/scripts-3.8/2to3-3.8
/usr/bin/install -c -m 644 ./Tools/gdb/libpython.py python-gdb.py
gcc -pthread -c -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall    -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration  -I./Include/internal  -I. -I./Include    -DPy_BUILD_CORE -o Programs/_testembed.o ./Programs/_testembed.c
gcc -pthread     -Xlinker -export-dynamic -o Programs/_testembed Programs/_testembed.o libpython3.8.a -lcrypt -lpthread -ldl  -lutil -lm -L/usr/local/openssl/openssl1.1.1/lib -lssl -lcrypto   -lm
sed -e "s,@EXENAME@,/usr/local/python3/python3.8.10/bin/python3.8," < ./Misc/python-config.in >python-config.py
LC_ALL=C sed -e 's,\$(\([A-Za-z0-9_]*\)),\$\{\1\},g' < Misc/python-config.sh >python-config

安装

$ sudo make install

......
(cd /usr/local/python3/python3.8.10/bin; ln -s 2to3-3.8 2to3)
if test "x" != "x" ; then \
        rm -f /usr/local/python3/python3.8.10/bin/python3-32; \
        (cd /usr/local/python3/python3.8.10/bin; ln -s python3.8-32 python3-32) \
fi
if test "x" != "x" ; then \
        rm -f /usr/local/python3/python3.8.10/bin/python3-intel64; \
        (cd /usr/local/python3/python3.8.10/bin; ln -s python3.8-intel64 python3-intel64) \
fi
rm -f /usr/local/python3/python3.8.10/share/man/man1/python3.1
(cd /usr/local/python3/python3.8.10/share/man/man1; ln -s python3.8.1 python3.1)
if test "xupgrade" != "xno"  ; then \
        case upgrade in \
                upgrade) ensurepip="--upgrade" ;; \
                install|*) ensurepip="" ;; \
        esac; \
         ./python -E -m ensurepip \
                $ensurepip --root=/ ; \
fi
Looking in links: /tmp/tmpmsb395gk
Processing /tmp/tmpmsb395gk/setuptools-56.0.0-py3-none-any.whl
Processing /tmp/tmpmsb395gk/pip-21.1.1-py3-none-any.whl
Installing collected packages: setuptools, pip
Successfully installed pip-21.1.1 setuptools-56.0.0
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv

配置 Python 环境变量

$ sudo vim /etc/bashrc

PY_VERSION=3.8.10
PY_PATH=/usr/local/python3
PY_BIN=${PY_PATH}/python${PY_VERSION}/bin
export PATH=${PY_BIN}:${PATH}

$ source /etc/bashrc 

查看安装结果

$ python3
Python 3.8.10 (default, Jun 13 2023, 19:28:11)
[GCC 11.2.1 20220127 (Red Hat 11.2.1-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import ssl
>>>

2023.06.14 Wed 14:24

posted @ 2023-06-21 17:22  HorseShoe2016  阅读(1725)  评论(0编辑  收藏  举报