言
今天给各位介绍下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小时内与您取得联系。