本文記錄Ubuntu 16.04 上使用Nginx、 Gunicorn、supervisor 部署django項(xiàng)目
準(zhǔn)備工作:
- Ubuntu16.04安裝Python3.6
Ubuntu16.04默認(rèn)安裝了Python2.7和3.5,但是我的項(xiàng)目是在mac系統(tǒng)調(diào)試完成,而mac系統(tǒng)安裝了python3.6,為了兩端保持調(diào)試一直,我決定把ubuntu上的python升級(jí)到3.6
請(qǐng)注意,系統(tǒng)自帶的python千萬(wàn)不能卸載!
sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6
sudo apt-get install python3.6-dev
調(diào)整Python3的優(yōu)先級(jí),使得3.6優(yōu)先級(jí)較高,python3的默認(rèn)版本就是python3.6
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2
更改默認(rèn)值,python默認(rèn)為Python2,現(xiàn)在修改為Python3,但是不建議更改
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150
如果需要通過(guò)pip命令單獨(dú)為python3安裝某些包,可不必修改系統(tǒng)默認(rèn)的python環(huán)境,我們安裝pip3 即可
sudo apt-get install python3-pip
安裝完成后,通過(guò)pip3安裝即可
注意:如果已經(jīng)安裝了python3.6后,安裝python3.6-dev時(shí),各種報(bào)錯(cuò),請(qǐng)升級(jí)python3.6.
- 創(chuàng)建一個(gè)django項(xiàng)目
我的項(xiàng)目托管在github,配置在新的服務(wù)器時(shí),通過(guò)git clone即可,這里把項(xiàng)目clone在
/var/www目錄下,這里放所有web項(xiàng)目的根目錄。
更改/var/www權(quán)限為www-data,以免每次都是用root權(quán)限去操作/var/www目錄
- 更改/var/www目錄權(quán)限為www-data
首先,確保我的用戶(hù)名包含在 www-data 組中。 如果沒(méi)有,你可以將你的用戶(hù)名添加為 www-data 組
sudo adduser $USER www-data
之后,你應(yīng)該將/var/www的所有權(quán)更改為你的用戶(hù)名
sudo chown $USER:www-data -R /var/www
下一步,對(duì)于常規(guī)實(shí)踐,你應(yīng)該更改權(quán)限為 755 ( rwxr-xr-x ),而不建議將權(quán)限更改為 777,因?yàn)榘踩栽?/p>
sudo chmod u=rwX,g=srX,o=rX -R /var/www
下面是設(shè)置前后的權(quán)限截圖

- 創(chuàng)建一個(gè)python3虛擬環(huán)境
mkvirtualenv -p /usr/bin/python3 blogapi
- 激活虛擬環(huán)境
這里跳過(guò)準(zhǔn)備工作,假設(shè)我已經(jīng)有了一個(gè)項(xiàng)目DjangoBlog和一個(gè)虛擬環(huán)境alpfaceblog
創(chuàng)建數(shù)據(jù)庫(kù)
登錄mysql創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),這里創(chuàng)建一個(gè)名稱(chēng)為blog數(shù)據(jù)庫(kù):
mysql -uroot -p
create database blog charset=utf8;
配置DjangoBlog/setting.py 中數(shù)據(jù)庫(kù) 相關(guān)配置,如下所示:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'blog',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'host',
'PORT': 3306,
}
}
安裝配置gunicorn
- 首先切換到項(xiàng)目的虛擬環(huán)境
workon alpfaceblog
- 創(chuàng)建數(shù)據(jù)庫(kù)
python manage.py makemigrations
python manage.py migrate
- 創(chuàng)建超級(jí)用戶(hù)
python manage.py createsuperuser
- 收集靜態(tài)文件
python manage.py collectstatic --noinput
python manage.py compress --force
- 在虛擬環(huán)境中安裝gunicorn
pip install django gunicorn
- 把 gunicorn 加入項(xiàng)目settings.py中的 INSTALLED_APPS
INSTALLED_APPS = (
# ...
'gunicorn',
)
- 測(cè)試gunicorn是否可以正常工作
cd /var/www/Blog
sudo gunicorn -b 0.0.0.0:8888 --worker-class=gevent DjangoBlog.wsgi:application
- 配置生產(chǎn)環(huán)境下的gunicorn
創(chuàng)建一個(gè)bash腳本用于快速啟動(dòng)gunicorn的
在項(xiàng)目目錄下創(chuàng)建一個(gè)文件夾bin,然后創(chuàng)建gunicorn_start文件
sudo vim gunicorn_start
添加以下內(nèi)容,注意路徑需要根據(jù)實(shí)際情況替換
#!/bin/bash
NAME="DjangoBlog" # 項(xiàng)目的名稱(chēng)
DJANGODIR=/var/www/Blog # 項(xiàng)目所在的目錄
SOCKFILE=/var/www/Blog/run/gunicorn.sock # 啟動(dòng)gunicorn.sock使用UNIX套接字
USER=root # the user to run as
GROUP=root # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=DjangoBlog.settings # which settings file should Django use
DJANGO_WSGI_MODULE=DjangoBlog.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# 啟動(dòng)虛擬環(huán)境的路徑
cd $DJANGODIR
source /home/parallels/.virtualenvs/alpfaceblog/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# gunicorn 安裝在虛擬環(huán)境下的完整路徑
exec /home/parallels/.virtualenvs/alpfaceblog/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-
添加可執(zhí)行權(quán)限: sudo chmod u+x bin/gunicorn_start
啟動(dòng)gunicorn
./bin/gunicorn_start
- 查看給項(xiàng)目配置的gunicorn_start是否啟動(dòng)了項(xiàng)目
sudo pstree -ap|grep gunicorn
如果顯示有進(jìn)程,則說(shuō)明已經(jīng)啟動(dòng),如下:
root@ubuntu:/etc/supervisor# sudo pstree -ap|grep gunicorn
| | | | | |-grep,16796 --color=auto gunicorn
| `-gunicorn,16776 /home/parallels/.virtualenvs/blogapi/bin/gunicorn BlogApi.wsgi:application --nameB
| |-gunicorn,16781 /home/parallels/.virtualenvs/blogapi/bin/gunicorn BlogApi.wsgi:application --nameB
| |-gunicorn,16785 /home/parallels/.virtualenvs/blogapi/bin/gunicorn BlogApi.wsgi:application --nameB
| `-gunicorn,16787 /home/parallels/.virtualenvs/blogapi/bin/gunicorn BlogApi.wsgi:application --nameB
此時(shí)可以通過(guò)瀏覽器訪問(wèn)試試
- 關(guān)閉gunicorn 進(jìn)程
sudo kill -9 上面查詢(xún)的第一個(gè)pid
如果配置了supervisor管理gunicorn進(jìn)程啟動(dòng),則會(huì)在殺死后自動(dòng)重啟
安裝并配置supervisor
Superviosr是一個(gè)進(jìn)程監(jiān)管的工具。簡(jiǎn)而言之,Superviosr可以保證你的程序在服務(wù)器開(kāi)機(jī)時(shí)自動(dòng)啟動(dòng)以及程序意外終止時(shí)重新啟動(dòng)。
- 安裝
sudo apt-get install supervisor
- 配置
supervisor的配置文件默認(rèn)從
/etc/supervisor/conf.d中讀取
cd /etc/supervisor/conf.d
創(chuàng)建并編輯一個(gè)supervisor的配置文件
sudo vim alpfaceblog.conf
添加下面內(nèi)容,注意路徑需要根據(jù)實(shí)際情況替換
[program:DjangoBlog]
command = /var/www/Blog/bin/django_start
user = root
autostart=true
autorestart=true
redirect_stderr = true
stdout_logfile = /root/logs/blog/robot.log
stderr_logfile=/root/logs/blog/err.log
手動(dòng)創(chuàng)建日志目錄:
mkdir -p /root/logs/blog
通過(guò)supervisorctl工具來(lái)啟用這些設(shè)置:
sudo supervisorctl update
sudo supervisorctl reload
啟動(dòng)
supervisord -c /etc/supervisor/supervisord.conf
查看supervisord進(jìn)程
ps aux | grep supervisord
查看日志,是否啟動(dòng)
cat /tmp/supervisord.log
每次修改配置文件后需進(jìn)入supervisorctl,執(zhí)行reload。 supervisord : supervisor的服務(wù)器端部分,用于supervisor啟動(dòng) supervisorctl:?jiǎn)?dòng)supervisor的命令行窗口,在該命令行中可執(zhí)行start、stop、status、reload等操作。
這里我遇到了Supervisor啟動(dòng)錯(cuò)誤信息:
- 問(wèn)題1:
pkg_resources.DistributionNotFound: The 'supervisor==3.2.0' distribution was
解決方法:
這是由于我把ubuntu的python默認(rèn)環(huán)境改成3.5的了,其實(shí)再改回2.7就好了
切換Python版本
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 200
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 100
- 問(wèn)題2:
supervisor 執(zhí)行 django項(xiàng)目中的gunicorn_start失敗
解決步驟:
查看`/var/log/supervisor/supervisord.log`,錯(cuò)誤為: `exit status 127; not expected`
查詢(xún)suspervisord配置的項(xiàng)目日志/root/logs/blogapi/robot.log顯示以下錯(cuò)誤
supervisor: couldn't exec /var/www/blogapi/bin/gunicorn_start: ENOEXEC
解決方法:
在stackoverflow中找到了答案,在項(xiàng)目的gunicorn_start文件頂部添加#!/bin/sh,其實(shí)我添加的是#!/bin/bash,我將它改為#!/bin/sh,再次執(zhí)行sudo supervisorctl reload 問(wèn)題解決。
- 問(wèn)題3:
執(zhí)行sudo supervisorctl update時(shí)報(bào)錯(cuò):root@ubuntu:/var/www/blogapi# sudo supervisorctl update error: <class 'xmlrpclib.Fault'>, <Fault 92: "CANT_REREAD: The directory named as part of the path /root/logs/blogapi/robot.log does not exist. in section 'program:BlogApi' (file: '/etc/supervisor/conf.d/blogapi.conf')">: file: /usr/lib/python2.7/xmlrpclib.py line: 800
解決方法:
啟動(dòng)supervisord
supervisord -c /etc/supervisor/supervisord.conf
- 問(wèn)題4:
每次supervisord reload 或者 啟動(dòng) 都會(huì)報(bào)錯(cuò):
Error: The directory named as part of the path /root/logs/blogapi/robot.log does not exist. in section 'program:BlogApi' (file: '/etc/supervisor/conf.d/blogapi.conf')
解決方法:
出現(xiàn)這個(gè)錯(cuò)誤,是提示/root/logs/blogapi/robot.log文件不存在,查看下/root/logs/blogapi/目錄確實(shí)不存在,創(chuàng)建mkdir /root/logs/blogapi/,然后重新啟動(dòng)或者reload即可
安裝并配置nginx
- 安裝nginx
sudo apt-get install nginx
- ubantu安裝完Nginx后,文件結(jié)構(gòu)大致為:
- 所有的配置文件都在 /etc/nginx下;
- 啟動(dòng)程序文件在 /usr/sbin/nginx下;
- 日志文件在 /var/log/nginx/下,分別是access.log和error.log;
- 并且在 /etc/init.d下創(chuàng)建了啟動(dòng)腳本nginx。
以下為nginx常用的命令
sudo /etc/init.d/nginx start # 啟動(dòng)
sudo /etc/init.d/nginx stop # 停止
sudo /etc/init.d/nginx restart # 重啟
- 配置nginx
配置Nginx 為我們的Django應(yīng)用創(chuàng)建一個(gè)配置文件/etc/nginx/sites-available/alpfaceblog.conf
sudo vim alpfaceblog.conf
刪除/etc/nginx/sites-available中default文件,/etc/nginx/sites-enabled中的default軟連接也一并刪除,不然瀏覽器訪問(wèn)的可能是nginx的默認(rèn)頁(yè)面。
添加以下內(nèi)容,注意:如果配置多個(gè)項(xiàng)目的nginx conf文件時(shí),conf中的upstream 名稱(chēng)(my_server)不要重復(fù),不然nginx啟動(dòng)時(shí)會(huì)報(bào)錯(cuò)
upstream my_server {
server unix:/var/www/Blog/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
large_client_header_buffers 4 16k;
client_max_body_size 300m;
client_body_buffer_size 128k;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 64k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
root /var/www/Blog;
keepalive_timeout 70;
access_log /var/log/nginx/django_access.log;
error_log /var/log/nginx/django_error.log;
location /static {
expires max;
alias /var/www/Blog/collectedstatic/;
}
location /media {
alias /var/www/Blog/media/;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if (!-f $request_filename) {
proxy_pass http://my_server;
break;
}
}
}
- 讓nginx的配置文件生效
sudo ln -s /etc/nginx/sites-available/alpfaceblog.conf /etc/nginx/sites-enabled/alpfaceblog.conf
- 重啟nginx服務(wù)器
sudo service nginx restart
- nginx 配置多個(gè)域名訪問(wèn)不同的項(xiàng)目
在不同的nginx conf文件下,添加server_name 為不同的域名,并設(shè)置listen 為同一斷開(kāi)80,
比如weather.conf
server {
listen 80;
server_name enba.com;
.....
}
再比如blog.conf
server {
listen 80;
server_name objc.com;
.....
}
- 當(dāng)項(xiàng)目的nginx conf文件配置完成完成,nginx運(yùn)行正常且可reload,但是就是無(wú)法通過(guò)瀏覽器訪問(wèn)時(shí),此時(shí)要檢查
sites-available下的.conf文件命名是否為.conf結(jié)尾,另外還有sites-enabled下的軟連接文件是否正?;蛘邽?conf結(jié)尾。 - 當(dāng)在
sites-available中刪除某個(gè).conf文件時(shí),sites-enabled下的軟連接也要?jiǎng)h除,進(jìn)入到sites-enabled目錄下,rm -rf 即可。
問(wèn)題:
nginx遇見(jiàn)的問(wèn)題
1.最近在訪問(wèn)部分頁(yè)面時(shí),速度經(jīng)常非常慢,導(dǎo)致報(bào)502 Bad Gateway錯(cuò)誤
解決方法:
查看nginx的錯(cuò)誤日志,我是配置在error_log /var/log/nginx/django_error.log;下
日志中我發(fā)現(xiàn)了兩個(gè)問(wèn)題,第一個(gè)問(wèn)題:
ubuntu@ip-172-31-17-237:/var/log/nginx$ cat django_error.log
2018/02/24 09:10:43 [error] 1132#1132: *72 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 66.249.64.22, server: www.alpface.com, request: "GET /article/2018/1/20/1.html HTTP/1.1", upstream: "http://unix:/var/www/Blog/run/gunicorn.sock/article/2018/1/20/1.html", host: "www.alpface.net"
2018/02/24 09:22:42 [error] 1132#1132: *87 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 222.249.170.75, server: www.alpface.com, request: "POST /admin/blog/article/add/ HTTP/1.1", upstream: "http://unix:/var/www/Blog/run/gunicorn.sock/admin/blog/article/add/", host: "alpface.com", referrer: "http://alpface.com/admin/blog/article/add/"
通過(guò)網(wǎng)友的各種嘗試,我決定試一試,最終解決了,解決方法:
這是由于,NGINX反向代理的超時(shí)報(bào)錯(cuò):
ubuntu@ip-172-31-17-237:/var/log/nginx$ cd /etc/nginx/sites-available/
ubuntu@ip-172-31-17-237:/etc/nginx/sites-available$ sudo vi alpfaceblog.conf
在網(wǎng)站的配置文件中添加以下,并重啟nginx
server {
listen 80;
server_name localhost;
large_client_header_buffers 4 16k;
client_max_body_size 300m;
client_body_buffer_size 128k;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 64k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
#.............................
}
重啟:sudo /etc/init.d/nginx restart
第二個(gè)問(wèn)題:
查看錯(cuò)誤日志可以看到:/var/www/Blog/media//, media后面多了一個(gè)/, 這是由于nginx配置文件中的資源文件路徑寫(xiě)錯(cuò)了導(dǎo)致的,修改下我的配置文件,重啟nginx解決;
ubuntu@ip-172-31-17-237:/var/log/nginx$ cat django_error.log
2018/03/05 06:44:04 [error] 3493#3493: *1 upstream prematurely closed connection while reading response header from upstream, client: 222.249.170.75, server: localhost, request: "GET /article/2018/2/28/38.html HTTP/1.1", upstream: "http://unix:/var/www/Blog/run/gunicorn.sock:/article/2018/2/28/38.html", host: "www.alpface.com", referrer: "http://www.alpface.com/login/?next=/article/2018/2/28/38.html"
2018/03/05 06:51:16 [error] 3493#3493: *33 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/article/edit/?aid=32"
2018/03/05 06:51:26 [error] 3493#3493: *32 open() "/var/www/Blog/collectedstatic//blog/img/favicon.ico" failed (2: No such file or directory), client: 222.249.170.75, server: localhost, request: "GET /static/blog/img/favicon.ico HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/article/edit/?aid=32"
2018/03/05 06:56:05 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/article/list/"
2018/03/05 06:56:09 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/message/comment/"
2018/03/05 06:56:11 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/message/os/"
2018/03/05 06:56:12 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/message/comment/"
2018/03/05 06:56:15 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/visitor/"
2018/03/05 06:56:18 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/link/"
2018/03/05 06:56:23 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/profile/"
2018/03/05 06:56:37 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/profile/"
2018/03/05 06:56:40 [error] 3493#3493: *41 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/profile/"
2018/03/05 06:56:41 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/link/"
2018/03/05 06:56:43 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/profile/"
2018/03/05 06:56:45 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/article/add/"
2018/03/05 06:56:52 [error] 3493#3493: *39 directory index of "/var/www/Blog/media//" is forbidden, client: 222.249.170.75, server: localhost, request: "GET /media/ HTTP/1.1", host: "www.alpface.com", referrer: "http://www.alpface.com/admin/"
執(zhí)行數(shù)據(jù)庫(kù)遷移時(shí)遇見(jiàn)的問(wèn)題
當(dāng)修改或新增model後, 執(zhí)行python manage.py makemigrations,未生成遷移:
解決方法:
刪除每個(gè)app文件下migrations文件中除了init.py的所有文件,然後再執(zhí)行python manage.py makemigrations重新生成遷移數(shù)據(jù)庫(kù)遷移時(shí)遇見(jiàn)的問(wèn)題:
錯(cuò)誤信息:
django.db.utils.InternalError: (1054, "Unknown column 'name' in 'django_content_type'")
解決方法:
在數(shù)據(jù)庫(kù)中手動(dòng)添加沒(méi)有創(chuàng)建的字段
alter table django_content_type add column name varchar(10)
- 遷移數(shù)據(jù)庫(kù)python manage.py migrate時(shí)出錯(cuò):
django.db.utils.InternalError: (1050, "Table 'auth_permission' already exists")
解決方法:
python manage.py migrate --fake
但是此種方法會(huì)忽略一些錯(cuò)誤,導(dǎo)致最終還是不能解決我們的遷移的問(wèn)題
- ModuleNotFoundError: No module named 'apt_pkg'
升級(jí)到python3.6會(huì)導(dǎo)致python庫(kù)的引用產(chǎn)生混亂,然后python3的軟鏈接也被我改成指向最新版本了。
解決方法:
先選擇刪除python-apt
apt-get remove --purge python-apt
安裝python-apt
apt-get install -f -y python-apt
拷貝python3.5的apt-pkg.so 名重名為python3.6的apt-pkg.so
cd /usr/lib/python3/dist-packages/
sudo cp apt_pkg.cpython-3?m-x86_64-linux-gnu.so apt_pkg.cpython-36m-x86_64-linux-gnu.so
總結(jié):
我的blog項(xiàng)目是在我的本地電腦ubuntu系統(tǒng)上開(kāi)發(fā)並測(cè)試的,然後提交到github上,最後部署到亞馬遜服務(wù)器時(shí),通過(guò)git命令clone到服務(wù)器上;
期間我在本地修改或創(chuàng)建了一些model,這時(shí)我在本地生成遷移和遷移時(shí)都沒(méi)有,但是在服務(wù)端遷移總是報(bào)錯(cuò),導(dǎo)致遷移失敗;
原因:在網(wǎng)上查找各種資料最終都沒(méi)有解決,最後我發(fā)覺(jué)項(xiàng)目的.gitignore中忽略了migrations文件,而每次改變model或新增model時(shí),都會(huì)生成一個(gè)000n_.py文件,每次改變n都會(huì)加1,
此時(shí)我的數(shù)據(jù)庫(kù)也會(huì)在遷移時(shí)發(fā)生改變,而當(dāng)我在服務(wù)器執(zhí)行遷移時(shí),服務(wù)器端沒(méi)有migrations文件,每次遷移都會(huì)重新生成,那麼和本地執(zhí)行時(shí)機(jī)不同,所以會(huì)需要每次執(zhí)行遷移時(shí),會(huì)根據(jù)migrations執(zhí)行的結(jié)果也不同;
解決方法:當(dāng)然我們可以在gitignore中取消這些忽略文件, 另外當(dāng)我們?cè)诜?wù)器段執(zhí)行遷移遇到文件時(shí),我們可以把本地的0001_initial.py中的復(fù)制到服務(wù)端對(duì)應(yīng)的這個(gè)文件再執(zhí)行python manage.py makemigrations和python manage.py migrate