星期二, 4月 13, 2021

ubuntu 20.04 + Python3.9.4

sudo apt vim
sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev
#ubuntu 21.04預設為python 3.9.5,直接apt安裝即可
sudo apt install python3 python3-pip python3.9-venv

sudo su
export mypyenv=3.9.5;
wget https://www.python.org/ftp/python/"$mypyenv"/Python-"$mypyenv".tgz
tar zxvf Python-"$mypyenv".tgz
cd Python-"$mypyenv"/
export LDFLAGS=-L/usr/lib64;./configure --prefix=/opt/python"$mypyenv"  --enable-shared --enable-optimizations
make -j 8
make test
make install

# 如果要用vpython, 因為還沒設定路徑,所以要用完整路徑執行剛安裝的python, 且會遇到shared library的問題,
# 因此要記得export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/$mypyenv/lib
# vpython 指令
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/$mypyenv/lib
cd $HOME
/opt/$mypyenv/bin/python3 -m venv v$mypyenv
vi $HOME/.bashrc
#加上 source $HOME/$mypyenv/bin/activate # $HOME基本上是你執行python3 -m venv的地方…
然後link 相關lib到$HOME/$mypyenv/lib裏
cd $HOME/$mypyenv/lib/
ln -s /opt/$mypyenv/lib/*.so ./
ln -s /opt/$mypyenv/lib/*.so.1.0 ./
vi $HOME/$mypyenv/bin/activate
#最後面加上
PYTHON3=/opt/python3.10.1
if [ -z "${LD_LIBRARY_PATH}" ]
then
    LD_LIBRARY_PATH="$PYTHON3/lib"; export LD_LIBRARY_PATH
else
    LD_LIBRARY_PATH="$PYTHON3/lib:${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH
fi

gdal

#直接裝套件
sudo apt install gdal-bin libgdal-dev
#或是自行編譯
apt install proj-bin libproj-dev netcdf-bin 
apt install libhdf5-dev libhdf4-dev libcurl4-openssl-dev libdap-dev libopenjp2-7-dev libkml-dev libgeos-dev
export GDALVER="3.2.3"
wget http://download.osgeo.org/gdal/$GDALVER/gdal-$GDALVER.tar.gz
tar zxvf gdal-$GDALVER.tar.gz
cd gdal-$GDALVER
./configure --prefix=/usr/local/gdal-$GDALVER
make -j 2 # 看你有幾個core,數字就多少,可以用到多核,
make install

postgresql

#ubuntu 21.04 預設為13版,改用如下指令
sudo apt install postgresql-server-dev-13 postgresql-client-13 postgis
#ubuntu 20.04 預設為12版
sudo apt install postgresql-server-dev-12 postgresql-client-12 postgis # 全都需要,不然pip3 install psycopg2會失敗
sudo su
su postgres
psql
CREATE DATABASE djangodb;
CREATE USER djdbuser WITH ENCRYPTED PASSWORD 'xxxxxx' ; <--新增使用者且對密碼加密(這個不需本機使用者,且可以用MD5由別台機登入)
GRANT ALL PRIVILEGES ON DATABASE djangodb to djdbuser ;
\q
psql djangodb
create extension postgis;

#修改
vi /etc/postgresql/12/main/pg_hba.conf
#加上
local   djangodb        all                                     md5
#重啟服務
systemctl restart postgresql
#
pip3 install GDAL==$(gdal-config --version | awk -F'[.]' '{print $1"."$2}')

django + uwsgi + nginx

sudo apt install nginx npm
sudo npm install -g parcel-bundler
pip3 install django
pip3 install uwsgi
pip3 install pyproj
pip3 install scipy
pip3 install netcdf4
pip3 install matplotlib
pip3 install pandas
pip3 install --global-option=build_ext --global-option=`gdal-config --cflags`  GDAL==`gdal-config --version`
#pip3 install psycopg2-binary #2.8版後改安裝psycopg2-binary,不然系統會說沒有psycopg2 模組
pip3 install psycopg # ubuntu 22.04
# 建立django專案(名稱為,remotesensing,路徑為/var/www/cgi-bin)
cd /var/www/cgi-bin
django-admin startproject remotesensing
cd remotesensing
python3 manage.py startapp xbradar


假設我們有一個remotesensing的django project,在PROJHOME=/var/www/cgi-bin/remotesensing 下
設定nginx
#在$PROJHOME/remotesensing/ 下新增 uwsgi_params 檔案
vi $PROJHOME/remotesensing/uwsgi_params
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS            $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;


#在$PROJHOME/remotesensing/ 下新增 remotesensing_nginx.conf 檔案
vi $PROJHOME/remotesensing/remotesensing_nginx.conf
# the upstream component nginx needs to connect to
upstream django_remotesensing {
     server unix:///var/www/cgi-bin/remotesensing/remotesensing/remotesensing.sock; # 這裏我們預計使用sock檔案,這個路徑必需是uwsgi所指定的路徑(設定檔如下),另外需注意路徑權限的問題
    #server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      80;
    # the domain name it will serve for
    server_name 192.168.10.91; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /remotesensing/media  {
        alias /var/www/cgi-bin/remotesensing/media;  # your Django project's media files - amend as required
    }

    location /remotesensing/static {
        alias /var/www/cgi-bin/remotesensing/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location /remotesensing {
        uwsgi_pass django_remotesensing;
        include     /var/www/cgi-bin/remotesensing/remotesensing/uwsgi_params; # the uwsgi_params 我們上面新增的uwsgi_params檔案
    }
}

#存檔後將這個檔案製作soft link到 /etc/nginx/sites-enabled 裹
cd /etc/nginx/sites-enabled
sudo ln -s /var/www/cgi-bin/remotesensing/remotesensing/remotesensing_nginx.conf
sudo systemctl restart nginx # 重啟 nginx 服務


設定uwsgi
新增PROJHOME/remotesensing/uwsgi.ini檔
vi /var/www/cgi-bin/remotesensing/remotesensing/uwsgi.ini
[uwsgi]
# 注意,註解要是全新的一行,不要接在設定面,會被當成設定內容,導致錯誤。
chdir        = /var/www/cgi-bin/remotesensing
# Django's wsgi file
#module       = remotesensing.wsgi:application
mount        = /remotesensing=remotesensing.wsgi:application
#按個人習慣,我喜歡把一個PROJ加到URL裏,例如http://my.domain/remotesensing 如果要拿掉,記得上面設定也要改。
manage-script-name = true
#env          = DJANGO_SETTINGS_MODULE=remotesensing.settings.production
env          = DJANGO_SETTINGS_MODULE=remotesensing.settings
# the virtualenv (full path)
home         = /opt/vPy-3.9.5

# process-related settings
# master
master       = true
# maximum number of worker processes
processes    = 2
# the socket (use the full path to be safe
socket       = /var/www/cgi-bin/remotesensing/remotesensing/remotesensing.sock
# 這個是指透過socket連接,不用另外指tcp port,較省資源
#當系統運作時,會在上面的路行建立remotesensing.sock檔,這個路徑必需與nginx.conf一致。另外需注意權限問題,此處是改為666
# ... with appropriate permissions - may be needed
chmod-socket = 666
#uid          = driftertek
#gid          = www-data
# clear environment on exit
vacuum       = true


讓 uwsgi 可以監視某個資料夾(此處設為/etc/uwsgi/vassals),只要裏面的uwsgi相關的config檔有更勭,就會自動套用
以root的身份建立資料夾
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals
把之前建立的uwsgi.ini放建立soft link 到 /etc/uwsgi/vassals 裏
sudo ln -s /var/www/cgi-bin/remotesensing/remotesensing/uwsgi.ini /etc/uwsgi/vassals/


以 root 的身份執行下面指令(注意,如果是用venv,只要以實際的完整路徑去執行uwsgi即可,它會知道相關環境。)
sudo /opt/vPy-3.9.5/bin/uwsgi --emperor /etc/uwsgi/vassals --uid driftertek --gid driftertek
上面這行可以放到rc.local裏去,或是新增成systemctl的一個服務(這裏取名叫djuwsgi)
vi /etc/systemd/system/djuwsgi.service
[Unit]
Description=for django detect uwsgi conf in /etc/uwsgi/vassal

[Service]
Type=simple
ExecStart=/opt/vPy-3.9.5/bin/uwsgi --emperor /etc/uwsgi/vassals --uid driftertek --gid driftertek  --daemonize /var/log/uwsgi/emperor.log
Restart=always

[Install]
WantedBy=multi-user.target

#注意使用者名稱及uwsgi的位置可能不同
#ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid ihmt --gid ihmt  --daemonize /var/log/uwsgi/emperor.log
#存檔之後
mkdir /var/log/uwsgi 
systemctl start djuwsgi
#設為開機啟動
systemctl enable djuwsgi
systemctl enable nginx # nginx 也順便設一下
systemctl enable postrgresql