言
今天給各位介紹下Tengine/Nginx服務器綁定多個域名多個網站的配置方法。
Tengine/Nginx配置文件
[root@localhost ~]# whereis nginx nginx: /usr/local/nginx [root@localhost ~]#
Nginx的配置文件
vim /usr/local/nginx/conf/nginx.conf #打開nginx配置文件命令 你也可以使用你喜歡的編輯工具如vi emacs gedit
原文件
#以下為Nginx 配置文件nginx.conf默認內容,已加注解。 user www www-data; #以www會員和www-data會員組運行nginx worker_processes 1; #最大進程數,一般設為cpu核心數量 如你是4核cpu 可以設為4 #error_log logs/error.log; #指定錯誤日志文件路徑,默認當前配置文件的父級目錄logs下的error.log #error_log logs/error.log notice; #指定錯誤日志文件路徑并指定為只記錄notice級別錯誤 #error_log logs/error.log info; #指定錯誤日志文件路徑并指定為只記錄info級別錯誤 #pid logs/nginx.pid; ##記錄nginx運行時的進程ID events { worker_connections 1024; #允許的最大連接數即tcp連接數 } # load modules compiled as Dynamic Shared Object (DSO) # 動態模塊加載(DSO)支持。加入一個模塊不再需要重新編譯整個Tengine 這個是Tengine特有的 #dso { # load ngx_http_fastcgi_module.so; #fastcgi模塊 # load ngx_http_rewrite_module.so; #URL重寫模塊 #} http { include mime.types; #設定mime類型,類型由conf目錄下mime.type文件定義 default_type application/octet-stream; #默認為 任意的二進制數據 ## 可配置日志格式: $remote_addr訪客ip ## $remote_user已經經過Auth Basic Module驗證的用戶名 ## $time_local訪問時間 ## $request請求的url ## $body_bytes_sent 傳送頁面的字節數 $http_referer訪問來源 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; #訪問記錄日志 sendfile on; #開啟高效文件傳輸模式 注意:如果圖片顯示不正常把這個改成off。 #tcp_nopush on; #防止網絡阻塞 #keepalive_timeout 0; keepalive_timeout 65; #長連接超時時間,單位是秒 #gzip on; #開啟gzip壓縮 server {#虛擬主機的配置 listen 80; #監聽80端口 server_name localhost; #綁定域名可以有多個,用空格隔開 #charset koi8-r; #字符編碼 可設為 utf-8 #access_log logs/host.access.log main; #訪問記錄日志 location / { ##網站根目錄設置在這里 root html; #配置文件父級html目錄,可以設到其它目錄如/home/www目錄,注意目錄的所有者和權限 本文開頭處user的信息 index index.html index.htm; #默認索引文件,從左到右,如:index.php index.html index.htm 空格分開 } #error_page 404 /404.html; #指定404錯誤文件位置 root指定目錄下的404.html 以下50x文件同理 # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; ##服務器50x得的錯誤都跳轉到html/50x.html文件 location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # 配置處理php文件,需要安裝PHP #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; ##禁止使用.htaccess文件 #} } # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
修改后
###以下為修改過的nginx.conf配置文件,已加注解。 user www www-data; #以www會員和www-data會員組運行nginx worker_processes 1; #最大進程數,一般設為cpu核心數量 如你是4核cpu 可以設為4 error_log logs/error.log; #指定錯誤日志文件路徑,默認當前配置文件的父級目錄logs下的error.log #error_log logs/error.log notice; #指定錯誤日志文件路徑并指定為只記錄notice級別錯誤 #error_log logs/error.log info; #指定錯誤日志文件路徑并指定為只記錄info級別錯誤 pid logs/nginx.pid; ##記錄nginx運行時的進程ID events { use epoll; #新加 提高nginx的性能,限Linux下使用 worker_connections 1024; #允許的最大連接數即tcp連接數 } # load modules compiled as Dynamic Shared Object (DSO) # 動態模塊加載(DSO)支持。加入一個模塊不再需要重新編譯整個Tengine 這個是Tengine特有的 #dso { # load ngx_http_fastcgi_module.so; #fastcgi模塊 # load ngx_http_rewrite_module.so; #URL重寫模塊 #} http { include mime.types; #設定mime類型,類型由conf目錄下mime.type文件定義 default_type application/octet-stream; #默認為 任意的二進制數據 ##可配置日志格式: $remote_addr訪客ip ## $remote_user已經經過Auth Basic Module驗證的用戶名 ## $time_local訪問時間 ## $request請求的url ## $body_bytes_sent 傳送頁面的字節數 ## $http_referer訪問來源 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; #訪問記錄日志 sendfile on; #開啟高效文件傳輸模式 注意:如果圖片顯示不正常把這個改成off。 #tcp_nopush on; #防止網絡阻塞 #keepalive_timeout 0; keepalive_timeout 65; #長連接超時時間,單位是秒 gzip on; #開啟gzip壓縮 ## 新加 include 項引入/usr/local/nginx/vhosts/目錄下所有.conf結尾的虛擬機配置文件 include /usr/local/nginx/vhosts/*.conf }
建立虛擬機配置目錄
mkdir /usr/local/nginx/vhosts/
新建網站配置文件
vim /usr/local/nginx/vhosts/test.conf ##www.test.my 的配置文件 server { #虛擬主機的配置 listen 80; #監聽80端口 server_name www.test.my www.test.my; #綁定域名可以有多個,用空格隔開 #charset koi8-r; #字符編碼 可設為 utf-8 charset utf-8; #access_log logs/host.access.log main; #訪問記錄日志 location / { ##網站根目錄設置在這里 root html; #配置文件父級html目錄,可以設到其它目錄如/home/www目錄,注意目錄的所有者和權限 本文開頭處user的信息 index index.html index.htm; #默認索引文件,從左到右,如:index.php index.html index.htm 空格分開 } #error_page 404 /404.html; #指定404錯誤文件位置 root指定目錄下的404.html 以下50x文件同理 # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; ##服務器50x得的錯誤都跳轉到html/50x.html文件 location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # 配置處理php文件,需要安裝PHP #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; ##禁止使用.htaccess文件 #} }
配置多個網站
#如再配置一個域名為 yuntheme.com站點的配置文件 vim /usr/local/nginx/vhosts/yuntheme.conf #復制剛才的test.conf的內容,只要像下面修改就行了 location / { ##網站根目錄設置在這里 root /usr/local/nginx/html/yuntheme; #修改此處 index index.html index.htm; }
完成配置,重啟Nginx
自hackerfactor,作者:Neal Krawetz,機器之心編譯。
本文作者有一群 geek 朋友,經常一起討論技術話題,有時候也會談到編程語言。「I hate Python」,作者表示。他對 Python 厭惡至極。即使有現成的 Python 代碼可用,他也寧愿用 C 語言重寫。為了系統地吐槽 Python,作者專門寫了這篇博客,細數 Python 的「八宗罪」。
這個話題已經在 Hacker News 上引發了熱烈的討論(評論 400+),感興趣的讀者可以去圍觀或參與一下。
1. 版本
如果要安裝一個默認的 Linux 操作系統,那你很有可能需要安裝多個版本的 Python:Python2、Python3 甚至是 3.5、3.7。原因在于:Python3 無法與 Python2 完全兼容。甚至一些用小數表示的版本(如 3.5、3.7)也明顯缺乏向后的兼容性。
我完全贊成往編程語言中添加新的功能,我甚至不介意淘汰一些舊的版本。但 Python 卻要分開安裝。我的 Python 3.5 代碼不適用于 Python 3.7 安裝版本,除非我特意將其導入 3.7。很多 Linux 開發者都覺得導出太麻煩,因此安裝 Ubuntu 的時候會一并安裝 Python2 和 Python3——因為有的核心功能需要前者,而有的需要后者。
向后兼容性的缺乏和各自為政的版本通常會為其敲響喪鐘。Commodore 創造了第一批家用電腦(比 IBM PC 和蘋果都要早很多)。但 Commodore PET 不能與后續的 Commodore CBM 兼容。CBM 又不與 VIC-20、Commodore-64、Amiga 等兼容。因此,你要么選擇花很多時間將代碼從一個平臺導到另一個,要么選擇放棄這個平臺。(Commodore 今天何在?早被用戶拋棄涼涼了……)
類似地,Perl 也火過一陣。但 Perl3 與 Perl2 的很多代碼也不兼容。社區罵聲一片,于是一些好的代碼導了出來,其他的則被拋棄了。Perl4 也是如此。等 Perl5 出來的時候,人們干脆改用另一種更穩定的編程語言。如今,只有一小部分人還在頻繁使用 Perl 來維持之前的項目。但已經沒有人用 Perl 創建新的大項目了。
同理,Python 的每個版本也都存在谷倉效應。之前的版本還要留著,最終造成手里有一堆舊的無用 Python 代碼,因為大家都不想花時間將其移到最新版上。據我所知,沒有人為 Python2 創建新代碼了,但我們還留著它,因為沒有人想將所需代碼移到 Python3.x 中。Python 2.7、3.5、3.6、3.7 的文檔都還在 Python 官網上積極維護著,因為他們無法下決心棄用之前的代碼。Python 就像一種僵尸編程語言——已經死掉的部分還在以行尸走肉的方式存在著。
2. 安裝
很多軟件包都可以幫你輕松地運行 apt、yum、rpm 或其他一些安裝庫,并獲得最新版本的代碼。但 Python 并非如此。如果用「apt-get install python」安裝,你都不知道自己安的是哪個版本,它可能也無法與你所需的所有代碼兼容。
因此,你要安裝你需要的那版 Python。我的其中一個項目用到 Python,但必須用 Python3.5。所以最后,我的電腦安裝了 Python2、Python2.6、Python3 及 Python3.5。其中兩個來自操作系統,一個用于項目,另外一個服務于出于其他原因安裝的無關軟件。雖然都是 Python,但此 Python 非彼 Python。
如果你想安裝 Python 包,你應該使用「pip」(Pip Installs Packages)。但由于系統上有一堆 Python,你要注意使用正確版本的 pip。否則,「pip」可能運行「pip2」,而不是你需要的「pip3.7」。(如果名稱不存在,你需要為 pip3.7 指定明確的真實路徑)
一位隊友建議我配置自己的環境,這樣的話每種軟件都可以使用 Python3.5 的 base 環境。在我需要用 Python3.6 開展另一個項目之前,這種做法是非常行得通的,但是需要 Python 3.6 就得創建另外一個環境。兩個項目,兩版 Python,一點都不會混,真的(用生命在假笑)。
pip 安裝程序將文件放置在用戶的本地目錄。安裝系統級的庫時不用 pip。Gawd 不允許你在運行「sudo pip」時出錯,因為那會毀了你的整個電腦!運行 sudo 可能會使一些軟件包在系統級別安裝,有些是為錯誤版本的 Python 安裝的,而你的主目錄中的一些文件可能最終歸 root 所有,因此未來的非 sudo pip 安裝可能會因權限問題而失敗。不要這樣做。
這些 pip 模塊由誰來維護呢?當然是社區。也就是說,沒有明確的所有者,也沒有強制性的來源鏈或責任鏈。今年早些時候,PyPI 的一個版本中發現了一個竊取 SSH 憑證的后門。這也是意料之中。(出于同樣的原因,我不用 Node.js 和 npm;我不信任他們的社區項目。)
3. 句法
我非常主張代碼的可讀性要強。乍一看,Python 的可讀性似乎不錯。但當你開始創建大型代碼庫的時候你就不會這么想了。
大多數編程語言使用某種符號來標識范圍——函數的開始和結束位置、條件語句中包含的操作、變量的定義范圍等。C 語言、Java、JavaScript、Perl 和 PHP 都用 {...} 來定義范圍,Lisp 使用 (...)。Python 呢?它用空格!如果你要定義復雜代碼的范圍,你可以縮進接下來的幾行代碼,縮進結束時,該范圍也截止。
Python 手冊說,你可以用任意數量的空格或制表符來定義范圍。但是,每次縮進最好使用四個空格!如果你想縮進兩次進行嵌套,使用八個空格!Python 社區已經對此進行標準化,即使 Python 手冊中并沒有明文規定。這個社區就喜歡用四個空格。所以,除非你不打算將自己的代碼向任何人展示,否則的話每次縮進最好用四個空格。
我第一次看到 Python 代碼時,覺得用縮進來定義范圍還挺好的,但這么做有一個巨大的缺陷。你可以進行深度嵌套,但這么做使得每一行都會很長,導致不得不在文本編輯器中換行。較長的函數和條件語句可能會使開始和結束范圍很難匹配。而且當你不小心把三個空格當成四個空格,還容易出現計算錯誤,進而花幾個小時來調試和追蹤。
對于其它語言,我已經養成了調試代碼不帶任何縮進的習慣。這樣,我可以快速瀏覽代碼,然后輕松地識別和刪除調試代碼。但 Python 呢?任何沒有適當縮進的代碼都會產生縮進錯誤。
4. includes
大部分編程語言都有辦法導入其它代碼塊。比如,C 語言用「#include」,PHP 語言可以用「include、include_once、require、require」。而 Python 用的是「import」。
Python 可以導入整個模塊、模塊的一部分或模塊中的特定函數。C 語言?你可以查看「/usr/include/」。Python 的話,最好用「python -v」列出所有路徑,然后從列表中搜索每個目錄和子目錄中的每個文件。我有些朋友很喜歡 Python,但我看到他們想導入東西時,總得瀏覽標準模塊。
導入功能還允許用戶重命名導入的代碼。它們基本上定義了一個自定義的命名空間。乍一看,你會覺得挺不錯的,但這最終會影響可讀性和長期支持。重命名對于較小的腳本來說還是不錯的,但對于長期項目來說真的不適用。那些使用 1-2 個字母作為命名空間(比如「import numpy as n」),而且還不按約定俗成的方式來命名的,簡直應該拉出去槍斃!
這還不是最糟糕的。大部分編程語言 include 代碼的時候就只是導入代碼而已。如果有一個帶有構造函數的全局對象,有些語言,如面向對象的 C++可能會執行代碼。類似地,有些 PHP 代碼可能會定義全局變量,所以導入可以運行代碼——但這種做法通常被認為很糟糕。相比之下,很多 Python 模塊包含在導入期間運行的初始化函數。你不知道在運行的是什么,它要干什么,你甚至可能不會注意到。除非存在命名空間沖突,如果這樣就好玩了,你得花很多時間來尋找原因。
5. 命名法
在其它語言中,數組(array)直接稱之為'arrays',但是在 Python 中,它們被稱為 'lists'。關聯數組在某些地方被稱為 'hash' (Perl),但是 Python 將其稱為「字典」(dictionary)。Python 似乎完全按照自己的節奏來,不使用計算機科學和信息科學領域的常見術語。
此外,Python 庫的命名也有問題。PyPy、PyPi、NumPy、SciPy、SymPy、PyGtk、Pyglet、PyGame……(前兩個庫的發音一樣,但是它們的功能完全不同)。我理解「py」表示 Python,但是它們就不能統一出現在前面或后面嗎?
一些常見庫放棄了類似雙關語的「Py」命名約定,包括 matplotlib、nose、Pillow 和 SQLAlchemy。雖然有一些命名可能暗示其目的(如 SQLAlchemy 包含 SQL,所以它可能是一個 SQL 接口),但是其它的可能只是隨機的單詞。如果你不知道「BeautifulSoup」這個庫是干什么的,那么你能從命名看出來它是一個 HTML/XML 解析器嗎?不過,BeautifulSoup 有很完善的文檔且易于使用,如果每一個 Python 模塊都這樣,我也就不抱怨了,但是大多數 Python 庫的文檔非常爛。
總的來說,我認為 Python 是一個具有不一致命名約定的函數庫集合。我經常抱怨開源項目的命名非常可怕。除非你知道這些項目在干什么,否則你從命名本身中什么都看不出來。除非你知道在尋找什么樣的庫,不然只能通過別人偶然提及的名字或偶然的機會發現一些庫。大多數 Python 庫加重了這種現象,也加重了 Python 的負面體驗。
6. 奇怪的操作
每種語言都有自己比較奇特的操作。C 語言中使用 & 和 * 獲取地址空間和值的命名法非常奇怪。C 語言中還有用 ++ 和—實現 increment/decrement 的捷徑。Bash 語言中,在引用特定字符(如用于正則表達式的圓括號和句號)時需要一直考慮「什么時候使用轉義符 (\)」。JavaScript 兼容性有問題(并非每個瀏覽器都支持所有有用的功能)。但 Python 的奇怪操作比我見過的其他語言都多。如:
如果你一開始認為 PHP 和 JavaScript 中的=、==、===有點奇怪,那等你用 Python 中的引號時可能不會這么想了。
7. 通過對象 Reference 傳遞
大多數編程語言的函數參數傳遞是傳值。如果函數改變了值,結果不會傳遞回調用代碼。但正如我解釋過的,Python 偏偏要有所不同。Python 默認使用 pass-by-object-reference 來傳遞函數參數。這意味著改變源變量可能最終會改變值。
這是面向程序、函數和對象的編程語言之間的最大區別。如果每個變量都由對象引用來傳遞,并且變量的任何變化都會改變所有的引用,那你可能使用的都是全局對象。通過不同的命名調用相同的對象不會改變對象,所以實際上它就是全局的。此外,正如 C 的程序員早就學到的,全局變量太惡心了,別用。
在 Python 中,你必須通過值來傳遞變量,例如「a=b」只是給相同的對象空間分配了另一個命名,但并沒有復制 b 的值給 a。如果你真的想要復制 b 的值,你需要使用一個 copy 函數,通常是「a=b.copy()"的形式。然而,注意我說的是「通常」。不是所有數據類型都有一個「copy」原型,或者 copy 函數可能是不完整的。在這種情況下,你可以使用單獨的「copy」庫:"a=copy.deepcopy(b)"。
8. 本地命名
用所用的庫或函數的名字來命名程序是常見的編程技巧。例如,如果我用一個叫做「libscreencapture.so」的 C 庫來測試一個截屏程序,我會將該程序命名為「screencapture.c」并編譯為「screencapture.exe」。
gcc -o screencapture.exe screencapture.c -lscreencapture
在 C、Java、JavaScript、Perl、PHP 等語言中,這通常很有效,因為這些語言可以輕易地辨別本地程序和資源庫,它們有不同的路徑。但 Python 呢?還是算了吧,千萬別這樣做。為什么?Python 會假定你首先要導入本地代碼。如果我有一個名為「screencapture.py」的程序使用了「import screencapture」,那么它將導入自己而不是系統庫。至少,你應該調用本地程序「myscreencapture.py」吧。
并非一無是處
Python 是一門非常流行的編程語言,有很多粉絲。甚至我的很多朋友都很喜歡 Python。多年來,我和他們討論過這些問題,每次他們都點頭表示同意。他們并不反對 Python 存在這些問題,只是認為這不足以澆滅他們對這種語言的熱情。
我的朋友經常提到那些非常酷的 Python 庫。我同意一些庫非常有用。例如,BeautifulSoup 是我用過最好的 HTML 解析器之一,NumPy 使多維數組和復雜的數學更容易實現,而 TensorFlow 對于機器學習非常有用。但是,我不會因為喜歡 TensorFlow 或 SciPy 而用 Python 創建單片程序。我不打算為了這些「蠅頭小利」而放棄可讀性和可維護性,這不值得。
通常當我寫一篇關于某個主題的批評時,我也會嘗試寫一些積極的東西。但我沒辦法列出關于 Python 的好的方面,因為我真的認為 Python 很糟糕。
秀站外合作有一個需求:需在一臺web服務器上增加一個虛擬主機用來做圖片資源站,所用程序為第三方,擔心有后門程序,因此希望最好隔斷與原機器其他服務的關系。
思考了一下,確實有一些風險存在。目前我們服務器上都統一使用nobody用戶啟動nginx和php,包括web目錄,這些機器上部分有多個域名在一起運行。這樣至少存在一個問題:如果某一個虛擬主機站點有問題,其web目錄如/diska/htdocs_1被注入惡意程序,那么其他的站點目錄如/diska/htdocs_2域名也很可能難以幸免地通過這個惡意程序被訪問到。分開不同用戶權限,固然可以解決這個問題。但同時也意味需要徒增一個特定用戶,想找一個類似chroot功能。經過搜索查找,nginx中可以增加一個配置項“fastcgi_param PHP_VALUE xxxx”達成這功能:
server {
listen 80 ;
……
location ~ \.(php|phtml) {
……
fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/";
……
}
}
配置項加入在需要設置vhost中,冒號":"為分隔多個路徑。當然也可以加入到 fastcgi_params中讓nginx全局調用。
這樣實現了虛擬主機限制在各自的web目錄中,當某一個域名下出現漏洞或被攻擊時,同一服務器下的其他應用域名不會因此而導致程序文件被查看或修改,避免“跨站”影響。
在查找過程中,同時發現如被入侵,雖然禁錮了對其他web目錄的操作,但php程序還可以調用系統的命令進行一些操作。進一步加強安全,降低webshell調用的系統命令,可在php.ini下加入以下選項:
disable_functions = rmdir,exec,system,passthru,shell_exec
以上,我和松哥通過一些探針腳本進行測試驗證,成功通過檢測。
如果沒上述的設置,那么惡意的腳本能直接通過瀏覽器訪問到其他站點目錄的內容,甚至可以本地調用系統命令啟動一些基于php啟動權限擁有者可以啟動的端口。
供參考。
**注** 網上一些資料說在php5.2版本下,這些設置是不生效的。特意試了一下,真的如此。幸好我們的普遍在5.3以上。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。