2020-09-19

Centos7 下 pyenv 環境中的 Python 升級記錄。含 mod-wsgi

 [升級 python / pyenv]

本篇流程在於你以前已經安裝過舊 python(例如3.5), 現在想升級新版(例如3.7)。全程都是使用 virtualenv 進行,也建議大家儘量都用 virtualenv 

* 前置安裝 (升級前必裝,之前有裝則免)

安裝一些compile時會用到的 development tools

#yum groupinstall "Development Tools"  -y

#yum install -y python-devel libevent-devel python-pip gcc xz-devel openssl-devel readline-devel sqlite-devel bzip2-devel

安裝 libffi-devel 避免產生 ctype 問題. httpd-devel 避免 mod-wsgi compile 問題
#yum install -y libffi-devel httpd-devel


* git 更新 pyenv 的版本成最新,以獲取最新 OS list

假設你原先的 pyenv 安裝在 /var/pyenv

#cd /var/pyenv/plugins/python-build/../.. && git pull && cd -
反正意思就是 git pull 最新就對了


*重要! 讓 python lib compile 成 shared 。 在pyenv 安裝 python 前必做!

因為我們 python 要在 apache 多網站多環境下使用,因此共用 python lib 是絕對必要的,因此要用 pyenv 安裝 python 時 --enable-shared

#PYTHON_CONFIGURE_OPTS="--enable-unicode=ucs4 --enable-shared"
#export PYTHON_CONFIGURE_OPTS 


*安裝 python3.7

#pyenv install  3.7.9


* 到 專案目錄下 建立 env37

切換到你的專案,建立虛擬環境

#cd /path/to/ur/project

將 global 環境切換成我們要安裝的版本,等全部大功告成後看需求是否再切回去
#pyenv global 3.7.9

檢查目前環境版本正確與否
#pyenv versions

安裝 virtualenv
#pip install virtualenv

升級 pip
#python -m pip install --upgrade pip

建立 envirtual environment 目錄
#virtualenv env37


* 啟用虛據環境,安裝所有 package

注意,有個「.」
# . env37/bin/activate

上傳我們之前 pip freeze > requirement.txt 的檔案
#pip install -r requirements.txt

再修改你的 apache/services/celery..等 環境變數成最新的 env37 即可

* 最後的最後,更新 mod_wsgi 成以目前 python 版本 build 的 wsgi

因為我們 requirements.txt 已經有 install mod-wsgi==4.7.1

若你沒有可以手動安裝

# pip install mod-wsgi

故我們只要將 虛擬環境下的 lib 直接 copy 到 httpd 的 modules 下即可(centos7 LoadModule 位置)

先刪舊資料(如果你之前有舊版已安裝的話,可 list httpd/modules 查看)

# rm -f  /etc/httpd/modules/mod_wsgi.so
# rm -f  /etc/httpd/modules/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so

再 copy 新 share library 到 httpd/modules (註:httpd/modules 是個目錄捷徑,實際位置在 /usr/lib64/httpd/modules , 但無關緊要)

copy 我們安在 env37 下的已 compiled wsgi 到 httpd modules
# cp /var/django/[你的專案]/env37/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so  /etc/httpd/modules/mod_wsgi.so

# cp /var/django/[你的專案]/env37/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so  /etc/httpd/modules

註1:由於我們對系統 link 來 link 去的 shared library 非常瞭解,所以才有100%信心做上述動作,絕對安全沒問題。若你有疑慮不放心,請看這篇安裝 mod_wsgi(https://missions5.blogspot.com/2014/06/centos-modwsgi.html)

註2:不放心的同鞋可以用 ldd 指令分別檢查你的舊 so 及新 so 檔比較看看即可明瞭

舊so
# ldd /etc/httpd/modules/mod_wsgi.so

新so
# ldd /var/django/[你的專案]/env37/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so

* 更改 /etc/ld.so.conf 下的 pyenv path 以便讓 wsgi 抓到 python shared library
例如原為
/var/pyenv/versions/3.5.1/lib/
改為
/var/pyenv/versions/3.7.9/lib/
載入
#ldconfig
註:若非要全域,個人可設環境變數 LD_LIBRARY_PATH,將 python library path 加入即可

重新啟動 apache,看 /var/log/httpd 下的 error_log
# systemctl restart httpd

[mpm_prefork:notice] [pid 9850] AH00163: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips mod_wsgi/4.7.1 Python/3.7 configured

顯示 wsgi4.7 + python3.7 正常運作, 即表示你的 so 檔已正常運行

完成!!!