显示标签为“服务器”的博文。显示所有博文
显示标签为“服务器”的博文。显示所有博文

2013年10月7日星期一

Nginx 根据 User-Agent 屏蔽访问

有以下的需求:
  • 对所有的机器人、爬虫、蜘蛛屏蔽内部测试用的站点。
  • 对使用 Microsoft Windows Internet Explorer 浏览器的用户展示一个“请更换浏览器”的页面。
set $botblocker_flag "0";
if ($http_user_agent ~* "bot|spider|crawl") {
    set $botblocker_flag "${botblocker_flag}1";
}
if ($uri !~ "/robots.txt(\?.*)?") {
    set $botblocker_flag "${botblocker_flag}2";
}
if ($botblocker_flag = "012") {
    return 403;
}
set $botblocker_flag "";
location = /noie.html {
    return 403;
    error_page 403 =403 @noie;
}
location @noie {
    root /var/www/error;
    index noie.html;
}
if ($http_user_agent ~* "MSIE| (360)?se |360spider|sou?gou|tencenttraveler") {
    rewrite .* /noie.html;
}
把上面的内容放到 /etc/nginx/botblocker 里。某一个站点需要用的时候就 include botblocker; 插在 server{} 块内。
然后写一个劝说用户更换浏览器的页面放在 /var/www/error/noie.html 里面。

2013年7月27日星期六

多人服务器的软件包和服务管理

现维护一台服务器,有很多人要登录,需要管理好软件包和服务。
为了避免服务器重启之后挨个通知大家的问题,我写了一个简单的服务管理脚本。有一些简陋(直接用 rc.local 而不是服务),也有一些 bug(比如关机脚本在某些发行版上不执行),但是安全性是有保障的。
那么软件包呢?服务器是 Debian 的,很多软件包在源里没有,或者版本太旧。这就需要用户自己编译。于是在 .bashrc 中写:
export PATH="$HOME/.local/bin:$HOME/.local/sbin:$PATH"
export LD_LIBRARY_PATH="$HOME/.local/lib"
export LD_RUN_PATH="$HOME/.local/lib"
export PREFIX="$HOME/.local"
export LDFLAGS="-L$HOME/.local/lib"
export CFLAGS="-I$HOME/.local/include"
export CPPFLAGS="-I$HOME/.local/include"
不对所有软件包生效(比如 cmake 生成的软件包,但是有解决方法),但是大部分的都可以这么做了。
可能读者朋友已经使用类似的方法了,这篇文章是个备忘。

2013年7月9日星期二

Nginx alias try_files php-fpm work together

There is such a configuration on my Nginx 1.2.1 server:
server {
 listen 80 default_server;
 listen [::]:80 default_server ipv6only=on;
 root /var/www;
 index index.php index.html;
 autoindex on;
 autoindex_localtime on;
 try_files $uri $uri/ =404;
 location ~ ^/~([^/]+)(/.*)?\.php(/.*)?$ {
  alias /home/$1/public_html$2.php;
  fastcgi_pass unix:/var/run/php5-fpm.sock;
  fastcgi_index index.php;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME /home/$1/public_html$2.php;
  fastcgi_param PATH_INFO $3;
 }
 location ~ ^/~([^/]+)(/.*)?$ {
  alias /home/$1/public_html$2;
 }
}
It aims to map /~username/ to /home/username/public_html/ so that users on my server can access and manage their own files.
However, this brought a problem. If one tried to access a non-exist .php file, such as /~username/asdfasdf.php, php-fpm would complain about “Invalid Argument” instead of displaying the “404 Not Found” page of Nginx.
I have browsed Nginx Wiki and found:
Note that there is a longstanding bug that alias and try_files don't work together.
But I would never give up!
I observed the environment variables that Nginx passed to PHP and found that $_SERVER["DOCUMENT_ROOT"] became the same value as $_SERVER["SCRIPT_FILENAME"] instead of /var/www.
try_files directive tries files from $document_root. For example, try_files $uri =404; tests the existence of the file named $document_root$uri.
It is clear after I noticed this. The workaround is just append try_files "" =404; after the line of alias.

Nginx alias try_files php-fpm 共存

Nginx 1.2.1 服务器有这么一个配置:
server {
 listen 80 default_server;
 listen [::]:80 default_server ipv6only=on;
 root /var/www;
 index index.php index.html;
 autoindex on;
 autoindex_localtime on;
 try_files $uri $uri/ =404;
 location ~ ^/~([^/]+)(/.*)?\.php(/.*)?$ {
  alias /home/$1/public_html$2.php;
  fastcgi_pass unix:/var/run/php5-fpm.sock;
  fastcgi_index index.php;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME /home/$1/public_html$2.php;
  fastcgi_param PATH_INFO $3;
 }
 location ~ ^/~([^/]+)(/.*)?$ {
  alias /home/$1/public_html$2;
 }
}
目的是把所有的 /~username/ 映射到 /home/username/public_html/,让服务器的用户能够存放自己的文件。
但这样带来了一个问题,如果访问一个不存在的 .php 文件,比如 /~username/asdfasdf.php,php-fpm 就会报错,显示“Invalid Argument”而不是 Nginx 的“404 Not Found”页面。
查看了 Nginx 的 Wiki,有这么一句话:
Note that there is a longstanding bug that alias and try_files don't work together.
但是我不会就此罢休的!
于是我观察了 Nginx 传递给 PHP 的环境变量,发现 $_SERVER["DOCUMENT_ROOT"] 变成了和 $_SERVER["SCRIPT_FILENAME"] 一样的值,而不是 /var/www 了。
try_files 指令是从 $document_root 算起的,比如 try_files $uri =404; 就是检测 $document_root$uri 是否存在。
弄明白了这个,就豁然开朗了。在 alias 那一行后面加上 try_files "" =404; 即可。