部署django和vue架在邏輯上能夠分爲web層與數據庫層:web前端經過實現了WSGI協議的模塊對python代碼進行解析,而python代碼中則經過特定於數據庫的操做接口對數據庫進行讀取與寫入。javascript
Django自身內置了輕量級的web服務器與sqlite數據庫,能夠用於簡單的代碼測試,並支持Apache httpd與Nginx做爲web前端,以及PostgreSQL/MySQL/Oracle等數據庫做爲後端存儲,用於實際的生產環境。php
本文分別以MySQL + Apache httpd + mod_wsgi與MySQL + Nginx + uwsgi爲例,經過源碼安裝的方式,簡單描述Django服務框架在Linux系統生產環境下的部署過程。css
1. 示例中包含兩臺服務器,操做系統版本均爲CentOS 7.6.1810,最小化全新安裝,無其餘項目運行。html
2. 示例中所使用的源碼包均位於/usr/local/src,列表以下:前端
Python-3.7.2.tgz
Django-2.1.5.tar.gz
mysql-boost-5.7.24.tar.gz
mysqlclient-1.3.14.tar.gz
httpd-2.4.37.tar.gz
apr-1.6.5.tar.gz
apr-util-1.6.1.tar.gz
mod_wsgi-4.6.5.tar.gz
tengine-2.2.3.tar.gz
uwsgi-2.0.17.1.tar.gzvue
3. 示例中對源碼包進行安裝時,均使用默認的目標安裝路徑。在實際的生產環境中,爲避免覆蓋,安裝前務必確認目標安裝路徑與文件是否存在,若存在則應查看當前已安裝版本,並選擇其餘目錄。java
[root@django-db ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}' 192.168.9.130/24 [root@django-db ~]#
安裝依賴包:node
[root@django-db ~]# yum -y install gcc gcc-c++ make cmake ncurses-devel openssl-devel
下載集成boost庫的mysql源碼包:python
[root@django-db ~]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.24.tar.gz -P /usr/local/src/
解壓源碼包並進入源碼目錄,配置編譯選項:mysql
源碼安裝mysql的默認目標路徑爲/usr/local/mysql,能夠經過cmake的-DCMAKE_INSTALL_PREFIX選項顯式指定。
[root@django-db ~]# cd /usr/local/src/ [root@django-db src]# [root@django-db src]# ll total 47960 -rw-r--r-- 1 root root 49110448 Oct 4 04:02 mysql-boost-5.7.24.tar.gz [root@django-db src]# [root@django-db src]# tar axf mysql-boost-5.7.24.tar.gz [root@django-db src]# [root@django-db src]# ll total 47964 drwxr-xr-x 36 7161 31415 4096 Oct 4 06:02 mysql-5.7.24 -rw-r--r-- 1 root root 49110448 Oct 4 04:02 mysql-boost-5.7.24.tar.gz [root@django-db src]# [root@django-db src]# cd mysql-5.7.24/ [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# ll /usr/local/mysql ls: cannot access /usr/local/mysql: No such file or directory [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# cmake . \ > -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ > -DWITH_BOOST=boost \ > -DWITH_INNOBASE_STORAGE_ENGINE=1 \ > -DWITH_PARTITION_STORAGE_ENGINE=1 \ > -DWITH_FEDERATED_STORAGE_ENGINE=1 \ > -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ > -DWITH_MYISAM_STORAGE_ENGINE=1 \ > -DENABLED_LOCAL_INFILE=1 \ > -DENABLE_DTRACE=0 \ > -DDEFAULT_CHARSET=utf8mb4 \ > -DDEFAULT_COLLATION=utf8mb4_general_ci \ > -DWITH_SSL=yes \ > -DWITH_EMBEDDED_SERVER=1
編譯並安裝:
可選擇爲make命令指定-j選項,執行多任務並行編譯;該步驟耗時較長,建議在screen/tmux等終端中運行,或以nohup的方式後臺運行,避免因終端關閉而致使運行終止。
[root@django-db mysql-5.7.24]# awk '/^processor/{print $3}' /proc/cpuinfo | wc -l 2 [root@django-db mysql-5.7.24]# make -j2 && make install
建立mysql用戶和組:
[root@django-db mysql-5.7.24]# id mysql id: mysql: no such user [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# useradd mysql -s /sbin/nologin [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# id mysql uid=1000(mysql) gid=1000(mysql) groups=1000(mysql) [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]#
建立mysql數據目錄與日誌目錄(本例中分別爲/usr/local/mysql/data與/usr/local/mysql/logs/):
[root@django-db mysql-5.7.24]# ll /usr/local/mysql/ total 64 drwxr-xr-x 2 root root 4096 Jan 16 15:26 bin -rw-r--r-- 1 root root 17987 Oct 4 05:48 COPYING -rw-r--r-- 1 root root 17987 Oct 4 05:48 COPYING-test drwxr-xr-x 2 root root 55 Jan 16 15:25 docs drwxr-xr-x 3 root root 4096 Jan 16 15:25 include drwxr-xr-x 4 root root 192 Jan 16 15:26 lib drwxr-xr-x 4 root root 30 Jan 16 15:26 man drwxr-xr-x 10 root root 4096 Jan 16 15:26 mysql-test -rw-r--r-- 1 root root 2478 Oct 4 05:48 README -rw-r--r-- 1 root root 2478 Oct 4 05:48 README-test drwxr-xr-x 28 root root 4096 Jan 16 15:26 share drwxr-xr-x 2 root root 90 Jan 16 15:26 support-files [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# mkdir -p /usr/local/mysql/{data,logs}
建立mysql運行時pid文件,錯誤日誌文件,慢查詢日誌文件(本例中分別爲/usr/local/mysql/logs/mysqld.pid,/usr/local/mysql/logs/mysqld-err.log與/usr/local/mysql/logs/mysqld-slw.log):
[root@django-db mysql-5.7.24]# touch /usr/local/mysql/logs/{mysqld.pid,mysqld-err.log,mysqld-slw.log} [root@django-db mysql-5.7.24]#
將mysql安裝的目標路徑(本例中爲/usr/local/mysql/)全部者設置爲mysql用戶和組:
[root@django-db mysql-5.7.24]# chown -R mysql:mysql /usr/local/mysql/ [root@django-db mysql-5.7.24]#
將mysql可執行文件的路徑(本例爲/usr/local/mysql/bin)添加至系統的查找路徑列表PATH中:
[root@django-db mysql-5.7.24]# which mysqld /usr/bin/which: no mysqld in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# sed -i '/^PATH/ s|$|:/usr/local/mysql/bin|' ~/.bash_profile [root@django-db mysql-5.7.24]# source ~/.bash_profile [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# [root@django-db mysql-5.7.24]# which mysqld /usr/local/mysql/bin/mysqld [root@django-db mysql-5.7.24]# mysqld --version mysqld Ver 5.7.24 for Linux on x86_64 (Source distribution)
初始化數據庫:
[root@django-db mysql-5.7.24]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data 2019-01-16T15:51:56.003707Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 2019-01-16T15:51:56.308083Z 0 [Warning] InnoDB: New log files created, LSN=45790 2019-01-16T15:51:56.355390Z 0 [Warning] InnoDB: Creating foreign key constraint system tables. 2019-01-16T15:51:56.414615Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: a6bc7921-19a6-11e9-a9ff-000c29000409. 2019-01-16T15:51:56.415817Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened. 2019-01-16T15:51:56.725302Z 0 [Warning] CA certificate ca.pem is self signed. 2019-01-16T15:51:56.897014Z 1 [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option. [root@django-db mysql-5.7.24]#
編輯mysql配置文件:
MySQL服務器的運行參數須要根據實際的應用場景與服務器的硬件配置而進行調整。
[root@django-db mysql-5.7.24]# cd [root@django-db ~]# [root@django-db ~]# ll /etc/my.cnf -rw-r--r--. 1 root root 570 Aug 16 14:00 /etc/my.cnf [root@django-db ~]# [root@django-db ~]# cp -a /etc/my.cnf{,.ori} [root@django-db ~]# [root@django-db ~]# vi /etc/my.cnf [mysqld] user = mysql port = 3306 server-id = 1 character-set-server = utf8mb4 socket = /tmp/mysql.sock basedir = /usr/local/mysql datadir = /usr/local/mysql/data pid-file = /usr/local/mysql/logs/mysqld.pid log_error = /usr/local/mysql/logs/mysqld-err.log slow_query_log_file = /usr/local/mysql/logs/mysqld-slw.log skip-name-resolve = 1 back_log = 300 max_connections = 1000 max_connect_errors = 6000 open_files_limit = 65535 table_open_cache = 128 max_allowed_packet = 4M binlog_cache_size = 1M max_heap_table_size = 8M tmp_table_size = 16M read_buffer_size = 2M read_rnd_buffer_size = 8M sort_buffer_size = 8M join_buffer_size = 8M key_buffer_size = 4M thread_cache_size = 8 query_cache_type = 1 query_cache_size = 8M query_cache_limit = 2M ft_min_word_len = 4 log_bin = mysql-bin binlog_format = mixed expire_logs_days = 30 slow_query_log = 1 long_query_time = 1 performance_schema = 0 explicit_defaults_for_timestamp #lower_case_table_names = 1 skip-external-locking default_storage_engine = InnoDB innodb_file_per_table = 1 innodb_open_files = 500 innodb_buffer_pool_size = 64M innodb_write_io_threads = 4 innodb_read_io_threads = 4 innodb_thread_concurrency = 0 innodb_purge_threads = 1 innodb_flush_log_at_trx_commit = 2 innodb_log_buffer_size = 2M innodb_log_file_size = 32M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 90 innodb_lock_wait_timeout = 120 bulk_insert_buffer_size = 8M myisam_sort_buffer_size = 8M myisam_max_sort_file_size = 10G myisam_repair_threads = 1 interactive_timeout = 28800 wait_timeout = 28800 [mysqldump] quick max_allowed_packet = 16M [myisamchk] key_buffer_size = 8M sort_buffer_size = 8M read_buffer = 4M write_buffer = 4M
將mysql的共享庫文件所在目錄(本例中爲/usr/local/mysql/lib)添加到系統共享庫查找路徑列表的配置文件中:
[root@django-db ~]# echo "/usr/local/mysql/lib" >> /etc/ld.so.conf.d/mysql-v5.7.24.conf [root@django-db ~]# [root@django-db ~]# cat /etc/ld.so.conf.d/mysql-v5.7.24.conf /usr/local/mysql/lib [root@django-db ~]# [root@django-db ~]# ldconfig [root@django-db ~]#
添加mysql服務,並設置爲隨系統啓動:
[root@django-db ~]# cp -a /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld [root@django-db ~]# chmod 755 /etc/init.d/mysqld [root@django-db ~]# chkconfig --level 35 mysqld on [root@django-db ~]#
啓動mysql服務:
[root@django-db ~]# /etc/init.d/mysqld start Starting MySQL.. SUCCESS! [root@django-db ~]#
設置mysql的root用戶密碼,並添加相應的受權(初始密碼爲空,本例中將root密碼設置爲django):
[root@django-db ~]# mysql -uroot -e "use mysql; set password for 'root'@'localhost' = password('django');" [root@django-db ~]# [root@django-db ~]# mysql -uroot -pdjango -e "grant all privileges on *.* to root@'192.168.9.%' identified by 'django' with grant option;" mysql: [Warning] Using a password on the command line interface can be insecure. [root@django-db ~]#
MySQL服務器安裝與配置完成。
[root@django-web ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}' 192.168.9.129/24 [root@django-web ~]#
安裝依賴包:
[root@django-web ~]# yum -y install gcc make libffi-devel readline-devel zlib-devel openssl-devel
下載python3源碼包:
[root@django-web ~]# wget https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tgz -P /usr/local/src/
解壓源碼包並進入源碼目錄,執行安裝:
源碼安裝python3的默認目標路徑爲/usr/local,能夠經過configure命令的--prefix選項顯式指定。該步驟耗時較長,建議在screen/tmux等終端中運行,或以nohup的方式後臺運行,避免因終端關閉而致使運行終止。
[root@django-web ~]# cd /usr/local/src/ [root@django-web src]# [root@django-web src]# ll total 22364 -rw-r--r-- 1 root root 22897802 Dec 24 03:42 Python-3.7.2.tgz [root@django-web src]# [root@django-web src]# tar axf Python-3.7.2.tgz [root@django-web src]# [root@django-web src]# cd Python-3.7.2/ [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# ./configure --enable-shared --enable-optimizations ... [root@django-web Python-3.7.2]# awk '/^processor/{print $3}' /proc/cpuinfo | wc -l 2 [root@django-web Python-3.7.2]# make -j2 && make install
將python3的共享庫文件所在目錄(本例中爲/usr/local/lib)添加到系統共享庫查找路徑列表的配置文件中:
[root@django-web Python-3.7.2]# which python3 /usr/local/bin/python3 [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# python3 -V python3: error while loading shared libraries: libpython3.7m.so.1.0: cannot open shared object file: No such file or directory [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# ll /usr/local/lib total 12072 lrwxrwxrwx 1 root root 20 Jan 16 17:05 libpython3.7m.so -> libpython3.7m.so.1.0 -r-xr-xr-x 1 root root 12337216 Jan 16 17:05 libpython3.7m.so.1.0 -r-xr-xr-x 1 root root 7656 Jan 16 17:05 libpython3.so drwxr-xr-x 2 root root 67 Jan 16 17:06 pkgconfig drwxr-xr-x 35 root root 8192 Jan 16 17:06 python3.7 [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# echo '/usr/local/lib' >> /etc/ld.so.conf.d/python-v3.7.2.conf [root@django-web Python-3.7.2]# ldconfig [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# [root@django-web Python-3.7.2]# python3 -V Python 3.7.2 [root@django-web Python-3.7.2]#
Python3解析器安裝完成。
安裝依賴包mysql-devel:
mysqlclient依賴於mysql服務端開發庫,若本機中先前已安裝mysql服務器,則無需此步驟。
[root@django-web ~]# yum -y install mysql-devel
下載mysqlclient源碼包:
[root@django-web ~]# wget https://files.pythonhosted.org/packages/f7/a2/1230ebbb4b91f42ad6b646e59eb8855559817ad5505d81c1ca2b5a216040/mysqlclient-1.3.14.tar.gz -P /usr/local/src/
解壓源碼包並進入源碼目錄,執行安裝:
[root@django-web ~]# cd /usr/local/src/ [root@django-web src]# [root@django-web src]# ll total 22460 -rw-r--r-- 1 root root 91391 Dec 4 10:06 mysqlclient-1.3.14.tar.gz drwxr-xr-x 19 501 501 4096 Jan 16 17:05 Python-3.7.2 -rw-r--r-- 1 root root 22897802 Dec 24 03:42 Python-3.7.2.tgz [root@django-web src]# [root@django-web src]# tar axf mysqlclient-1.3.14.tar.gz [root@django-web src]# cd mysqlclient-1.3.14/ [root@django-web mysqlclient-1.3.14]# python3 setup.py install
查看版本:
[root@django-web mysqlclient-1.3.14]# python3 -c "import MySQLdb; print(MySQLdb.version_info)" (1, 3, 14, 'final', 0) [root@django-web mysqlclient-1.3.14]#
mysqlclient安裝完成。
下載源碼包:
[root@django-web ~]# wget wget https://www.djangoproject.com/m/releases/2.1/Django-2.1.5.tar.gz -P /usr/local/src/
解壓源碼包並進入源碼目錄,執行安裝:
[root@django-web ~]# cd /usr/local/src/ [root@django-web src]# [root@django-web src]# ll total 30876 -rw-r--r-- 1 root root 8612384 Jan 4 13:47 Django-2.1.5.tar.gz drwxrwxr-x 9 1000 1000 4096 Jan 16 17:16 mysqlclient-1.3.14 -rw-r--r-- 1 root root 91391 Dec 4 10:06 mysqlclient-1.3.14.tar.gz drwxr-xr-x 19 501 501 4096 Jan 16 17:05 Python-3.7.2 -rw-r--r-- 1 root root 22897802 Dec 24 03:42 Python-3.7.2.tgz [root@django-web src]# [root@django-web src]# tar axf Django-2.1.5.tar.gz [root@django-web src]# cd Django-2.1.5/ [root@django-web Django-2.1.5]# python3 setup.py install
查看版本:
[root@django-web Django-2.1.5]# python3 -m django --version 2.1.5 [root@django-web Django-2.1.5]#
安裝成功後,將生成用於django項目管理的命令行工具django-admin:
[root@django-web Django-2.1.5]# which django-admin /usr/local/bin/django-admin [root@django-web Django-2.1.5]#
運行django-admin startproject命令,在指定目錄中(本例中爲/opt/webs/t_django)建立django項目:
django-admin startproject命令的格式爲:django-admin startproject 項目名 [目標目錄]
項目名是必選參數,目標目錄是可選參數,若忽略,則在當前目錄下建立一個與項目名同名的目錄。
[root@django-web Django-2.1.5]# cd [root@django-web ~]# [root@django-web ~]# mkdir -p /opt/webs/t_django [root@django-web ~]# django-admin startproject t_app /opt/webs/t_django [root@django-web ~]# [root@django-web ~]# tree /opt/webs/t_django/ /opt/webs/t_django/ ├── manage.py └── t_app ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py 1 directory, 5 files [root@django-web ~]#
以上顯示的目錄層級結構中,/opt/webs/下的t_djang爲項目頂級目錄,該目錄下包含一個用於管理當前項目的manage.py程序,與一個python包(目錄);該項目包內的settings.py用於配置當前項目的各項參數,urls.py用於定義當前項目的url路徑,wsgi.py爲web訪問的入口。
爲當前django項目建立單獨的數據庫以及相應的用戶(本例中,數據庫名稱爲t_django_db,用戶名爲u_django,密碼爲p_django):
步驟3.1中已添加root用戶在192.168.9.%網段的登陸權限。
在非mysql服務器所在主機上,運行mysql命令行客戶端須要安裝mysql軟件包:yum -y install mysql
[root@django-web ~]# mysql -h192.168.9.130 -P3306 -uroot -pdjango -e "create database t_django_db; grant all privileges on t_django_db.* to u_django@'192.168.9.129' identified by 'p_django';"
編輯項目配置文件settings.py,進行如下修改:
[root@django-web ~]# cd /opt/webs/t_django/ [root@django-web t_django]# ll total 4 -rwxr-xr-x 1 root root 537 Jan 16 17:33 manage.py drwxr-xr-x 2 root root 74 Jan 16 17:33 t_app [root@django-web t_django]# [root@django-web t_django]# [root@django-web t_django]# [root@django-web t_django]# cp -a t_app/settings.py{,.ori} [root@django-web t_django]# [root@django-web t_django]# sed -n '/^ALLOWED_HOSTS/p' t_app/settings.py ALLOWED_HOSTS = [] [root@django-web t_django]# sed -i '/^ALLOWED_HOSTS/ s|\[\]|\['\''*'\''\]|' t_app/settings.py [root@django-web t_django]# [root@django-web t_django]# sed -n '/^ALLOWED_HOSTS/p' t_app/settings.py ALLOWED_HOSTS = ['*'] [root@django-web t_django]#
[root@django-web t_django]# sed -i '/ENGINE/ s/sqlite3/mysql/' t_app/settings.py [root@django-web t_django]# sed -i '/ENGINE/{n;d}' t_app/settings.py [root@django-web t_django]# sed -i -e '/ENGINE/ a\ '\''HOST'\'': '\''192.168.9.130'\'',\n '\''PORT'\'': '\''3306'\'',\n '\''NAME'\'': '\''t_django_db'\'',\n '\''USER'\'': '\''u_django'\'',\n '\''PASSWORD'\'': '\''p_django'\'',\n '\''TIME_ZONE'\'': '\''Asia/Shanghai'\'',\n '\''USE_TZ'\'': False' t_app/settings.py
修改前:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
修改後:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '192.168.9.130', 'PORT': '3306', 'NAME': 't_django_db', 'USER': 'u_django', 'PASSWORD': 'p_django', 'TIME_ZONE': 'Asia/Shanghai', 'USE_TZ': False } }
[root@django-web t_django]# sed -i '$a\STATIC_ROOT = os.path.join(BASE_DIR, '\''static'\'')' t_app/settings.py [root@django-web t_django]# [root@django-web t_django]# sed -n '$p' t_app/settings.py STATIC_ROOT = os.path.join(BASE_DIR, 'static')
運行python3 manage.py collectstatic命令,收集靜態文件:
該命令在當前django項目的頂級目錄/opt/webs/t_django下建立靜態文件目錄/static/
[root@django-web t_django]# pwd /opt/webs/t_django [root@django-web t_django]# ll total 4 -rwxr-xr-x 1 root root 537 Jan 16 17:33 manage.py drwxr-xr-x 2 root root 97 Jan 16 17:57 t_app [root@django-web t_django]# [root@django-web t_django]# python3 manage.py collectstatic 119 static files copied to '/opt/webs/t_django/static'. [root@django-web t_django]# [root@django-web t_django]# ll total 4 -rwxr-xr-x 1 root root 537 Jan 16 17:33 manage.py drwxr-xr-x 3 root root 19 Jan 16 17:59 static drwxr-xr-x 3 root root 116 Jan 16 17:59 t_app [root@django-web t_django]# [root@django-web t_django]# du -sh static/ 1.7M static/ [root@django-web t_django]#
鏈接數據庫並建立相應的表:
[root@django-web t_django]# mysql -h192.168.9.130 -P3306 -uu_django -pp_django -Dt_django_db -e "show tables;" [root@django-web t_django]# [root@django-web t_django]# python3 manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK [root@django-web t_django]# mysql -h192.168.9.130 -P3306 -uu_django -pp_django -Dt_django_db -e "show tables;" +----------------------------+ | Tables_in_t_django_db | +----------------------------+ | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ [root@django-web t_django]# [root@django-web t_django]# ss -atn | grep :3306 ESTAB 0 0 192.168.9.129:44518 192.168.9.130:3306 [root@django-web t_django]#
運行python3 manage.py runserver 0:8000命令,以tcp的8000端口啓動django內置的web服務器:
內置的web服務器初始化須要幾秒鐘。
[root@django-web t_django]# python3 manage.py runserver 0:8000 & [1] 30910 [root@django-web t_django]# Performing system checks... System check identified no issues (0 silenced). January 16, 2019 - 18:06:19 Django version 2.1.5, using settings 't_app.settings' Starting development server at http://0:8000/ Quit the server with CONTROL-C. [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 [root@django-web t_django]# ss -atn | grep :8000 LISTEN 0 10 *:8000 *:*
待8000端口處於LISTEN狀態後,瀏覽器分別訪問http://192.168.9.129:8000/與http://192.168.9.129:8000/admin,若顯示如下頁面,則說明設置成功:
終端輸出的訪問日誌:
[16/Jan/2019 18:08:26] "GET / HTTP/1.1" 200 16348 [16/Jan/2019 18:08:26] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423 Not Found: /favicon.ico [16/Jan/2019 18:08:26] "GET /favicon.ico HTTP/1.1" 404 1975 [16/Jan/2019 18:08:26] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 200 80304 [16/Jan/2019 18:08:26] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 200 82564 [16/Jan/2019 18:08:26] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 200 81348 [16/Jan/2019 18:08:31] "GET /admin HTTP/1.1" 301 0 [16/Jan/2019 18:08:31] "GET /admin/ HTTP/1.1" 302 0 [16/Jan/2019 18:08:31] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 1819 [16/Jan/2019 18:08:32] "GET /static/admin/css/responsive.css HTTP/1.1" 200 17976 [16/Jan/2019 18:08:32] "GET /static/admin/css/base.css HTTP/1.1" 200 16225 [16/Jan/2019 18:08:32] "GET /static/admin/css/login.css HTTP/1.1" 200 1203
Django環境的安裝與初始配置完成。
[root@django-web ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}' 192.168.9.129/24 [root@django-web ~]#
安裝依賴包:
[root@django-web ~]# yum -y install expat-devel pcre-devel
下載apr,apr-util,httpd,mod_wsgi源碼包:
[root@django-web ~]# wget \ > http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-1.6.5.tar.gz \ > http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-util-1.6.1.tar.gz \ > http://mirrors.hust.edu.cn/apache//httpd/httpd-2.4.37.tar.gz \ > https://files.pythonhosted.org/packages/47/69/5139588686eb40053f8355eba1fe18a8bee94dc3efc4e36720c73e07471a/mod_wsgi-4.6.5.tar.gz \ > -P /usr/local/src/
解壓apr源碼包並進入源碼目錄,執行安裝:
源碼安裝apr的默認目標路徑爲/usr/local,能夠經過configure命令的--prefix選項顯式指定。
[root@django-web ~]# cd /usr/local/src/ [root@django-web src]# [root@django-web src]# ll total 41920 -rw-r--r-- 1 root root 1073556 Sep 14 04:07 apr-1.6.5.tar.gz -rw-r--r-- 1 root root 554301 Oct 22 2017 apr-util-1.6.1.tar.gz drwxr-xr-x 12 1000 1000 4096 Jan 16 17:31 Django-2.1.5 -rw-r--r-- 1 root root 8612384 Jan 4 13:47 Django-2.1.5.tar.gz -rw-r--r-- 1 root root 9177278 Oct 22 14:13 httpd-2.4.37.tar.gz -rw-r--r-- 1 root root 490018 Oct 22 04:03 mod_wsgi-4.6.5.tar.gz drwxrwxr-x 9 1000 1000 4096 Jan 16 17:16 mysqlclient-1.3.14 -rw-r--r-- 1 root root 91391 Dec 4 10:06 mysqlclient-1.3.14.tar.gz drwxr-xr-x 19 501 501 4096 Jan 16 17:05 Python-3.7.2 -rw-r--r-- 1 root root 22897802 Dec 24 03:42 Python-3.7.2.tgz [root@django-web src]# [root@django-web src]# [root@django-web src]# tar axf apr-1.6.5.tar.gz [root@django-web src]# cd apr-1.6.5/ [root@django-web apr-1.6.5]# ./configure && make && make install
解壓apr-util源碼包並進入源碼目錄,執行安裝:
以configure命令的--with-apr選項指定已安裝的apr所在的目錄。
[root@django-web apr-1.6.5]# cd .. [root@django-web src]# tar axf apr-util-1.6.1.tar.gz [root@django-web src]# cd apr-util-1.6.1/ [root@django-web apr-util-1.6.1]# ./configure --with-apr=/usr/local/apr && make && make install
解壓httpd源碼包並進入源碼目錄,執行安裝:
源碼安裝httpd的默認目標路徑爲/usr/local,能夠經過configure命令的--prefix選項顯式指定。
[root@django-web apr-util-1.6.1]# cd .. [root@django-web src]# tar axf httpd-2.4.37.tar.gz [root@django-web src]# cd httpd-2.4.37/ [root@django-web httpd-2.4.37]# ./configure \ > --with-apr=/usr/local/apr/ \ > --with-apr-util=/usr/local/apr/ \ > --enable-mpms-shared=all && make -j2 && make install
將apache可執行文件的路徑(本例爲/usr/local/apache2/bin)添加至系統的查找路徑列表PATH中:
[root@django-web httpd-2.4.37]# ls /usr/local/apache2/ bin build cgi-bin conf error htdocs icons include logs man manual modules [root@django-web httpd-2.4.37]# ls /usr/local/apache2/bin/ ab apxs dbmmanage envvars-std htcacheclean htdigest httpd logresolve apachectl checkgid envvars fcgistarter htdbm htpasswd httxt2dbm rotatelogs [root@django-web httpd-2.4.37]# [root@django-web httpd-2.4.37]# which apachectl /usr/bin/which: no apachectl in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) [root@django-web httpd-2.4.37]# [root@django-web httpd-2.4.37]# sed -i '/^PATH/ s|$|:/usr/local/apache2/bin|' ~/.bash_profile [root@django-web httpd-2.4.37]# source ~/.bash_profile [root@django-web httpd-2.4.37]# which apachectl /usr/local/apache2/bin/apachectl [root@django-web httpd-2.4.37]# [root@django-web httpd-2.4.37]# apachectl -v Server version: Apache/2.4.37 (Unix) Server built: Jan 17 2019 22:35:36 [root@django-web httpd-2.4.37]#
解壓mod_wsgi源碼包並進入源碼目錄,執行安裝:
configure命令的--with-apxs與--with-python選項分別指定apache的apxs與python可執行文件的路徑。
[root@django-web httpd-2.4.37]# cd .. [root@django-web src]# tar axf mod_wsgi-4.6.5.tar.gz [root@django-web src]# cd mod_wsgi-4.6.5/ [root@django-web mod_wsgi-4.6.5]# ./configure \ > --with-python=/usr/local/bin/python3 \ > --with-apxs=/usr/local/apache2/bin/apxs && \ > make -j && make install
建立用於運行apache的web用戶與組(本例中爲www):
[root@django-web mod_wsgi-4.6.5]# cd [root@django-web ~]# id www id: www: no such user [root@django-web ~]# useradd www -s /sbin/nologin [root@django-web ~]# id www uid=1000(www) gid=1000(www) groups=1000(www) [root@django-web ~]#
編輯apache主配置文件(本例中爲/usr/local/apache2/conf/httpd.conf),執行如下修改:
[root@django-web ~]# ll /usr/local/apache2/conf/httpd.conf -rw-r--r-- 1 root root 18541 Jan 17 13:57 /usr/local/apache2/conf/httpd.conf [root@django-web ~]# [root@django-web ~]# cp -a /usr/local/apache2/conf/httpd.conf{,.ori} [root@django-web ~]# [root@django-web ~]# sed -n '/^User\|^Group/p' /usr/local/apache2/conf/httpd.conf User daemon Group daemon [root@django-web ~]# sed -i '/^User\|^Group/ s/daemon/www/' /usr/local/apache2/conf/httpd.conf [root@django-web ~]# [root@django-web ~]# sed -n '/^User\|^Group/p' /usr/local/apache2/conf/httpd.conf User www Group www [root@django-web ~]#
[root@django-web ~]# sed -n '/ServerName/p' /usr/local/apache2/conf/httpd.conf # ServerName gives the name and port that the server uses to identify itself. #ServerName www.example.com:80 [root@django-web ~]# [root@django-web ~]# sed -i '/^#ServerName/a\ServerName localhost:80' /usr/local/apache2/conf/httpd.conf [root@django-web ~]# [root@django-web ~]# sed -n '/ServerName/p' /usr/local/apache2/conf/httpd.conf # ServerName gives the name and port that the server uses to identify itself. #ServerName www.example.com:80 ServerName localhost:80 [root@django-web ~]#
默認的文檔根目錄爲/usr/local/apache2/htdocs,首頁爲index.html
[root@django-web ~]# sed -n '/^DocumentRoot/p' /usr/local/apache2/conf/httpd.conf DocumentRoot "/usr/local/apache2/htdocs" [root@django-web ~]# [root@django-web ~]# ll /usr/local/apache2/htdocs/ total 4 -rw-r--r-- 1 root 40 45 Jun 11 2007 index.html [root@django-web ~]#
測試配置文件語法,若無誤則啓動apache:
[root@django-web ~]# apachectl configtest Syntax OK [root@django-web ~]# apachectl [root@django-web ~]# [root@django-web ~]# ss -atn | grep :80 LISTEN 0 10 *:8000 *:* ESTAB 0 0 192.168.9.129:8000 192.168.9.1:58666 ESTAB 0 0 192.168.9.129:8000 192.168.9.1:58665 ESTAB 0 0 192.168.9.129:8000 192.168.9.1:58667 ESTAB 0 0 192.168.9.129:8000 192.168.9.1:58663 LISTEN 0 128 :::80 :::* [root@django-web ~]#
瀏覽器訪問http://192.168.9.129/,若頁面顯示"It works!",則說明配置成功。
apache做爲wsgi前端時,mod_wsgi能夠配置爲兩種工做模式(mode):
對於非Windows平臺,Django官方文檔中推薦使用守護進程模式。
內嵌模式的基本配置包括:
爲django項目建立單獨的文檔根目錄與虛擬主機配置文件(本例中分別爲/opt/webs/documents與/usr/local/apache2/conf/extra/httpd-django.conf):
Django自身並不提供文件服務,而是交由前端的web服務器處理;對於url路徑到本地路徑的映射,Apache經過server/virtual host/directory上下文中的Alias指令指定,而Nginx則經過location塊中的alias指令指定。
[root@django-web ~]# mkdir -p /opt/webs/documents [root@django-web ~]# vi /usr/local/apache2/conf/extra/httpd-django.conf WSGIPythonPath /opt/webs/t_django <VirtualHost *:80> ServerName localhost:80 DocumentRoot /opt/webs/documents LoadModule wsgi_module modules/mod_wsgi.so WSGIScriptAlias / /opt/webs/t_django/t_app/wsgi.py Alias /static/ /opt/webs/t_django/static/ <Directory /opt/webs/t_django> Require all granted </Directory> </VirtualHost>
在apache主配置文件中包含django虛擬主機配置文件:
[root@django-web ~]# sed -i '$a\Include conf/extra/httpd-django.conf' /usr/local/apache2/conf/httpd.conf [root@django-web ~]# sed -n '$p' /usr/local/apache2/conf/httpd.conf Include conf/extra/httpd-django.conf [root@django-web ~]#
測試配置文件並從新加載:
[root@django-web ~]# apachectl configtest Syntax OK [root@django-web ~]# [root@django-web ~]# apachectl graceful [root@django-web ~]# [root@django-web ~]# apachectl -M | grep wsgi wsgi_module (shared) [root@django-web ~]# [root@django-web ~]# ss -atn | grep :80 LISTEN 0 10 *:8000 *:* LISTEN 0 128 :::80 :::* [root@django-web ~]#
瀏覽器訪問http://192.168.9.129/與http://192.168.9.129/admin,若頁面顯示與步驟3.2.3中相同,則說明內嵌模式配置成功。
查看訪問日誌:
[root@django-web ~]# tail -f /usr/local/apache2/logs/access_log 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /admin HTTP/1.1" 301 - 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /admin/ HTTP/1.1" 302 - 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 1819 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/css/base.css HTTP/1.1" 200 16225 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/css/login.css HTTP/1.1" 200 1203 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/css/responsive.css HTTP/1.1" 200 17976 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 200 81348 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 200 80304 192.168.9.1 - - [17/Jan/2019:15:58:48 +0000] "GET /favicon.ico HTTP/1.1" 404 1970 192.168.9.1 - - [17/Jan/2019:16:00:20 +0000] "GET / HTTP/1.1" 200 16348 192.168.9.1 - - [17/Jan/2019:16:00:20 +0000] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 200 82564
守護進程模式的基本配置包括:
<code class="language-apache">[root@django-web ~]# cp -a /usr/local/apache2/conf/extra/httpd-django.conf /usr/local/apache2/conf/extra/httpd-django-embedded.conf [root@django-web ~]# [root@django-web ~]# vi /usr/local/apache2/conf/extra/httpd-django.conf <VirtualHost *:80> ServerName localhost:80 DocumentRoot /opt/webs/documents LoadModule wsgi_module modules/mod_wsgi.so WSGIProcessGroup t_app WSGIDaemonProcess t_app python-path=/opt/webs/t_django WSGIScriptAlias / /opt/webs/t_django/t_app/wsgi.py process-group=t_app Alias /static/ /opt/webs/t_django/static/ <Directory /opt/webs/t_django> Require all granted </Directory> </VirtualHost>
[root@django-web ~]# [root@django-web ~]# apachectl configtest Syntax OK [root@django-web ~]# apachectl [root@django-web ~]# ps aux | grep http | grep -v grep root 60941 0.0 0.2 85860 2820 ? Ss 01:02 0:00 /usr/local/apache2/bin/httpd www 60942 0.2 0.7 464672 7008 ? Sl 01:02 0:00 /usr/local/apache2/bin/httpd www 60943 0.2 0.9 483100 9148 ? Sl 01:02 0:00 /usr/local/apache2/bin/httpd www 60944 0.2 0.9 483100 9148 ? Sl 01:02 0:00 /usr/local/apache2/bin/httpd www 60945 0.1 0.9 483100 9144 ? Sl 01:02 0:00 /usr/local/apache2/bin/httpd [root@django-web ~]# pstree -a 60941 httpd ├─httpd │ └─17*[{httpd}] ├─httpd │ └─26*[{httpd}] ├─httpd │ └─26*[{httpd}] └─httpd └─26*[{httpd}]
apache根據多進程處理模塊(MPM, Multi-Processing Module)中指定的工做模式(prefork/worker/event)分配資源以處理請求,通常會預先分配若干進程或進程+線程,具體依賴於特定的模式以及相應的參數配置。根據tree命令與ps命令的輸出能夠看到,apache主進程60941以root啓動後,預分配了4個以www運行的子進程(60942/60943/60944/60945),每個子進程又各自包含若干線程。
[root@django-web ~]# apachectl -V Server version: Apache/2.4.37 (Unix) Server built: Jan 17 2019 22:35:36 Server's Module Magic Number: 20120211:83 Server loaded: APR 1.6.5, APR-UTIL 1.6.1 Compiled using: APR 1.6.5, APR-UTIL 1.6.1 Architecture: 64-bit Server MPM: event threaded: yes (fixed thread count) forked: yes (variable process count) Server compiled with.... -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=256 -D HTTPD_ROOT="/usr/local/apache2" -D SUEXEC_BIN="/usr/local/apache2/bin/suexec" -D DEFAULT_PIDLOG="logs/httpd.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf"
從apachectl -V命令的輸出能夠看出,當前使用的event MPM,且爲多進程+多線程方式;但此時沒法區分mod_wsgi與apache的其餘子進程;WSGIDaemonProcess指令的display-name選項爲進程組指定名稱,經過自定義字符串加以區分,若指定爲display-name=%{GROUP},則mod_wsgi進程將顯示爲(wsgi:進程組名稱)。
添加display-name:
[root@django-web ~]# vi /usr/local/apache2/conf/extra/httpd-django.conf <VirtualHost *:80> ServerName localhost:80 DocumentRoot /opt/webs/documents LoadModule wsgi_module modules/mod_wsgi.so WSGIProcessGroup t_app WSGIDaemonProcess t_app python-path=/opt/webs/t_django display-name=%{GROUP} WSGIScriptAlias / /opt/webs/t_django/t_app/wsgi.py process-group=t_app Alias /static/ /opt/webs/t_django/static/ <Directory /opt/webs/t_django> Require all granted </Directory> </VirtualHost> [root@django-web ~]# [root@django-web ~]# apachectl configtest Syntax OK [root@django-web ~]# apachectl graceful [root@django-web ~]# [root@django-web ~]# ps aux | grep http | grep -v grep root 60941 0.0 0.3 85860 3864 ? Ss 01:02 0:00 /usr/local/apache2/bin/httpd www 61089 0.0 0.9 483100 9148 ? Sl 01:18 0:00 /usr/local/apache2/bin/httpd www 61090 0.0 0.9 483100 9144 ? Sl 01:18 0:00 /usr/local/apache2/bin/httpd www 61091 0.0 0.9 483100 9148 ? Sl 01:18 0:00 /usr/local/apache2/bin/httpd [root@django-web ~]# [root@django-web ~]# pstree -a 60941 httpd ├─httpd │ └─17*[{httpd}] ├─httpd │ └─26*[{httpd}] ├─httpd │ └─26*[{httpd}] └─httpd └─26*[{httpd}] [root@django-web ~]# ps aux | grep t_app www 61088 0.0 0.7 464656 7020 ? Sl 01:18 0:00 (wsgi:t_app) root 61195 0.0 0.0 112708 976 pts/0 S+ 01:19 0:00 grep --color=auto t_app [root@django-web ~]# [root@django-web ~]# ps -p 61088 -o pid,ppid,args PID PPID COMMAND 61088 60941 (wsgi:t_app) [root@django-web ~]#
從以上輸出能夠看出,ps aux | grep http僅顯示了4個進程,包括一個以root用戶啓動的主進程以及3個以www用戶運行的子進程;另外一個預先分配的子進程被wsgi進程佔據,仍做爲httpd的子進程,但顯示爲(wsgi:t_app)。
守護進程模式的wsgi經過unix域套接字的方式與apache主進程通訊;unix域套接字爲本地文件,對於Apache + mod_wsgi,該文件通常位於apache的logs目錄下,能夠在配置文件的server上下文中,經過WSGISocketPrefix指令指定爲其餘目錄;mod_wsgi官方文檔中建議該指令指定的目錄應僅對root用戶或apache的運行時用戶可寫。
[root@django-web ~]# ll /usr/local/apache2/logs/ total 12 -rw-r--r-- 1 root root 655 Jan 17 22:41 access_log -rw-r--r-- 1 root root 2112 Jan 18 01:18 error_log -rw-r--r-- 1 root root 6 Jan 18 01:18 httpd.pid srwx------ 1 www root 0 Jan 18 01:18 wsgi.60941.1.1.sock [root@django-web ~]# [root@django-web ~]# file /usr/local/apache2/logs/wsgi.60941.1.1.sock /usr/local/apache2/logs/wsgi.60941.1.1.sock: socket
Apache + mod_wsgi基本配置完成,更多參數配置可查看官方文檔。
Nginx + uwsgi做爲django前端時,Nginx起到的做用更多仍在於反向代理服務器,在邏輯架構上能夠與具體的後端應用相分離,而uwsgi做爲實現了wsgi協議的web服務器則以獨立的進程運行。Nginx自0.8.40版本開始提供對uwsgi的原生支持,uwsgi自身能夠指定經過本地unix域套接字或網絡套接字與Nginx進行通訊,且支持豐富的配置參數,整個服務框架相較於Apache + mod_wsgi的部署方式更加複雜與靈活。
[root@django-web ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}' 192.168.9.129/24 [root@django-web ~]#
安裝依賴包:
[root@django-web ~]# yum -y install gcc make openssl-devel pcre-devel
下載nginx(本例使用tengine)與uwsgi源碼包:
[root@django-web ~]# wget \ > https://projects.unbit.it/downloads/uwsgi-2.0.17.1.tar.gz \ > http://tengine.taobao.org/download/tengine-2.2.3.tar.gz -P /usr/local/src/
解壓nginx源碼包並進入源碼目錄,執行安裝:
源碼安裝nginx的默認目標路徑爲/usr/local,能夠經過configure命令的--prefix選項顯式指定;--with-http_uwsgi_module=shared選項指定將uwsgi模塊以共享庫的方式安裝。
[root@django-web ~]# cd /usr/local/src/ [root@django-web src]# ll total 44084 drwxr-xr-x 28 1001 1001 4096 Jan 17 13:51 apr-1.6.5 -rw-r--r-- 1 root root 1073556 Sep 14 04:07 apr-1.6.5.tar.gz drwxr-xr-x 21 1001 1001 4096 Jan 17 13:53 apr-util-1.6.1 -rw-r--r-- 1 root root 554301 Oct 22 2017 apr-util-1.6.1.tar.gz drwxr-xr-x 12 www www 4096 Jan 16 17:31 Django-2.1.5 -rw-r--r-- 1 root root 8612384 Jan 4 13:47 Django-2.1.5.tar.gz drwxr-sr-x 12 root 40 4096 Jan 17 13:57 httpd-2.4.37 -rw-r--r-- 1 root root 9177278 Oct 22 14:13 httpd-2.4.37.tar.gz drwxr-xr-x 8 501 games 325 Jan 17 14:02 mod_wsgi-4.6.5 -rw-r--r-- 1 root root 490018 Oct 22 04:03 mod_wsgi-4.6.5.tar.gz drwxrwxr-x 9 www www 4096 Jan 16 17:16 mysqlclient-1.3.14 -rw-r--r-- 1 root root 91391 Dec 4 10:06 mysqlclient-1.3.14.tar.gz drwxr-xr-x 19 501 501 4096 Jan 16 17:05 Python-3.7.2 -rw-r--r-- 1 root root 22897802 Dec 24 03:42 Python-3.7.2.tgz -rw-r--r-- 1 root root 2203079 Jan 3 04:17 tengine-2.2.3.tar.gz -rw-r--r-- 1 root root 800156 Jul 8 2018 uwsgi-2.0.17.1.tar.gz [root@django-web src]# [root@django-web src]# tar axf tengine-2.2.3.tar.gz [root@django-web src]# cd tengine-2.2.3/ [root@django-web tengine-2.2.3]# [root@django-web tengine-2.2.3]# ./configure \ > --with-http_uwsgi_module=shared \ > --with-http_gzip_static_module \ > --with-http_concat_module \ > --with-http_stub_status_module \ > --with-http_ssl_module \ > --with-pcre \ > --with-backtrace_module \ > --with-http_upstream_check_module \ > --with-http_sysguard_module \ > --with-http_slice_module \ > --with-http_upstream_ip_hash_module=shared \ > --with-http_upstream_session_sticky_module=shared \ > --with-http_upstream_least_conn_module=shared && \ > make -j && make install
將nginx可執行文件的路徑(本例爲/usr/local/nginx/sbin)添加至系統的查找路徑列表PATH中:
[root@django-web tengine-2.2.3]# ls /usr/local/nginx/ conf html include logs modules sbin [root@django-web tengine-2.2.3]# ls /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx [root@django-web tengine-2.2.3]# which nginx /usr/bin/which: no nginx in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/apache2/bin) [root@django-web tengine-2.2.3]# [root@django-web tengine-2.2.3]# sed -i '/^PATH/ s|$|:/usr/local/nginx/sbin|' ~/.bash_profile [root@django-web tengine-2.2.3]# source ~/.bash_profile [root@django-web tengine-2.2.3]# which nginx /usr/local/nginx/sbin/nginx [root@django-web tengine-2.2.3]# nginx -v Tengine version: Tengine/2.2.3 (nginx/1.8.1) [root@django-web tengine-2.2.3]#
解壓uwsgi源碼包並進入源碼目錄,執行安裝:
[root@django-web tengine-2.2.3]# cd .. [root@django-web src]# tar axf uwsgi-2.0.17.1.tar.gz [root@django-web src]# cd uwsgi-2.0.17.1/ [root@django-web uwsgi-2.0.17.1]# python3 setup.py install
安裝成功後將生成uwsgi管理程序/usr/local/bin/uwsgi:
[root@django-web uwsgi-2.0.17.1]# which uwsgi /usr/local/bin/uwsgi [root@django-web uwsgi-2.0.17.1]# [root@django-web uwsgi-2.0.17.1]# uwsgi --version 2.0.17.1 [root@django-web uwsgi-2.0.17.1]#
以tcp套接字的方式啓動uwsgi:
--socket 127.0.0.1:8000 以tcp套接字的127.0.0.1:8000啓動
--uid/--gid 指定運行時的用戶與組
--master 守護進程方式運行
--pidfile 運行時的pid文件
--daemonize 守護進程方式的日誌輸出文件
--chdir 項目包所在的目錄
--module 項目包:入口文件:方法
[root@django-web ~]# uwsgi \ > --socket 127.0.0.1:8000 \ > --uid=www --gid=www \ > --master \ > --pidfile=/opt/webs/t_django/t_app.pid \ > --daemonize=/opt/webs/t_django/t_app.log \ > --chdir=/opt/webs/t_django \ > --module=t_app.wsgi:application \ > --processes=5 \ > --harakiri=20 \ > --max-requests=500 \ > --vacuum [root@django-web ~]# [root@django-web ~]# ss -atn | grep 8000 LISTEN 0 100 127.0.0.1:8000 *:* [root@django-web ~]#
查看日誌:
[root@django-web ~]# tail -f /opt/webs/t_django/t_app.log mapped 437520 bytes (427 KB) for 5 cores *** Operational MODE: preforking *** WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0xd8e280 pid: 65614 (default app) *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 65614) spawned uWSGI worker 1 (pid: 65615, cores: 1) spawned uWSGI worker 2 (pid: 65616, cores: 1) spawned uWSGI worker 3 (pid: 65617, cores: 1) spawned uWSGI worker 4 (pid: 65618, cores: 1) spawned uWSGI worker 5 (pid: 65619, cores: 1)
設置nginx將wsgi請求轉發至127.0.0.1:8000
Nginx轉發wsgi協議需經過wsgi_pass指令指定後端服務,且在location塊中包含定義了uwsgi相關參數的uwsgi_params文件。
[root@django-web ~]# mkdir -p /usr/local/nginx/conf/vhosts [root@django-web ~]# vi /usr/local/nginx/conf/vhosts/upstream.conf upstream t_django { server 127.0.0.1:8000; } [root@django-web ~]# vi /usr/local/nginx/conf/vhosts/t_django.conf server { listen 80; server_name 192.168.9.129; charset utf-8; client_max_body_size 75M; location /static { alias /opt/webs/t_django/static; } location / { include /usr/local/nginx/conf/uwsgi_params; uwsgi_pass t_django; uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; } access_log logs/t_django-access.log main; }
轉發wsgi須要加載ngx_http_uwsgi_module.so模塊,且在http上下文中包含以上兩個配置文件。
[root@django-web ~]# vi /usr/local/nginx/conf/nginx.conf user www www; worker_processes auto; pid /usr/local/nginx/logs/nginx.pid; error_log /usr/local/nginx/logs/error.log warn; #Specifies the value for maximum file descriptors that can be opened by this process. worker_rlimit_nofile 51200; events { use epoll; worker_connections 4096; } dso { load ngx_http_uwsgi_module.so; load ngx_http_upstream_ip_hash_module.so; load ngx_http_upstream_least_conn_module.so; load ngx_http_upstream_session_sticky_module.so; } http { include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 128; client_header_buffer_size 16k; large_client_header_buffers 4 32k; client_max_body_size 8m; access_log off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 30; proxy_cache_methods POST GET HEAD; open_file_cache max=655350 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; gzip on; gzip_min_length 1k; gzip_buffers 8 8k; gzip_http_version 1.0; gzip_comp_level 4; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php; gzip_vary on; server_tokens off; log_format main '$remote_addr\t$upstream_addr\t[$time_local]\t$request\t' '$status\t$body_bytes_sent\t$http_user_agent\t$http_referer\t' '$http_x_forwarded_for\t$request_time\t$upstream_response_time\t$remote_user\t' '$request_body'; map $http_upgrade $connection_upgrade { default upgrade; '' close; } include /usr/local/nginx/conf/vhosts/upstream.conf; include /usr/local/nginx/conf/vhosts/t_django.conf; }
配置文件語法測試無誤後,啓動nginx:
[root@django-web ~]# nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@django-web ~]# [root@django-web ~]# nginx [root@django-web ~]# [root@django-web ~]# ss -atn | grep 80 LISTEN 0 128 *:80 *:*
瀏覽器訪問http://192.168.9.129/與http://192.168.9.129/admin,若配置正確則應顯示步驟3.2.3中的頁面。
查看日誌:
[root@django-web ~]# tail -f /usr/local/nginx/logs/t_django-access.log 192.168.9.1 127.0.0.1:8000 [18/Jan/2019:03:13:36 +0000] GET / HTTP/1.1 200 4191 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 - -0.005 0.005 - - 192.168.9.1 - [18/Jan/2019:03:13:36 +0000] GET /static/admin/css/fonts.css HTTP/1.1 200 423 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0http://192.168.9.129/ - 0.000 - - - 192.168.9.1 - [18/Jan/2019:03:13:36 +0000] GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1 200 82564 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 http://192.168.9.129/static/admin/css/fonts.css - 0.000 - -- 192.168.9.1 - [18/Jan/2019:03:13:36 +0000] GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1 200 80304 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 http://192.168.9.129/static/admin/css/fonts.css - 0.000 --- 192.168.9.1 - [18/Jan/2019:03:13:36 +0000] GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1 200 81348 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 http://192.168.9.129/static/admin/css/fonts.css - 0.000 --- 192.168.9.1 127.0.0.1:8000 [18/Jan/2019:03:13:40 +0000] GET /admin/ HTTP/1.1 302 0Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 - -0.002 0.002 - - 192.168.9.1 127.0.0.1:8000 [18/Jan/2019:03:13:40 +0000] GET /admin/login/?next=/admin/ HTTP/1.1 200 781 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 - - 0.010 0.010 - - 192.168.9.1 - [18/Jan/2019:03:13:40 +0000] GET /static/admin/css/responsive.css HTTP/1.1 200 3580 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 http://192.168.9.129/admin/login/?next=/admin/ - 0.000 - - - 192.168.9.1 - [18/Jan/2019:03:13:40 +0000] GET /static/admin/css/base.css HTTP/1.1 200 3949 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0http://192.168.9.129/admin/login/?next=/admin/ - 0.000 - - - 192.168.9.1 - [18/Jan/2019:03:13:40 +0000] GET /static/admin/css/login.css HTTP/1.1 200 502 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0http://192.168.9.129/admin/login/?next=/admin/ - 0.000 - - -
中止綁定至tcp 8000端口的uwsgi,而以unix域套接字的方式啓動:
[root@django-web ~]# uwsgi --stop /opt/webs/t_django/t_app.pid [root@django-web ~]# uwsgi \ > --socket /tmp/t_app.sock \ > --uid=www --gid=www \ > --master \ > --pidfile=/opt/webs/t_django/t_app.pid \ > --daemonize=/opt/webs/t_django/t_app.log \ > --chdir=/opt/webs/t_django \ > --module=t_app.wsgi:application \ > --processes=5 \ > --harakiri=20 \ > --max-requests=500 \ > --vacuum [root@django-web ~]# tail -f /opt/webs/t_django/t_app.log uwsgi socket 0 bound to UNIX address /tmp/t_app.sock fd 3 Python version: 3.7.2 (default, Jan 17 2019, 22:21:08) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] *** Python threads support is disabled. You can enable it with --enable-threads *** Python main interpreter initialized at 0xccdda0 your server socket listen backlog is limited to 100 connections your mercy for graceful operations on workers is 60 seconds mapped 437520 bytes (427 KB) for 5 cores *** Operational MODE: preforking *** WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0xccdda0 pid: 69293 (default app) *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 69293) spawned uWSGI worker 1 (pid: 69294, cores: 1) spawned uWSGI worker 2 (pid: 69295, cores: 1) spawned uWSGI worker 3 (pid: 69296, cores: 1) spawned uWSGI worker 4 (pid: 69297, cores: 1) spawned uWSGI worker 5 (pid: 69298, cores: 1)
本地unix域套接字已被建立:
[root@django-web ~]# ll /tmp/t_app.sock srwxrwxrwx 1 www www 0 Jan 18 03:25 /tmp/t_app.sock [root@django-web ~]#
將nginx的upstream由127.0.0.1:8000改成unix:/tmp/t_app.sock並從新加載nginx配置文件:
[root@django-web ~]# sed -n '/server/p' /usr/local/nginx/conf/vhosts/upstream.conf server 127.0.0.1:8000; [root@django-web ~]# [root@django-web ~]# sed -i '/server/ s|127.0.0.1:8000|unix:/tmp/t_app.sock|' /usr/local/nginx/conf/vhosts/upstream.conf [root@django-web ~]# [root@django-web ~]# sed -n '/server/p' /usr/local/nginx/conf/vhosts/upstream.conf server unix:/tmp/t_app.sock; [root@django-web ~]# [root@django-web ~]# nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@django-web ~]# [root@django-web ~]# nginx -s reload [root@django-web ~]#
瀏覽器再次訪問http://192.168.9.129/與http://192.168.9.129/admin,並查看日誌:
[root@django-web ~]# tail -f /usr/local/nginx/logs/t_django-access.log 192.168.9.1 unix:/tmp/t_app.sock [18/Jan/2019:03:33:44 +0000] GET / HTTP/1.1 200 4191 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 --0.038 0.038 - - 192.168.9.1 - [18/Jan/2019:03:33:44 +0000] GET /static/admin/css/fonts.css HTTP/1.1 304 0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0http://192.168.9.129/ - 0.000 - - - 192.168.9.1 unix:/tmp/t_app.sock [18/Jan/2019:03:33:49 +0000] GET /admin/ HTTP/1.1 302 0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0- - 0.013 0.013 - - 192.168.9.1 unix:/tmp/t_app.sock [18/Jan/2019:03:33:49 +0000] GET /admin/login/?next=/admin/ HTTP/1.1 200 781 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0 - - 0.080 0.080 - -
Nginx + uwsgi基本配置完成,更多參數配置可查看官方文檔。
如下腳本將上述步驟簡單封裝爲腳本,分爲兩個文件:
用法:將兩個文件放在同一目錄下,根據須要實現的組件安裝與配置,在django-setup.sh中添加相應的函數調用。建議以nohup後臺的方式執行,並將輸出重定向至指定的日誌文件,能夠避免因終端關閉致使的運行意外終止狀況,且能夠經過刷新日誌文件查看運行過程與結果,例如:
nohup ./django-setup.sh &> /tmp/django-apache-daemon.log &
django-environment.sh腳本文件:
#! /bin/bash # 函數列表 #install_common_dependencies #install_python3_dependencies #install_mysqlclient_dependencies #install_apache_dependencies #install_nginx_dependencies #install_mysql_dependencies #make_source #path_not_exists #install_python3 #install_mysqlclient #install_apache #install_nginx #install_uwsgi #install_django #django_basic_setup #apache_djange_daemon_mode #install_setup_mysql readonly SOURCE_DIR="/usr/local/src" readonly USER_PROFILE="${HOME}/.bash_profile" readonly DEFAULT_LIB_CONF="/etc/ld.so.conf" readonly DJANGO_PROJECT_DIR="/opt/webs/t_django" readonly DJANGO_APP="t_app" readonly WEB_USER="www" readonly WEB_GROUP="www" readonly WEB_USER_SHELL="/sbin/nologin" install_common_dependencies() { yum -y install gcc make } install_python3_dependencies() { yum -y install libffi-devel readline-devel zlib-devel openssl-devel } install_mysqlclient_dependencies() { yum -y install mysql-devel } install_apache_dependencies() { yum -y install expat-devel pcre-devel } install_nginx_dependencies() { yum -y install openssl-devel pcre-devel } install_mysql_dependencies() { yum -y install gcc-c++ cmake ncurses-devel openssl-devel } #多核編譯 make_source() { local CPU_CORES=$(awk '/^processor/{print $3}' /proc/cpuinfo | wc -l) local OPTIONS="$@" make -j ${CPU_CORES} ${OPTIONS} make install } # 檢查第1個參數指定的路徑是否位於系統環境變量PATH中,若不存在則返回0,反之則返回1 path_not_exists() { [[ ${1} != "" && ${1} != " " ]] && local PATH_ELEM=${1} || return 0 local OLD_IFS="${IFS}" local IFS=":" local PATH_LIST=($PATH) IFS=${OLD_IFS} for i in ${PATH_LIST[@]}; do [[ ${i} == ${PATH_ELEM} ]] && return 1 done return 0 } # 安裝python3解析器 install_python3() { local PYTHON_BIN="/usr/local/bin/python3" [[ -x ${PYTHON_BIN} ]] && \ { echo "python3已存在,請檢查當前版本"; return 0; } echo "開始安裝python3解析器" local PYTHON_BIN_DIR="$(dirname ${PYTHON_BIN})" local PYTHON_LIB_CONF="/etc/ld.so.conf.d/python-v3.7.2.conf" local PYTHON_LINK="/usr/bin/python3" install_python3_dependencies # python3安裝的目標路徑爲--prefix選項顯式指定的目錄,或默認的/usrl/local/bin目錄 # 若使用默認路徑,則與之相關的共享庫位於/usr/local/lib目錄 cd ${SOURCE_DIR} tar xaf Python-3.7.2.tgz cd Python-3.7.2/ ./configure --enable-shared --enable-optimizations make_source -Wno-error=coverage-mismatch echo "python3解析器安裝成功" # 將python3的共享庫目錄/usr/local/lib添加到系統共享庫查找路徑列表的配置文件中 [[ ! -f ${PYTHON_LIB_CONF} ]] && \ echo '/usr/local/lib' > ${PYTHON_LIB_CONF} || \ echo '/usr/local/lib' >> ${DEFAULT_LIB_CONF} ldconfig # 若python3可執行文件的路徑不在PATH中,則添加 path_not_exists "${PYTHON_BIN_DIR}" && \ sed -i "/^PATH/s|$|:${PYTHON_BIN_DIR}|" ${USER_PROFILE}; source ${USER_PROFILE} # 建立python3可執行文件的符號連接 [[ ! -L ${PYTHON_LINK} ]] && \ ln -s ${PYTHON_BIN} ${PYTHON_LINK} } install_mysqlclient() { python3 -c "import MySQLdb; print(MySQLdb.version_info)" &> /dev/null && \ { echo "mysqlclient已存在,請檢查當前版本"; return 0; } install_mysqlclient_dependencies cd ${SOURCE_DIR} tar xaf mysqlclient-1.3.14.tar.gz cd mysqlclient-1.3.14/ python3 setup.py install echo "mysqlclient安裝成功" } # 安裝apache web環境,包括apr,apr-util,apache httpd,mod_wsgi模塊 install_apache() { local APACHE_BIN="/usr/local/apache2/bin/httpd" # apr,apache安裝的目標路徑爲--prefix選項顯式指定的目錄,或默認的/usrl/local/apr與/usrl/local/apache2目錄 # 對於apache,若使用默認目標路徑,則可執行文件的目錄爲/usrl/local/apache2/bin if [[ ! -x ${APACHE_BIN} ]]; then install_apache_dependencies local APR_BIN="/usr/local/apr/bin/apr-1-config" if [[ ! -x ${APR_BIN} ]]; then echo "開始安裝apr" cd ${SOURCE_DIR} tar xaf apr-1.6.5.tar.gz cd apr-1.6.5/ ./configure make_source echo "apr安裝成功" else echo "apr已存在,請檢查當前版本" fi local APU_BIN="/usr/local/apr/bin/apu-1-config" if [[ ! -x ${APU_BIN} ]]; then echo "開始安裝apr-util" cd ${SOURCE_DIR} tar xaf apr-util-1.6.1.tar.gz cd apr-util-1.6.1/ ./configure --with-apr=/usr/local/apr make_source echo "apr-util安裝成功" else echo "apr-util已存在,請檢查當前版本" fi echo "開始安裝apache" cd ${SOURCE_DIR} tar xaf httpd-2.4.37.tar.gz cd httpd-2.4.37/ ./configure \ --with-apr=/usr/local/apr \ --with-apr-util=/usr/local/apr \ --enable-mpms-shared=all make_source echo "apache安裝成功" local APACHE_BIN_DIR="$(dirname ${APACHE_BIN})" # 若apache可執行文件的目錄不在PATH中,則添加 path_not_exists "${APACHE_BIN_DIR}" && \ sed -i "/^PATH/s|$|:${APACHE_BIN_DIR}|" ${USER_PROFILE}; source ${USER_PROFILE} else echo "apache已存在,請檢查當前版本" fi local APACHE_WSGI="/usr/local/apache2/modules/mod_wsgi.so" if [[ ! -e ${APACHE_WSGI} ]]; then echo "開始安裝mod_wsgi模塊" cd ${SOURCE_DIR} tar xaf mod_wsgi-4.6.5.tar.gz cd mod_wsgi-4.6.5/ ./configure \ --with-apxs=/usr/local/apache2/bin/apxs \ --with-python=/usr/local/bin/python3 make_source echo "mod_wsgi模塊安裝成功" else echo "mod_wsgi模塊已存在,請檢查當前版本" fi } install_nginx() { local NGINX_BIN="/usr/local/nginx/sbin/nginx" [[ -x ${NGINX_BIN} ]] && \ { echo "nginx已存在,請檢查當前版本"; return 0; } local NGINX_CONFIG_OPTS="--with-http_uwsgi_module=shared \ --with-http_gzip_static_module \ --with-http_concat_module \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-pcre \ --with-backtrace_module \ --with-http_upstream_check_module \ --with-http_sysguard_module \ --with-http_slice_module \ --with-http_upstream_ip_hash_module=shared \ --with-http_upstream_session_sticky_module=shared \ --with-http_upstream_least_conn_module=shared" install_nginx_dependencies local NGINX_BIN_DIR="$(dirname ${NGINX_BIN})" # nginx安裝的目標路徑爲--prefix選項顯式指定的目錄,或默認的/usrl/local/nginx目錄 # 若使用默認目標路徑,則可執行文件的目錄爲/usrl/local/nginx/sbin echo "開始安裝nginx" cd ${SOURCE_DIR} tar xaf tengine-2.2.3.tar.gz cd tengine-2.2.3/ ./configure ${NGINX_CONFIG_OPTS} make_source echo "nginx安裝成功" # 若nginx可執行文件的目錄不在系統的PATH中,則添加 path_not_exists "${NGINX_BIN_DIR}" && \ sed -i "/^PATH/s|$|:${NGINX_BIN_DIR}|" ${USER_PROFILE}; source ${USER_PROFILE} } install_uwsgi() { local UWSGI_BIN="/usr/local/bin/uwsgi" [[ -e ${UWSGI_BIN} ]] && \ { echo "uwsgi已存在,請檢查當前版本"; return 0; } local UWSGI_BIN_DIR="$(dirname ${UWSGI_BIN})" echo "開始安裝uwsgi" cd ${SOURCE_DIR} tar xaf uwsgi-2.0.17.1.tar.gz cd uwsgi-2.0.17.1/ python3 setup.py install echo "uwsgi安裝成功" # 若uwsgi可執行文件的目錄不在系統PATH中,則添加 path_not_exists "${UWSGI_BIN_DIR}" && \ sed -i "/^PATH/s|$|:${UWSGI_BIN_DIR}|" ${USER_PROFILE}; source ${USER_PROFILE} } install_django() { python3 -m django --version &> /dev/null && \ { echo "django已存在,請檢查當前版本"; return 0; } echo "開始安裝django" cd ${SOURCE_DIR} tar xaf Django-2.1.5.tar.gz cd Django-2.1.5/ python3 setup.py install echo "django安裝成功" } # django項目基本配置 django_basic_setup() { local DJANGO_DB_NAME="t_django_db" local DJANGO_DB_USER="u_django" local DJANGO_DB_PASS="p_django" local DJANGO_DB_HOST="192.168.9.130" local DJANGO_DB_PORT="3306" [[ ! -d ${DJANGO_PROJECT_DIR} ]] && mkdir -p ${DJANGO_PROJECT_DIR} [[ ! -d ${DJANGO_PROJECT_DIR}/${DJANGO_APP} ]] && \ django-admin startproject ${DJANGO_APP} ${DJANGO_PROJECT_DIR} cd ${DJANGO_PROJECT_DIR} cp -a ${DJANGO_APP}/settings.py{,.ori} sed -i '/^ALLOWED_HOSTS/ s|\[\]|\['\''*'\''\]|' ${DJANGO_APP}/settings.py sed -i '/ENGINE/{n;d}' ${DJANGO_APP}/settings.py sed -i -e '/ENGINE/ s/sqlite3/mysql/' -e '/ENGINE/a\ '\''HOST'\'': '\'''${DJANGO_DB_HOST}''\'',\n '\''PORT'\'': '\'''${DJANGO_DB_PORT}''\'',\n '\''NAME'\'': '\'''${DJANGO_DB_NAME}''\'',\n '\''USER'\'': '\'''${DJANGO_DB_USER}''\'',\n '\''PASSWORD'\'': '\'''${DJANGO_DB_PASS}''\'',\n '\''TIME_ZONE'\'': '\''Asia/Shanghai'\'',\n '\''USE_TZ'\'': False' ${DJANGO_APP}/settings.py sed -i '$a\STATIC_ROOT = os.path.join(BASE_DIR, '\''static'\'')' ${DJANGO_APP}/settings.py python3 manage.py collectstatic python3 manage.py migrate # python3 manage.py runserver 0:8000 & } # mod_wsgi守護進程模式 apache_djange_daemon_mode() { local APACHE_BASE_DIR="/usr/local/apache2" local APACHE_DOC_ROOT_DIR="/opt/webs/documents" local APACHE_BASE_CONF="conf/httpd.conf" local APACHE_DJANGO_CONF="conf/extra/httpd-django.conf" local TAB="$(echo -ne '\t')" id -u ${WEB_USER} &> /dev/null || \ useradd ${WEB_USER} -N -s ${WEB_USER_SHELL} getent group ${WEB_GROUP} &> /dev/null || \ groupadd ${WEB_GROUP} id -gr ${WEB_USER} &> /dev/null || \ usermod -g ${WEB_GROUP} ${WEB_USER} [[ ! -d ${APACHE_DOC_ROOT_DIR} ]] && \ mkdir -p ${APACHE_DOC_ROOT_DIR} chmod +x ${APACHE_DOC_ROOT_DIR} cd ${APACHE_BASE_DIR} cp -a ${APACHE_BASE_CONF}{,.ori} sed -i 's/User daemon/User '${WEB_USER}'/' ${APACHE_BASE_CONF} sed -i 's/Group daemon/Group '${WEB_GROUP}'/' ${APACHE_BASE_CONF} sed -i '/^DocumentRoot/,/<\/Directory\>/ s/^/#/' ${APACHE_BASE_CONF} sed -i '$a\\nServerName localhost:80' ${APACHE_BASE_CONF} sed -i '$a\Include '${APACHE_DJANGO_CONF}'' ${APACHE_BASE_CONF} [[ -f ${APACHE_DJANGO_CONF} ]] && \ cp -a ${APACHE_DJANGO_CONF}{,.ori} cat > ${APACHE_DJANGO_CONF} <<-EOF WSGISocketPrefix ${DJANGO_PROJECT_DIR}/${DJANGO_APP} <VirtualHost *:80> ${TAB}ServerName localhost:80 ${TAB}DocumentRoot ${APACHE_DOC_ROOT_DIR} ${TAB}LoadModule wsgi_module modules/mod_wsgi.so ${TAB}WSGIDaemonProcess ${DJANGO_APP} python-path=${DJANGO_PROJECT_DIR} display-name=%{GROUP} ${TAB}WSGIProcessGroup ${DJANGO_APP} ${TAB}WSGIScriptAlias / ${DJANGO_PROJECT_DIR}/${DJANGO_APP}/wsgi.py process-group=${DJANGO_APP} Alias /static/ ${DJANGO_PROJECT_DIR}/static/ ${TAB}<Directory ${DJANGO_PROJECT_DIR}> ${TAB}${TAB}Require all granted ${TAB}</Directory> </VirtualHost> EOF } # mysql安裝與基本配置 install_setup_mysql() { local MYSQL_BIN="/usr/local/mysql/bin/mysqld" [[ -x ${MYSQL_BIN} ]] && \ { echo "mysql已存在,請檢查當前版本"; return 0; } local MYSQL_BASE_DIR="/usr/local/mysql" local MYSQL_BIN_DIR="${MYSQL_BASE_DIR}/bin" local MYSQL_DATA_DIR="${MYSQL_BASE_DIR}/data" local MYSQL_LOGS_DIR="${MYSQL_BASE_DIR}/logs" local MYSQL_ERR_LOG="${MYSQL_LOGS_DIR}/mysqld-err.log" local MYSQL_SLW_LOG="${MYSQL_LOGS_DIR}/mysqld-slw.log" local MYSQL_PID_FILE="${MYSQL_LOGS_DIR}/mysqld.pid" local MYSQL_LIB_DIR="${MYSQL_BASE_DIR}/lib" local MYSQL_LIB_CONF="/etc/ld.so.conf.d/mysql-v5.7.24.conf" local MYSQL_USER="mysql" local MYSQL_GROUP=${MYSQL_USER} local MYSQL_USER_SHELL="/sbin/nologin" local MYSQL_CMAKE_OPTS="-DCMAKE_INSTALL_PREFIX=${MYSQL_BASE_DIR} \ -DWITH_BOOST=boost \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_PARTITION_STORAGE_ENGINE=1 \ -DWITH_FEDERATED_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_MYISAM_STORAGE_ENGINE=1 \ -DENABLED_LOCAL_INFILE=1 \ -DENABLE_DTRACE=0 \ -DDEFAULT_CHARSET=utf8mb4 \ -DDEFAULT_COLLATION=utf8mb4_general_ci \ -DWITH_SSL=yes \ -DWITH_EMBEDDED_SERVER=1" local DJANGO_DB_NAME="t_django_db" local DJANGO_DB_USER="u_django" local DJANGO_DB_PASS="p_django" local DB_ROOT_PASS="django" local DJANGO_CLIENT="192.168.9.%" install_mysql_dependencies # 若mysql用戶不存在,則建立 id -u ${MYSQL_USER} &> /dev/null || \ useradd ${MYSQL_USER} -N -s ${MYSQL_USER_SHELL} # 若mysql組不存在,則建立 getent group ${MYSQL_GROUP} &> /dev/null || \ groupadd ${MYSQL_GROUP} # 若mysql用戶不是mysql組的成員,則加入 id -gr ${MYSQL_USER} &> /dev/null || \ usermod -g ${MYSQL_GROUP} ${MYSQL_USER} # mysql安裝的目標路徑爲-DCMAKE_INSTALL_PREFIX選項顯式指定的目錄,或默認的/usrl/local/mysql目錄 # 若使用默認目標路徑,則與之相關的共享庫位於/usr/local/mysql/lib cd ${SOURCE_DIR} tar xaf mysql-boost-5.7.24.tar.gz cd mysql-5.7.24/ cmake . ${MYSQL_CMAKE_OPTS} make_source # 建立mysql數據文件,錯誤日誌文件,慢查詢日誌文件,pid文件,並設置所屬的用戶和組 [[ ! -d ${MYSQL_DATA_DIR} ]] && mkdir -p ${MYSQL_DATA_DIR} [[ ! -d ${MYSQL_LOGS_DIR} ]] && mkdir -p ${MYSQL_LOGS_DIR} [[ ! -f ${MYSQL_ERR_LOG} ]] && touch ${MYSQL_ERR_LOG} [[ ! -f ${MYSQL_SLW_LOG} ]] && touch ${MYSQL_SLW_LOG} [[ ! -f ${MYSQL_PID_FILE} ]] && touch ${MYSQL_PID_FILE} chown -R ${MYSQL_USER}:${MYSQL_GROUP} ${MYSQL_BASE_DIR} # 若mysql可執行文件的路徑不在PATH中,則添加 path_not_exists "${MYSQL_BIN_DIR}" && \ sed -i "/^PATH/s|$|:${MYSQL_BIN_DIR}|" ${USER_PROFILE}; source ${USER_PROFILE} mysqld --initialize-insecure --user=${MYSQL_USER} --basedir=${MYSQL_BASE_DIR} --datadir=${MYSQL_DATA_DIR} mv /etc/my.cnf{,.ori} cat > /etc/my.cnf <<-EOF [mysqld] user = mysql port = 3306 server-id = 1 character-set-server = utf8mb4 socket = /tmp/mysql.sock basedir = ${MYSQL_BASE_DIR} datadir = ${MYSQL_DATA_DIR} pid-file = ${MYSQL_ERR_LOG} log_error = ${MYSQL_ERR_LOG} slow_query_log_file = ${MYSQL_SLW_LOG} skip-name-resolve = 1 back_log = 300 max_connections = 1000 max_connect_errors = 6000 open_files_limit = 65535 table_open_cache = 128 max_allowed_packet = 4M binlog_cache_size = 1M max_heap_table_size = 8M tmp_table_size = 16M read_buffer_size = 2M read_rnd_buffer_size = 8M sort_buffer_size = 8M join_buffer_size = 8M key_buffer_size = 4M thread_cache_size = 8 query_cache_type = 1 query_cache_size = 8M query_cache_limit = 2M ft_min_word_len = 4 log_bin = mysql-bin binlog_format = mixed expire_logs_days = 30 slow_query_log = 1 long_query_time = 1 performance_schema = 0 explicit_defaults_for_timestamp #lower_case_table_names = 1 skip-external-locking default_storage_engine = InnoDB innodb_file_per_table = 1 innodb_open_files = 500 innodb_buffer_pool_size = 64M innodb_write_io_threads = 4 innodb_read_io_threads = 4 innodb_thread_concurrency = 0 innodb_purge_threads = 1 innodb_flush_log_at_trx_commit = 2 innodb_log_buffer_size = 2M innodb_log_file_size = 32M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 90 innodb_lock_wait_timeout = 120 bulk_insert_buffer_size = 8M myisam_sort_buffer_size = 8M myisam_max_sort_file_size = 10G myisam_repair_threads = 1 interactive_timeout = 28800 wait_timeout = 28800 [mysqldump] quick max_allowed_packet = 16M [myisamchk] key_buffer_size = 8M sort_buffer_size = 8M read_buffer = 4M write_buffer = 4M EOF # 將mysql的共享庫目錄添加到系統共享庫查找路徑列表的配置文件中 [[ ! -f ${MYSQL_LIB_CONF} ]] && \ echo ${MYSQL_LIB_DIR} > ${MYSQL_LIB_CONF} || \ echo ${MYSQL_LIB_DIR} >> ${DEFAULT_LIB_CONF} ldconfig cp -a ${MYSQL_BASE_DIR}/support-files/mysql.server /etc/init.d/mysqld chmod 755 /etc/init.d/mysqld /etc/init.d/mysqld start chkconfig --level 35 mysqld on mysql -uroot -e "use mysql; set password for 'root'@'localhost' = password('${DB_ROOT_PASS}');" mysql -uroot -pdjango -e "create database ${DJANGO_DB_NAME}; grant all privileges on ${DJANGO_DB_NAME}.* to ${DJANGO_DB_USER}@'${DJANGO_CLIENT}' identified by '${DJANGO_DB_PASS}';" echo "mysql安裝成功" }
django-setup.sh腳本文件:
#! /bin/bash # usage: nohup ./django-setup.sh &> /tmp/django-apache-daemon.log & set -o errexit source /etc/profile readonly LOCK_FD=$[$(ls -l /proc/${BASHPID}/fd | sed -n '$p' | awk '{print $9}') + 1] readonly LOCK_FILE="/tmp/$(basename $0).pid" readonly FUNC_FILE="./django-environment.sh" # 對指定的文件設置非阻塞模式的獨佔鎖,並將正在運行的進程pid寫入到加鎖文件 # 程序運行前首先必須獲取文件鎖,並在運行期間始終持有;若獲取鎖操做失敗,則當即以失敗返回而沒法運行 # 確保程序僅運行單個實例,避免出現競爭狀態 eval "exec ${LOCK_FD}>>${LOCK_FILE}" flock -n ${LOCK_FD} && \ { echo "${BASHPID} - 運行開始"; echo ${BASHPID}>>${LOCK_FILE}; } || \ { echo "${BASHPID} - 運行失敗,($(cat ${LOCK_FILE}))正在運行"; exit 1; } # 若程序成功執行完畢,則在退出前顯式解鎖,備份並清空鎖文件 success() { echo "${BASHPID} - 運行完畢" flock -u ${LOCK_FD} eval "exec ${LOCK_FD}>&-" cp -a ${LOCK_FILE}{,.$(date +%Y-%m-%d-%H-%M-%S)} :>${LOCK_FILE} } trap success EXIT # 加載包含函數定義的文件 source ${FUNC_FILE} setup_apache_django_daemon_mode() { install_common_dependencies install_python3 install_mysqlclient install_django django_basic_setup install_apache apache_djange_daemon_mode } setup_mysql_for_django() { install_setup_mysql } setup_apache_django_daemon_mode #setup_mysql_for_django
uwsgi官方文檔:https://uwsgi-docs.readthedocs.io/en/latest/index.html
mod_wsgi官方文檔:https://modwsgi.readthedocs.io/en/develop/index.html
Django官方文檔:https://docs.djangoproject.com/en/2.1/intro/
Nginx官方文檔:https://docs.nginx.com/nginx/admin-guide/
github項目地址:https://github.com/superwujc
尊重原創,歡迎轉載,註明出處:https://my.oschina.net/superwjc/blog/3003027