Code Monkey home page Code Monkey logo

blog's Introduction

blog's People

Contributors

dependabot[bot] avatar gaoxt avatar

Stargazers

 avatar

blog's Issues

README测试

gh-md-toc

gh-md-toc — is for you if you want to generate TOC for README.md or
GitHub's wiki page and don't want to install any additional software.

It's my try to fix a problem:

gh-md-toc is able to process:

  • stdin
  • local files (markdown files in local file system)
  • remote files (html files on github.com)

gh-md-toc tested on Ubuntu only. If you want it on Mac OS X or Windows you
better to use a golang based implementation:

It's more solid, reliable and with ability of a parallel processing. And
absolutely without dependencies.

Build Status

Table of contents

Installation

$ wget https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc
$ chmod a+x gh-md-toc

Usage

STDIN

Here's an example of TOC creating for markdown from STDIN:

➥ cat ~/projects/Dockerfile.vim/README.md | ./gh-md-toc -
  * [Dockerfile.vim](#dockerfilevim)
  * [Screenshot](#screenshot)
  * [Installation](#installation)
        * [OR using Pathogen:](#or-using-pathogen)
        * [OR using Vundle:](#or-using-vundle)
  * [License](#license)

Local files

Here's an example of TOC creating for a local README.md:

➥ ./gh-md-toc ~/projects/Dockerfile.vim/README.md                                                                                                                                                Вс. марта 22 22:51:46 MSK 2015

Table of Contents
=================

  * [Dockerfile.vim](#dockerfilevim)
  * [Screenshot](#screenshot)
  * [Installation](#installation)
        * [OR using Pathogen:](#or-using-pathogen)
        * [OR using Vundle:](#or-using-vundle)
  * [License](#license)

Remote files

And here's an example, when you have a README.md like this:

And you want to generate TOC for it.

There is nothing easier:

➥ ./gh-md-toc https://github.com/ekalinin/envirius/blob/master/README.md

Table of Contents
=================

  * [envirius](#envirius)
    * [Idea](#idea)
    * [Features](#features)
  * [Installation](#installation)
  * [Uninstallation](#uninstallation)
  * [Available plugins](#available-plugins)
  * [Usage](#usage)
    * [Check available plugins](#check-available-plugins)
    * [Check available versions for each plugin](#check-available-versions-for-each-plugin)
    * [Create an environment](#create-an-environment)
    * [Activate/deactivate environment](#activatedeactivate-environment)
      * [Activating in a new shell](#activating-in-a-new-shell)
      * [Activating in the same shell](#activating-in-the-same-shell)
    * [Get list of environments](#get-list-of-environments)
    * [Get current activated environment](#get-current-activated-environment)
    * [Do something in environment without enabling it](#do-something-in-environment-without-enabling-it)
    * [Get help](#get-help)
    * [Get help for a command](#get-help-for-a-command)
  * [How to add a plugin?](#how-to-add-a-plugin)
    * [Mandatory elements](#mandatory-elements)
      * [plug_list_versions](#plug_list_versions)
      * [plug_url_for_download](#plug_url_for_download)
      * [plug_build](#plug_build)
    * [Optional elements](#optional-elements)
      * [Variables](#variables)
      * [Functions](#functions)
    * [Examples](#examples)
  * [Example of the usage](#example-of-the-usage)
  * [Dependencies](#dependencies)
  * [Supported OS](#supported-os)
  * [Tests](#tests)
  * [Version History](#version-history)
  * [License](#license)
  * [README in another language](#readme-in-another-language)

That's all! Now all you need — is copy/paste result from console into original
README.md.

And here is a result:

Moreover, it's able to work with GitHub's wiki pages:

➥ ./gh-md-toc https://github.com/ekalinin/nodeenv/wiki/Who-Uses-Nodeenv

Table of Contents
=================

  * [Who Uses Nodeenv?](#who-uses-nodeenv)
    * [OpenStack](#openstack)
    * [pre-commit.com](#pre-commitcom)

Multiple files

It supports multiple files as well:

➥ ./gh-md-toc \
    https://github.com/aminb/rust-for-c/blob/master/hello_world/README.md \
    https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md \
    https://github.com/aminb/rust-for-c/blob/master/primitive_types_and_operators/README.md \
    https://github.com/aminb/rust-for-c/blob/master/unique_pointers/README.md

  * [Hello world](https://github.com/aminb/rust-for-c/blob/master/hello_world/README.md#hello-world)

  * [Control Flow](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#control-flow)
    * [If](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#if)
    * [Loops](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#loops)
    * [For loops](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#for-loops)
    * [Switch/Match](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#switchmatch)
    * [Method call](https://github.com/aminb/rust-for-c/blob/master/control_flow/README.md#method-call)

  * [Primitive Types and Operators](https://github.com/aminb/rust-for-c/blob/master/primitive_types_and_operators/README.md#primitive-types-and-operators)

  * [Unique Pointers](https://github.com/aminb/rust-for-c/blob/master/unique_pointers/README.md#unique-pointers)

Combo

You can easily combine both ways:

➥ ./gh-md-toc \
    ~/projects/Dockerfile.vim/README.md \
    https://github.com/ekalinin/sitemap.s/blob/master/README.md

  * [Dockerfile.vim](~/projects/Dockerfile.vim/README.md#dockerfilevim)
  * [Screenshot](~/projects/Dockerfile.vim/README.md#screenshot)
  * [Installation](~/projects/Dockerfile.vim/README.md#installation)
        * [OR using Pathogen:](~/projects/Dockerfile.vim/README.md#or-using-pathogen)
        * [OR using Vundle:](~/projects/Dockerfile.vim/README.md#or-using-vundle)
  * [License](~/projects/Dockerfile.vim/README.md#license)

  * [sitemap.js](https://github.com/ekalinin/sitemap.js/blob/master/README.md#sitemapjs)
    * [Installation](https://github.com/ekalinin/sitemap.js/blob/master/README.md#installation)
    * [Usage](https://github.com/ekalinin/sitemap.js/blob/master/README.md#usage)
    * [License](https://github.com/ekalinin/sitemap.js/blob/master/README.md#license)

Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)

Tests

Done with bats.
Useful articles:

How to run tests:

➥ make test                                                                                                                                                                                                      Пн. марта 23 13:59:27 MSK 2015
 ✓ TOC for local README.md
 ✓ TOC for remote README.md
 ✓ TOC for mixed README.md (remote/local)
 ✓ TOC for markdown from stdin
 ✓ --help
 ✓ --version

6 tests, 0 failures

Dependency

  • curl or wget
  • awk (mawk, gawk is not supported)
  • grep
  • sed
  • bats (for unit tests)

Tested on Ubuntu 14.04/14.10 in bash/zsh.

如何优化高流量站点的nginx和php-fpm的几个方面

通信机制的选择

nginx和php-fpm 是使用 tcp socket 还是 unix socket ?

合理的配置nginx处理请求数

#cat /proc/cpuinfo | grep processor #查看服务器cpu的处理器数量
# vi /etc/nginx/nginx.conf
worker_processes 16;  #修改为处理器数量
events { 
  worker_connections 4096; # 单个woker进程最大连接并发数 
  multi_accept on;  #linux2.6+默认epoll,如果使用了更优秀的kqueue模型,则使用默认off。
}

配置nginx+php-fpm负载均衡

单机能力有限,比如要支持1000台并发,生成两个sock文件,让每个php-fpm处理500台。

# nginx.conf
upstream backend { 
  server unix:/dev/shm/php-fpm.sock1 weight=100 max_fails=5 fail_timeout=5; 
  server unix:/dev/shm/php-fpm.sock2 weight=100 max_fails=5 fail_timeout=5; 
}


# php-fpm.conf(同理,php7在的配置文件末行引入了pool.d的所有配置)
# www1.conf
listen = /dev/shm/php-fpm.sock1;
listen.backlog = -1  
listen.allowed_clients = 127.0.0.1

pm.max_children = 500
pm.max_requests = 5000

rlimit_files = 50000
request_slowlog_timeout = 20s
slowlog = /var/log/php-slow.log

# cp www1.conf www.conf2
listen = /dev/shm/php-fpm.sock2;

禁止访问日志文件

高流量站点涉及大量I/O,必须在线程间同步。

# nginx.conf
access_log off; 
log_not_found off; 
error_log /var/log/nginx-error.log warn;

如果不能关闭日志访问,至少设置缓冲

access_log /var/log/nginx/access.log main buffer=16k;

启用GZip

# nginx.conf
gzip on; 
gzip_disable "msie6"; 
gzip_vary on; 
gzip_proxied any; 
gzip_comp_level 6; 
gzip_min_length 1100; 
gzip_buffers 16 8k; 
gzip_http_version 1.1; 
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

缓存经常访问的文件

# nginx.conf
open_file_cache max=2000 inactive=20s; 
open_file_cache_valid 60s; 
open_file_cache_min_uses 5; 
open_file_cache_errors off;

调整客户端超时

# nginx.conf
client_max_body_size 50M; 
client_body_buffer_size 1m; 
client_body_timeout 15; 
client_header_timeout 15; 
keepalive_timeout 2 2; 
send_timeout 15; 
sendfile on; 
tcp_nopush on; 
tcp_nodelay on;

调整输出缓冲区

# nginx.conf
fastcgi_buffers 256 16k; 
fastcgi_buffer_size 128k; 
fastcgi_connect_timeout 3s; 
fastcgi_send_timeout 120s; 
fastcgi_read_timeout 120s; 
fastcgi_busy_buffers_size 256k; 
fastcgi_temp_file_write_size 256k; 
reset_timedout_connection on; 
server_names_hash_bucket_size 100;

调整/etc/sysctl.conf

# Recycle Zombie connections 
net.inet.tcp.fast_finwait2_recycle=1 
net.inet.tcp.maxtcptw=200000 

# Increase number of files 
kern.maxfiles=65535 
kern.maxfilesperproc=16384 

# Increase page share factor per process 
vm.pmap.pv_entry_max=54272521 
vm.pmap.shpgperproc=20000 

# Increase number of connections 
vfs.vmiodirenable=1 
kern.ipc.somaxconn=3240000 
net.inet.tcp.rfc1323=1 
net.inet.tcp.delayed_ack=0 
net.inet.tcp.restrict_rst=1 
kern.ipc.maxsockbuf=2097152 
kern.ipc.shmmax=268435456 

# Host cache 
net.inet.tcp.hostcache.hashsize=4096 
net.inet.tcp.hostcache.cachelimit=131072 
net.inet.tcp.hostcache.bucketlimit=120 

# Increase number of ports 
net.inet.ip.portrange.first=2000 
net.inet.ip.portrange.last=100000 
net.inet.ip.portrange.hifirst=2000 
net.inet.ip.portrange.hilast=100000 
kern.ipc.semvmx=131068 

# Disable Ping-flood attacks 
net.inet.tcp.msl=2000 
net.inet.icmp.bmcastecho=1 
net.inet.icmp.icmplim=1 
net.inet.tcp.blackhole=2 
net.inet.udp.blackhole=1

Nginx状态监控

Nginx中的stub_status模块主要用于查看Nginx的一些状态信息,默认不会编译进Nginx,重新编译安装nginx stub_status模块,

持续监视打开的连接数,可用内存和等待线程数。 设置警报以在阈值超过时通知您。您可以自己构建这些警报,或使用像ServerDensity。 请务必安装NGINX stub_status模块 你需要重新编译NGINX -

./configure \
--prefix=/usr/local/nginx \
--with-http_stub_status_module \

make && make install

安装完毕后在server块中加入location

server{  
         location /nginx-status {  
             stub_status on;  
        }  
} 

重启nginx后访问www.x.com/nginx-status即可看到返回的信息

active connections – 活跃的连接数量
server accepts handled requests — 总共处理了11989个连接 , 成功创建11989次握手, 总共处理了11991个请求
reading — 读取客户端的连接数.
writing — 响应数据到客户端的数量
waiting — 开启 keep-alive 的情况下,这个值等于 active – (reading+writing), 意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接.

参考
Nginx基本配置整理
Nginx Core functionality
Optimizing NGINX and PHP-fpm for high traffic sites
启用nginx status状态详解

现代php7

现代php7

内置的web服务器

php5.4之后,自带web服务器

> php -S localhost:8000

代码风格指南

PSR-[0,1,2,4]遵循PHP代码风格,可用与git hook再PUSH时候统一风格。

语言亮点

trait,php5.4起,它的作用是为了减少单继承语言限制,增加函数复用性产生的,trait与class的区别是trait不能被实例化。

函数式编程,即函数可以赋给一个变量,然后动态调用它。
匿名函数,php5.3起,即没有命名的函数。

<?php
$greet = function($name)
{
    printf("Hello %s\r\n", $name);
};
$greet('World');
?>

调用回调函数,并把一个数组参数作为回调函数的参数

mixed call_user_func_array ( callable $callback , array $param_arr ) 

魔术方法

__autoLoad() #自动加载使用类文件
__call() #调用不存在的函数进入到此
__get()/__set()/__unset() #在给不可访问(set、isset、empty、unset)或不可读取(get)属性赋值时,调用private值,并且可以在__get方法增加逻辑处理。
__clone() #对象的复制
__toString() #打印对象信息,必须有返回值

反射API

比print_r()、var_dump()提供更多的信息,调用别人接口时候提供了极大的便利。
常用的Reflection::export($obj);
资料

重载

使用魔术方法来实现,自定义函数__call()中进行逻辑处理,但是本质上是进行了重定向,因为本身是弱类型语言。
资料

参考

php编程之道

iptables基本用法

组织层次
tables -> chains -> rules (表 -> 规则链 -> 规则)
iptables内置了4个tables(filter、NAT、Mangle、Raw)。默认的表是filter。
filter内置了3个chains(INPUT、RORWARD、OUTPUT)
默认是无规则,并且全部ACCEPT。

常用命令:

sudo iptables -nvL

查看iptables列表

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

建立连接后持续接收

sudo iptables -I INPUT 1 -i lo -j ACCEPT

支持lookback,允许ping入/出

sudo iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ACCEPT

允许默认ssh端口22的访问

sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD DROP

限制入口、转发,不限制vps出口。(限制INPUT DROP之前记得开放ss端口,以免断线)

参考:
http://www.jianshu.com/p/28b8536a6c8a
http://www.berlinix.com/linux/iptables.php
https://my.oschina.net/HankCN/blog/117796
http://blog.csdn.net/reyleon/article/details/12976341
http://waringid.blog.51cto.com/65148/512140
http://waringid.blog.51cto.com/65148/517656

systemd 常用指令和配置实例

systemd

在想着把一个脚本文件作为开机启动时候,放到/etc/rc.d/rc.local下reboot后发现并没有启动,发现/etc/rc.d/rc.local注释里写的很明白,要么给rc.local增加chmod -x 的权限用于引导时执行,要么推荐使用systemd或udev规则。

Systemd是一个系统的第一个进程,用于集中管理和配置init。
而Sytemctl主要负责控制Systemd系统和服务管理。

常用命令

systemctl list-unit-files --type=service #列出所有服务
systemctl status nginx.service #检查nginx服务状态
systemctl start/restart/stop/reload/status nginx.service #启动、重启、停止、重载、检查nginx服务
systemctl enable/disable nginx.service #自动启动、禁止启动nginx服务
systemctl daemon-reload #更新.service配置到系统
systemctl kill nginx #杀死nginx服务
systemctl show nginx #查看nginx配置细节

系统命令

whereis systemd/systemctl #检查二进制文件和库文件的安装位置
ps -eaf | grep systemd # 检查systemd是否运行
systemctl --version #查看systemd版本
systemd-analyze blame #分析启动各个进程耗时
systemd-cgls #按等级列出控制组
systemd-cgtop #按CPU、内存、输入和输出列出控制组
systemctl rescue #启动系统救援模式
systemctl emergency #进入紧急模式
systemctl get-default #列出当前使用的运行等级
systemctl isolate runlevel5.target/graphical.target #启动运行等级5,即图形模式
systemctl isolate runlevel3.target/multiuser.target #启动运行等级3,即多用户模式(命令行)
systemctl set-default runlevel3.target #设置多用户模式为默认运行等级
systemctl reboot/halt/suspend/hibernate/hybrid-sleep  #重启、停止、挂起、休眠系统或使系统进入混合睡眠

单元命令

systemd-analyze #分析启动进程
systemd-analyze critical-chain #分析启动时关键链,Systemctl接受服务(.service),挂载点(.mount),套接口(.socket)和设备(.device)作为单元。
systemctl show -p CPUShares nginx.service #查看nginx服务CPU分配额,默认1024
systemctl set-property nginx.service CPUShares=2048 #将nginx服务CPU分配额设置2048
systemd-analyze critical-chain nginx.service #分析nginx服务关键链
systemctl list-dependencies nginx.service #获取nginx依赖性列表
systemctl list-units #列出运行中的单元
systemctl --failed #列出失败的单元
systemctl list-unit-files #列出可用单元状态
systemctl list-unit-files --type=service/mount/socket/device   #列出可用的系统套接字/挂载点
systemctl start/stop/restart/reload/status *.service/*.socket/*.mount/*.device #常用操作
systemctl mask/unmask *.socket/*.mount/*.service/*.device #注销/取消注销	
systemctl is-enabled *.socket/*.mount/*.service/*.device #检查是否启动
systemctl is-active *.socket/*.mount/*.service/*.device #检查是否活跃的
systemctl enable/disable *.socket/*.mount/*.service/*.device #自动启动、禁止启动

新增自己的systemd服务

# vi my-init.service

[Unit]
Description=my-init service
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/bash /etc/rc.d/init.d/init.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

# mv my-init.service /usr/lib/systemd/system/
# systemctl enable my-init.service
# reboot
# ps:init.sh脚本文件里面执行路径必须是绝对路径

新增一个shadowsocke启动服务

[Unit]
Description=Shadowsocks Server
After=network.target

[Service]
Type=forking
PIDFile=/run/ssserver.pid
ExecStart=/usr/bin/ssserver -c /etc/shadowsocks.json --pid-file /run/ssserver.pid  -d start
Restart=on-abort

[Install]
WantedBy=multi-user.target
运行等级 个人理解
0 为停机,机器关闭
1 为单用户模式,救援维护模式,就像Win9x 下的安全模式类似
2 为多用户模式,但是没有NFS 支持
3 为完整的多用户模式,是标准的运行级
4 一般不用,在一些特殊情况下可以用它来做一些事情,例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置
5 就是 X11 ,进到 X Window 系统了
6 为重启,运行 init 6 机器就会重启

参考

systemd简体中文wiki
systemctl 命令完全指南
编写systemd脚本

搭建自己的外网vps

  1. 购买境外vps
    有很多境外的vps,选一个好的vps会让自己省心不少,我这里使用了ConoHa,包月五十多,好处是不限流量,还支持支付宝付款。
  2. 在vps上安装shadowsocks
    购买之后按默认配置追加一台服务器,点击控制台,输入追加服务器时候的用户名和密码,更新软件包,安装pip,使用pip安装shadowsocks,新建/etc/shadowsocks.json配置文件,使用ssserver启动带入配置文件即完成安装。
  3. 在自己电脑上连接vps
    安装shadowsocks客户端,填写在vps配置的shadowsock.json文件信息,启动即可访问。
    Ubunto等linux客户端,可以使用在线gfwlist配合sslocal做到pac的智能分流。

高性能Linux服务器构建实战 第一章 服务器安全运维

1. 服务器安全运维

1.1 账户和登录安全


1.1.1 用户和用户组管理

cat/less/more /etc/passwd
awk -F':' '{print $1}' /etc/passwd
wc -c/l/w  #字节/行数/字数
userdel games
groupdel games
usermod -s /sbin/nologin nagios   #禁用该用户登录

1.1.2 系统服务管理

service/sysv-rc-conf /chkconfig
service --status-all  #查看服务列表
chkconfig --list #显示所有服务
chkconfig [--add] [--del] name
chkconfig --level 345 bluetooth off #指定蓝牙在345等级中关闭
服务名称 服务内容
acpid 电源管理,重要,建议开启
apmd 高级电源能源管理服务,监控电池性能
kudzu 检测硬件是否变化,建议开启
crond 为linux下自动安排的进程提供运行服务,建议开启
atd 类似crond,提供在指定时间做指定的事情,与window下计划任务功能相同
keytables 装载镜像键盘,选择启动
iptables 内置防火墙,必须启动
xinetd 支持多种网络服务的核心守护进程,建议开启
xfs 使用X window桌面系统必须的服务
network 启动网络服务,必须启动
sshd linux远程登录服务,建议开启
syslog 系统日志服务,重要,建议开启
运行等级 个人理解
0 为停机,机器关闭
1 为单用户模式,就像Win9x 下的安全模式类似
2 为多用户模式,但是没有NFS 支持
3 为完整的多用户模式,是标准的运行级
4 一般不用,在一些特殊情况下可以用它来做一些事情,例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置
5 就是 X11 ,进到 X Window 系统了
6 为重启,运行 init 6 机器就会重启

1.1.3 登录密码安全管理

vi /etc/ssh/sshd_config 
Protocol 2 #允许使用ssh2
PubkeyAuthentication yes #启动PublickKey认证
AuthorizedKeysFile .ssh/authorized_key #PublicKey文件路径
PasswordAuthentication no #禁用口令登录
/etc/rc.d/init.d/sshd restart

1.1.4 用户root权限管理

sudo vi /etc/sudoers /sudo visudo  #检查sudoers语法
sudo su -  #切换到root用户
sudo [-l]  #显示当前用户的权限 [-V] #显示版本
user01 ALL=(ALL) NOPASSWD: ALL
用户名 网络中的主机=(执行命令的目标用户) 执行的命令范围

1.1.5 系统欢迎页面管理

/etc/issue、/etc/issue.net、/etc/redhat-release、/etc/motd
vi /etc/ssh/sshd_config 
Banner /etc/issue.net  #在ssh登录后显示内容,默认不开启

ssh或telnet登录显示issue.net内容
本地登录显示issue内容
系统公告 /etc/motd #可发布系统维护、升级、警告黑客等信息 

1.1.6禁用Control-Alt-Delete键盘关闭命令

CentOS5.x以下
vi /etc/inittab
# ca::ctrlaltdel:/sbin/shutdown -t3 -r now
CentOS6.x以上 
vi /etc/init/control-alt-delete.conf
# exec /sbin/shuddown -r now "Control-Alt-Delete pressed"

1.2远程访问和认证安全


1.2.1 取消telnet使用ssh登录

telnet 是古老的远程登录认证服务,在网络上用明文传送口令和数据。
sshd 通过使用ssh,加密所有传输的数据并压缩,加快网络传输速度,防止dns和ip欺骗。

vi /etc/ssh/sshd_config
Port 22 #sshd监听端口,建议更改默认5位以上的陌生数字
Protocol 2 #ssh协议版本,ssh1有缺陷和漏洞,默认ssh2
ListenAddress 0.0.0.0 #sshd服务器绑定的ip地址
HostKey /etc/ssh/ssh_host_dsa_key #服务器密匙文件路径
KeyRegenerationInterval 1h #多少秒后系统自动自动生成服务器密匙,防止被盗用
ServerKeyBits 1024 #服务器密匙长度
SyslogFacility AUTHPRIV #记录来自sshd消息的时候是否"facility code"
LogLevel INFO #sshd日志消息级别
LoginGraceTime 2m #如果用户登录失败,切断链接前服务器需要等待的时间
PermitRootLogin no #超级用户root能不能用ssh登录,建议no
StricModes yes #ssh在接收登录请求之前是否检查用户根目录和rhosts文件的权限和所有权,建议yes
RSAAuthentication no #是否开启RSA密钥验证,针对SSH1
PubkeyAuthentication yes #设置是否开启公钥验证
AuthorizedKeysFile .ssh/authorized_keys #设置公钥验证文件的路径,与PubkeyAuthentication配合使用
IgnoreUserKnownHosts no #SSH在进行RhostsRSAAuthentication 安全验证时是否忽略用户 "$HOME/.ssh/known_hosts"文件
IgnoreRhosts yes #验证时是否使用 "~/,rhosts" 和 "~/.shosts" 文件
PasswordAuthentication yes # 设置是否开启密码验证机制
PermitEmptyPasswords no #是否允许用口令为空的账户登录系统,选择no
ChallengeResponseAuthentication no #禁用s/key密码
UsePAM no #不通过PAM验证
X11Forwarding yes #用户设置是否允许X11转发
PrintMotd yes #设置sshd是否在用户登录的时候显示 "/etc/motd" 中的信息。
PrintLastLog no #是否显示上次登录信息,建议no
Compression yes #是否压缩命令,建议yes
TCPKeepAlive yes #防止死连接,建议yes
UseDNS no #是否使用DNS反向解析
MaxStartups 5 #设置同时允许几个尚未登入的联机,用户连上SSH尚未输入密码的联机。
MaxAuthTries 3 #失败尝试登录次数3
AllowUsers <用户名 用户名2> #指定允许通过远程访问的用户
AllowGroups <组名 组名2> #指定允许通过远程访问的用户组
DenyUsers <用户名 用户名2> #禁止通过远程访问的用户
DenyGroups <组名 组名2> #禁用通过远程访问的用户组

1.2.2 合理使用shell历史记录命令

/etc/bashrc 或 /etc/bash.bashrc 或 ~/.bashrc
HISTFILESIZE=4000
HISTSIZE=4000
HISTTIMEFORMAT='%F %T'
export HISTTIMEFORMAT

/etc/profile 提供系统审计和故障排查的历史功能
#history
USER_IP=`who -u am i 2>/dev/null | awk '{print $NF}' | sed -e 's/[()]//g'`
HISTDIR=/usr/share/.history
if [ -z $USER_IP ]; then
        USER_IP=`hostname`
fi

if [ ! -d $HISTDIR ]; then
        mkdir -p $HISTDIR
        chmod 777 $HISTDIR
fi

if [ ! -d $HISTDIR/${LOGNAME} ]
        then
        mkdir -p $HISTDIR/${LOGNAME}
        chmod 300 $HISTDIR/${LOGNAME}
fi

export HISTSIZE=4000
DT='date + %Y%m%d_%H%M%S'
export HISTFILE="$HISTDIR/${LOGNAME}/${USER_IP}.history.$DT"
export HISTTIMEFORMAT="[%Y.%m.%d %H:%M:%S]"
chmod 600 $HISTDIR/${LOGNAME}/*.history* 2>/dev/null


find / -path /media -prune -o -name '*.history' -print 2>/dev/null #查找除/media目录以外的*.history文件

1.2.3 启用tcp_wrappers防火墙

分析tcp/ip封包软件,类似的ip封包软件有iptables
iptables通过ip过滤机制实现第一层防护,直观地监视系统的运行状态,阻挡恶意攻击。
tcp_wrappers实现某些服务的开发和关闭、允许和禁止,更有效的保证系统运行。

service:host(s) [:action]

service: #服务名,sshd、vsftpd、sendmail
host(s): #主机名或ip,192.168.1.0、www.scooky.com
action: #符合条件后采取的动作

ALL:ALL EXCEPT 192.168.1.100 #除了192.168.1.100这台机器,任何机器执行所有服务时或被允许或被拒绝

vi /etc/hosts.allow
sshd: 192.168.1.100
sshd: 192.168.1.101
sshd: www.scooky.com

vi /etc/hosts.deny
sshd:ALL

允许来自192.168.1.100/101或www.scooky.com的ssh连接,其余的主机被限制。

1.3 文件系统安全


1.3.1 锁定系统重要文件

chattr [-RV] [-v version] [mode] 文件或目录
-R #递归修改所有的文件及子目录
-V #详细显示修改内容,并打印出来
mode
a #append,允许添加不能删除,常用于服务器日志文件安全设定。
i  #immutable,不允许对文件进行任何操作,包括root。

lsattr [-adlRvV] 文件或目录
-a #列出目录中所有文件
-d #显示指定目录的属性
-R #递归方式列出目录中文件
-v #显示文件或目录版本

防止root被盗,对重要文件锁定,常用的有:
chattr -R +i /bin /boot /lib /sbin
chattr -R +i /usr/bin /usr/include /usr/lib /usr/sbin
chattr +i /etc/passwd
chattr +i /etc/shadow
chattr +i /etc/hosts
chattr +i /etc/resolv.conf
chattr +i /etc/fstab
chattr +i /etc/sudoers
chattr +a /var/log/messages
chattr +a /var/log/wtmp

1.3.2 文件权限检查和修改

find / -type f -perm -2 -o -perm -20 | xargs ls -al #查找系统中任何用户都有写权限的文件
find / -type d -perm -2 -o -perm -20 | xargs ls -ld #查找系统中任何用户都有写权限的目录
find / -type f -perm -4000 -o -perm -2000 -print | xargs ls -al #查找系统中所有含有s位的程序
find / -user root -perm -2000 -print  -exec md5sum {} \; #检查系统中所有suid及sgid文件
find / -user root -perm -4000 -print  -exec md5sum {} \; #检查系统中所有suid及sgid文件
find / -nouser -o -nogroup #检查系统中没有属主的文件

1.3.3 /tmp、/var/tmp、/dev/shm 安全设定

/tmp、/var/tmp用来存放临时文件的主要目录
/dev/shm是linux下的共享内存设备,启动系统时默认加载,使用tmpfs内存文件系统,数据驻留在RAM中,通过/dev/shm可直接操控系统内存。

1. 设立/tmp分区法
将/tmp设定为独立的磁盘分区,修改/etc/fstab的/tmp挂载属性,增加nosuid(不允许任何suid程序)、noexec(不能执行脚本)、nodev(不存在设备文件)三个选项,重新挂载/tmp分区即可。
将/var/tmp链接到/tmp下
mv /var/tmp/* /tmp
ln -s /tmp /var/tmp
2. 建立loopback文件系统法
通过创建loopback文件系统来利用linux内核的loopback特性将文件系统挂载到/tmp下
dd if=/dev/zero of=/dev/tmpfs bs=1M count=10000
mke2fs -j /dev/tmpfs
cp -av /tmp /tmp.old
mount -o loop,noexec,nosuid,rw /dev/tmpfs /tmp
chmod 1777 /tmp
mv -f /tmp.old/* /tmp/
rm -rf /tmp.old
编辑/etc/fstab,以便系统启动时自动加载loopback文件系统
/dev/tmpfs /tmp ext3 loop,nosuid,noexec,rw 0 0

修改/dev/shm安全设置
vi /etc/fstab
tmpfs /dev/shm tmpfs defaults,nosuid,noexec,rw 0 0

1.4 系统软件安全管理


yum(yellow dog updater modified)
rpm -qa | grep yum #检查是否安装了yum

/etc/yum.conf #主配置文件
/etc/yum.repos.d #资源配置目录

/etc/yum.repos.d/CentOS-Base.repo #资源库配置
name #发行版名称,Base表明此段寻找的事Base包信息
mirrorlist #yum在互联网上查找升级文件的URL地址,basearch代表硬件架构(i386、x86-64等)
gpgcheck #是否启动gpg检查,启用需要配置GPG-RPM-KEY的位置
gpgkey #指定GPG密钥的地址

yum自动下载升级资源包默认放置在/var/cache/yum目录下

yum install dhcp #安装dhcp
yum remove licp #删除licq包和有依赖性的包
yum checkin-update #检查可更新的RPM包
yum update #更新所有RPM包
yum update kernel kernel-source #更新指定的RPM包
yum upgrade #大规模的版本,与update的区别是陈旧的包也会升级
yum info #列出资源库中所有可以安装或更新的RPM信息
yum into perl* #列出资源库中特定的可以安装或更新以及安装的RPM包信息
yum info updates #列出资源库中所有可以更新的RPM包信息
yum info installed #列出所有已安装的所有RPM包信息
yum info extras #列出已经安装,但不包含资源库中的RPM包信息,也就是其他网站下载的RPM包
yum list updates #列出资源库中所有可以更新的RPM包
yum list installed #列出已安装的RPM包
yum list extras #列出已安装,但不包含在资源库中的RPM包,也就是其他网站下载的RPM包
yum list # 列出资源库中所有可以安装或更新的RPM包
yum list gcc* #列出资源库中特定的可以安装或更新以及已安装的RPM包
yum search wget #搜索特定字符的RPM包信息
yum provides realplay #搜索包含特定文件名的RPM包
yum clean packages #清除暂存的RPM包
yum clean headers #清除暂存的RPM头文件
yum clean oldheaders #清除暂存中旧的RPM头文件
yum [clean /clean all] #清除暂存旧的rpm头文件和包文件

yum第三方源
EPEL,企业版Linux附件软件包
RPMForge,第三方软件源仓库

1.5 Linux后门入侵检测工具


文件级别rootkit,通过修改系统的重要文件来达到隐藏自己的目的,通常容易被替换的系统程序有,login、ls、ps、ifconfig、du、find、netstat,检查文件完整性工具常见的有Tripwire、aide等。

内核级别rootkit,对系统底层获得完全控制权,修改内核,截获运行程序向内核提交的命令,并重定向到入侵者所选择的程序,只有防范攻击者将系统维持在最小权限工作,避免内核被植入rootkit。

rootkit后门检测工具[chkrootkit](http://www.chkrootkit.org/)
1. 准备gcc编译环境
yum -y install gcc
yum -y install gcc-c++
yum -y install make
2. 安装chkrootkit
从官网下载chkrootkit源码
tar zxvf chkrootkit.tar.gz
cd chkrootkit-*
make sense
cd ..
cp -r chkrootkit-* /usr/local/chkrootkit
rm -rf chkrootkit-*
3. 使用chkrootkit
/usr/local/chkrootkit/chkrootkit -h #显示帮助信息
-p dir1:dir2:dirN #指定chkrootkit检测时使用系统命令的目录
/usr/local/chkrootkit/chkrootkit #开始检测系统
4. chkrootkit的缺点
chkrootkit在检查rootkit的过程中使用了部分系统命令,如果依赖的系统命令被替换,此时检测的结果将变得完全不可信。为了避免这个问题,在服务器对外开放之前,事先将chkrootkit使用的系统命令进行备份,使用时用备份命令进行检测。
mkdir /usr/share/.commands
cp `which --skip-alias awk cut echo find egrep id head ls netstat ps strings sed uname` /usr/share/.commands
/usr/local/chkrootkit/chkrootkit -p /usr/share/.commands/
cd /usr/share/
tar zcvf commands.tar.gz .commands
rm -rf commands.tar.gz
在/usr/share/下建立一个.commands的隐藏文件,将chkrootkit使用的系统命令压缩备份,然后下载到一个安全的地方,服务器被入侵后,可以上传回来通过chkrootkit -p参数指定路径进行检测。

rootkit后门检测工具[RKHunter](http://www.rootkit.nl/projects/rootkit_hunter.html)
1. 安装RKHunter
tar -zxvf rkhunter-1.4.0.tar.gz
cd rkhunter-1.4.0
./installer.sh --layout default --install
2. 使用rkhunter
/usr/local/bin/rkhunter-help   #显示帮助
/usr/local/bin/rkhunter -c         #开始检测
/usr/local/bin/rkhunter --check --skip-keypress   #开始检测并跳过enter确认
3. 定时运行
/etc/crontab
09 3 * * * root /usr/local/bin/rkhunter --check --cronjob

1.6 服务器遭受攻击后的处理过程


1. 一般思路
切断网络、查找攻击源、分析入侵原因和途径、备份用户数据、重新安装系统、修复程序或系统漏洞、恢复数据和连接网络。

2. 检查并锁定可疑用户
w   #列出所有登录过的所有用户
passwd -l nobody #锁定nobody用户
ps -ef | grep $pts/3 #根据w命令的TTY找到pid值
kill -9 6051 #将此用户踢下线
last #查看用户登录事件

3. 检查并关闭系统可疑进程
pidof sshd #查找正在运行软件的pid值
ls -al /proc/13276/exe #进入内存目录找到pid对应的exe文件信息
fuser -n tcp 25 #指定tcp、udp协议找到进程pid
ps -ef | grep 2037 #根据pid找到运行目录

4. 检查文件系统完好性
对比/bin/ls文件的大小
rpm -Va #rpm工具验证,文件标记M被篡改或替换

1.7 一次Linux被入侵后的分析


  1. 攻击者通过80端口的web服务文件漏洞进行shell注入,进入系统,在/var/tmp目录下创建隐藏目录,将rootkit后门文件传到该路径下。
  2. 通过后门程序,获取超级用户权限,通过这台服务器进行对外发包
  3. 攻击者ip地址可能是代理的,也可能是控制其他的肉鸡服务器
  4. 为了永久控制这台机器,修改了系统默认账户mail,将mail账户变为登录,并设置了密码。
  5. 攻击完成后,自动清理了系统访问日志,毁灭证据。

防范:

  1. 安装稳定版本操作系统,删除系统默认不需要的用户。
  2. 系统登录改为公钥认证,避开密码认证缺陷。
  3. 安装高版本的web服务器和对程序代码进行审核。
  4. 使用linux下的tcp_wrappers防火墙,限制SSH登录的源地址。

参考:

高性能Linux服务器构建实战 -- 高俊峰

高性能Linux服务器构建实战 第二章 网络安全运维

2. 网络安全运维

2.1 网络实时流量监控工具iftop

iftop是一个免费的网卡实时流量监控工具,类似linux下的top命令。可以监控指定网卡的实时流量、端口连接信息、反向解析ip等,非常适合监控代理服务器或路由器的网络流量。

2.2 网络流量监控与分析工具Ntop和Ntopng

对于单台服务器的网络故障排除,iftop工具可以轻松实现,监控庞大的网络服务器,并且要分析每台主机以及端口的网络状态时,就需要一个高效的网络管理系统了。

2.3网络性能评估工具iperf

iperf是一个基于TCP/IP和UDP/IP的网络性能测试工具,可以用来测量网络带宽和网络质量,提供网络延迟抖动、数据包丢失率、最大传输单元等统计信息,从而定位网络瓶颈,解决网络故障。

2.4 网络探测和安全审核工具nmap

nmap是一个开源免费的网络发现工具,通过它能够找出网络上在线的主机,测试主机上哪些端口处于监听状态,通过端口确定主机上运行的应用程序类型和版本信息,最后利用它还能侦测出操作系统的类型和版本。

参考:

高性能Linux服务器构建实战 -- 高俊峰

nginx和php-fpm 是使用 tcp socket 还是 unix socket ?

tcp socket

允许通过网络进程之间的通信,也可以通过loopback进行本地进程之间通信。

unix socket

允许在本地运行的进程之间进行通信。

分析

图解
从上面的图片可以看,unix socket减少了不必要的tcp开销,而tcp需要经过loopback,还要申请临时端口和tcp相关资源。但是,unix socket高并发时候不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。tcp这样的面向连接的协议,多少可以保证通信的正确性和完整性。

我的选择

如果是在同一台服务器上运行的nginx和php-fpm,并发量不超过1000,选择unix socket,因为是本地,可以避免一些检查操作(路由等),因此更快,更轻。
如果我面临高并发业务,我会选择使用更可靠的tcp socket,以负载均衡、内核优化等运维手段维持效率。

nginx和php-fpm 使用unix socket

将sock文件放在/dev/shm目录下,使用的内存读写更快。

# cd /dev/shm
touch php7.0-fpm.sock 
chown www-data:www-data php7.0-fpm.sock
chmod 777 php7.0-fpm.sock

php-fpm 配置

# vi /etc/php/7.0/fpm/pool.d/www.conf
listen= /dev/shm/php7.0-fpm.sock
listen.owner = www-data
listen.group = www-data

nginx server块配置

  location ~* \.php$ {
    fastcgi_pass unix:/dev/shm/php7.0-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
  }

提高nginx和php-fpm使用的 unix socket稳定性(单机能力有限)

1.修改内核参数

net.unix.max_dgram_qlen = 4096
net.core.netdev_max_backlog = 4096
net.core.somaxconn = 4096

2.提高backlog
backlog默认位128,1024这个值最好换算成自己正常的QPS。

nginx.conf
server{
  listen 80 default backlog=1024;
}

php-fpm.conf
listen.backlog = 1024

3.增加sock文件和php-fpm实例
在/dev/shm新建一个sock文件,在nginx中通过upstream魔抗将请求负载均衡到两个sock文件,
并且将两个sock文件分别对应到两套php-fpm实例上。

参考

nginx通过TCP以及unix-domain-socket连接fastcgi方式对比
nginx、php-fpm默认配置与性能–TCP socket还是unix domain socket

nginx 配置说明

安装nginx

装好gcc g++ 开发库环境
ubunto

$ apt-get install build-essential
$ apt-get install libtool

centos

$ yum -y install gcc automake autoconf libtool make
$ yum install gcc gcc-c++

下载nginx

下载依赖模块gzpi、rewrite、ssl

设定nginx安装目录

/usr/local/nginx/

解压nginx后编译安装

$ sudo ./configure \
--prefix=/usr/local/nginx/nginx \
--with-pcre=/usr/local/opensoft/pcre-8.39 \
--with-zlib=/usr/local/opensoft/zlib-1.2.8 \
--with-openssl=/usr/local/opensoft/openssl-1.0.1t

运行

/usr/local/nginx/sbin/nginx

查看80端口是否运行

netstat -ano | grep 80

访问 localhost ,显示Welcome to nginx! 完成安装。

管理nginx

编译安装需要自行建立nginx shell

配置nginx.conf

配置介绍

user www www;      #运行用户和组
worker_processes  number | auto;      #worker进程数,cpu总核同数量,减少cpu调度成本。
worker_cpu_affinity 01 10;     #多核绑定,位图表示法,ps -F查看,PSR列对应CPU号
pid /usr/local/webserver/nginx/nginx.pid;     #指定pid存放的路径
worker_rlimit_nofile;     #文件描述符数量
master_process on | off;     #启动进程池机制,默认on,如果设置为off,将不会建立master进程,用一个worker来处理。worker_processes也会失效。
daemon on | off;     #是否守护进程,默认on。

#任意域可配
error_log file | level     #debug | info | notice | warn | error | crit | alert | emerg  默认error,过滤前面包含后面,debug需要编译--with-debug,debug按模块控制等级,例如debug_http。

events{
  use poll;     #开启多路复用IO(linux2.6内核以上)
  worker_connections 65535;     #单个worker进程最大连接并发数
  debug_connection 192.168.1.0/24;      #单个ip段进行debug
}
http{
  include mime.types;     #包含mime.types文件
  include vhost/*.conf;     #包含vhost下的所有虚拟主机配置文件

  default_type application/octet-stream;     #指定默认的MIME类型 
  client_max_body_size 8m;                       #客户端上传的文件大小

  #设置日志格式
  log_format  name  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" $http_x_forwarded_for '
                    '"$upstream_addr" "$upstream_status" "$upstream_response_time" "$request_time"';

  #日志存放路径、格式和缓存大小,格式设定为上面定义的name
  access_log /var/log/nginx/access.log  name;
  sendfile            on;              #sendfile是个比 read 和 write 更高性能的系统接口,  反向代理时候无效,因为文件句柄是 socket。
  tcp_nopush     on;           #调用tcp_cork方法,这个也是默认的,结果就是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞。
  tcp_nodelay    on;           #合并小的TCP 包为一个,避免了过多的小报文的 TCP 头所浪费的带宽。如果开启了这个算法 (默认),则协议栈会累积数据直到以下两个条件之一满足的时候才真正发送出去,积累的数据量到达最大的 TCP Segment Size或收到了一个 Ack。
  server_tokens   off;         #关闭nginx 版本号,修改版本号 vi src/core/nginx.h,NGINX_VER
  gzip            on;                #启用压缩
  gzip_static     on;             #启用HTTPGzipStatic模块(不在core和standard模块组中,但rpm安装带了此模块),该模块可以读取预先压缩的gz文件,这样可以减少每次请求进行gzip压缩的CPU资源消耗。
  gzip_comp_level 5;         #压缩级别,1最小最快,9最大最慢,一般设为3
  gzip_min_length 1024;    #压缩的最小长度,小于此长度的不压缩(此长度即header中的Content-Length)
  gzip_types text/plain text/css application/x-javascript application/javascript application/xml; (什么类型的页面或文档启用压缩)

  limit_zone   myzone  $binary_remote_addr  10m;     #myzone 名字,$binary_remote_addr = $remore_addr,,10m的会话空间池
  limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s;     #rate=1r/s 的意思是每个地址每秒只能请求一次,也就是说根据漏桶(leaky bucket)算法 burst=120 一共有120块令牌,并且每秒钟只新增1块令牌, 120块令牌发完后 多出来的那些请求就会返回503
  server{
     limit_conn one 1;                      #限制客户端并发连接数量为1
     limit_req zone=req_one burst=120;          #加上 nodelay之后超过 burst大小的请求就会直接 返回503
  }

  #反向代理时nginx需要访问的上游服务器和负载均衡策略 
  #加权轮询,基础策略,计算各个后端服务器的当前权值,选择得分最高的服务器处理当前请求。
  #ip哈希,哈希选择失败20以上或一台后端服务器,采用加权。
  #加权适用性强,不依赖客户端任何信息,能把客户端请求合理均匀的分配,劣势是同一个客户端多次请求会被分配到不同的后端服务器处理,无法满足会话保持。
  #ip哈希较好地把同一客户端的多次请求分配到同一台后端服务器,劣势是某个ip地址请求特别多(大量用户通过一个nat代理请求),会导致某台后端服务器压力非常大,其他服务器很空闲的不均衡情况。

  upstream back_end{   
    ip_hash;        #负载均衡策略,默认使用加权轮询(round robin),官方内置,一致哈希、fair第三方模块。
    server 127.0.0.1:80;                                                      #一台普通上游服务器
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;   #默认值1 和 30s,30s内连接3次失败,休息一会,30s后再来。
    server UNIX:/tmp/backend3 backup;                           #备机,不可用时,不能使用ip_hash,扰乱哈希结果违背ip_hash策略初衷。
    server 192.168.0.1:9000 down;                                    #主动宕机,不参与被选。
    server backend1.example.com weight=3;                     #权重3,默认1,与加权策略配合使用。
  }

  #取$is_args的值,定义为$my_flag,默认值为0,如果是“?”,值为1
  map $is_args $my_flag{
    default 0;
    "?"       1;
  }

  #禁止用户通过ip地址访问服务器,nginx未配置该域名或通过服务器ip来访问采用。
  server{
    listen 80 default;     #表示这个server是80端口默认的server
    return 500;             #表示任何使用这个server配置的请求将会返回500
  }

  #虚拟主机配置块
  server{   
    listen 80; #监听80端口
    server_name localhost | *.ibeiliao.com | *.* ; #主机名称,~开头的正则表达式
    keepalive_timeout 75 | 0;#超时时间,默认75s,设为0自动断连, http、location、server域中。    
    
    # nginx 常用变量(按阶段执行,先统一set变量)
    # curl -v -o /dev/null 'http://localhost/index.html?a=1&b=2' -H 'hello:world'
    # $uri                  : 当前请求的uri,不包含?后的参数                                             = /index.html
    # $is_args            : 当前请求是否带参数,如果有参数值为?,否则是空字符串        =?
    # $args                : 当前请求的完整参数,即?后面的字符串                                    =a=1&b=2
    # $request_uri     : 当前请求的完整URI,包含参数                                                =/index.html?a=1&b=2
    # $arg_xxx          : 当前请求的某个参数                                                        arg_a=1
    # $http_xxx         : 当前请求的xxx头部对应的值                                      http_hello= world
    # $sent_http_xxx : 返回给客户端的响应头部对应的值                                             =nginx/1.8.0
    #
    # nginx 自定义变量
    # set $max_size 10000;
    # set $new_uri /v2$request_uri
    # set $log_tag "extra action"
    #
    # location [ = | ~ | ~* | ^~ | @ ] uri { ... }
    # 例如 location /image/ {...} 匹配 /image/001.jpg
    # =   : URI必须完全匹配   
    # ~   : 大小写敏感匹配                   location ~ \.(php)$ {...} 大小写敏感处理php请求
    # ~*  : 大小写不敏感匹配               location ~* \.(png)$ {...} 忽略大小写,匹配所有的png文件
    # ^~ : 匹配前半部分即可               location ^~ /image/ {...} 匹配/image/*.* 优先级比上面低。
    # @  : 用于内部子请求,外部无法访问 
    
    #一个转发的location 
    location /passto {    
        proxy_set_header Host $host;            #转发原始请求的host头部
        proxy_buffering off;                           #禁用反向代理缓存,保证每次请求真实转发    
        proxy_pass http://back_end;              #转发到upstream块定义的服务器集群
        #能用try_files代替则用它,否则不要用if,官方声明if用不好的话会有bug。
        #例子:优先使用person下的图片,目录不存在则使用公共目录的图片
        if(-e "${document_root}/person"){
           rewrite ^/(.*)$ /person/$1 break;
        }
        #try_files写法
        try_files /person$uri /$uri =400;
    }      
    location / { #匹配任意URI
       root html;  #http请求根目录,静态web服务器
       alias /var/data/;   #请求目录,与root不同的是,会把location当为别名。location /image/ {...},返回/var/data/001.jpg
       index index.php; #默认index文件
       auth_basic Auth;                                      #弹出信息提示字符为Auth
       auth_basic_user_file /etc/ngx_passwd;     #账号密码
       autoindex  on;                                        #自动列出目录,禁用index
       autoindex_exact_size on;                      #设置索引文件大小的单位
       autoindex_localtime  on;                        #开启本地时间显示文件时间
    }
    #增加websocket的支持
    location /wsapp/ {
      proxy_pass http://wsbackend;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
    location = /50x.html {
      root html;
    }
    location ~ ^(.*)\/\.svn\/{   #禁止访问SVN配置文件
       deny all;                      #禁止该匹配下的所有访问
       deny 192.168.10.1;     #禁止该ip访问,403 forbidden错误。
    }
    #下列文件缓存在本地浏览器30天
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${
           expires 30d;
    }
    #下列文件缓存在本地浏览器1小时
    location ~ .*\.(js|css)?${
           expires 1h;
    }
    error_page 500 502 503 504 /50x.html; #错误返回页面
  }
}

nginx优点

事件驱动,nginx内部流程的向前推进基本都是靠各种事件触发来驱动的,否则nginx将一直阻塞在函数epoll_wait()或sigsuspend()这样的系统调用上。

nginx比apache更快是因为启用了epoll模式(linux kenel 2.6+),它不会随着被监控描述符数目的增长而导致效率急速下降。 而apache用的是select模式,采用遍历扫描来判断每个描述符是否有事件发生。监控的描述符数目越多,消耗也就越大。而且受系统默认限制,select模型最多只能同时监控1024个描述符。

首先,基于poll的epoll具有原生poll的优点,即同时监控的描述符个数不受限制(受进程可打开文件描述符个数限制,cat /proc/sys/fs/file-max),其次,epoll模型对事件的响应是触发式的,无需列表扫描。

epoll
1、监控描述符不受限制(受进程可打开文件描述符个数限制)
2、I/O事件响应触发(LT水平触发,不做处理内核持续通知,ET边缘触发,通知一次,更有优势)
select
1、监控最大1024个描述符
2、I/O事件轮询触发

select 标准的I/O复用模型,unix系统都提供,性能较差,nginx可编译中禁用。
poll 标准的I/O复用模型,理论上比select优,同select类似。
epoll Linux 2.6+上正式提供的更为优秀的I/O复用模型
kqueue FreeBSD4.1+、OpenBSD2.9+、NetBSD2.0、OS X上特有的更优秀的I/O复用模型
eventport 系统Solaris 10上可用的高性能I/O复用模型
/dev/poll 同上
rtsig 实时信号模型(real time signals)
aio 异步I/O

多路复用模型
例子:如果要监控10条高速公路堵车(是否可读),需要10个人(10个线程,10处代码)来做这件事,利用某种技术把10条马路的情况统一传达到某个中心,那么只需要1个人在中心进行监控就行了。而select或epoll这样的多路I/O复用机制好比摄像头的功能,能把多个I/O端口的状况反馈到一处,比如某个特定的文件描述符上,这样,应用程序只需要利用对应的select()或epoll_wait()系统调用阻塞关注一处即可。

调试nginx

遇到性能瓶颈(strace -T 跟踪消耗时间)、启动失败、响应数据与预期不一致、莫名其妙的Segment ation Fault段错误。

ps aux | grep nginx

状态为Ts(s代表Nginx进程为会话的首进程,session leader,T代表处在TASK_STOPPED状态)

使用gdb | cgdb 调试
1、编译nginx的时候绑定gdb
2、修改nginx为一个工作进程,关闭守护进程。
3、开始调试gdb -q -p 4614

使用strace(系统调用)/pstack(内部函数)调试
1、strace -p 4033
2、wget 127.0.0.1 函数

其他调试
System Tap/

参考

  • 深入剖析 nginx -- 高群凯
  • 实战nginx:取代apache的高性能web服务器 -- 张宴
  • ningx.cn

docker 的基本用法与实例

docker

从官方的图片可以很形象的看出来,docker这个玩意,像一艘货轮一样,托运着无数的集装箱。而这个货轮,就是docker,集装箱就是你打包的镜像。也就不难理解docker是一个开源的应用容器引擎这句话了,如果你用过vmware,就会发现它跟快照的功能差不多,但是比快照更轻。有了它,可以让开发人员快速构建可随时运行的容器化应用程序,就是docker提出的“创建一次,到处运行”。

docker概念

使用docker之前,先理解一下docker里面的一些概念,更方便使用。

  • 容器:一个从镜像中启动,包含正在运行的程序的进程。
  • Dockerfile:用于创建镜像的脚本
  • 主机:运行容器的机器。
  • 镜像:文件的层次结构,以及包含如何运行容器的元数据, Dockerfile中的每条命令都会在文件系统中创建一个新的层次结构,文件系统在这些层次上构建起来,镜像就构建于这些联合的文件系统之上。
  • 镜像仓库(Registry):镜像云服务,存放镜像的地方,如Docker Hub
  • 卷(Volumn):将物理机的文件夹挂载到容器内部。

docker安装

安装docker ce(社区免费版),以本机Ubuntu 16.04为例。

  1. 安装依赖
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  1. 添加并验证docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
  1. 添加docker稳定镜像源
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
  1. 更新仓库后安装docker-ce
sudo apt-get update
sudo apt-get install docker-ce
  1. 验证docker版本
sudo docker version

从docker云仓库里面运行一个镜像到本地

从docker hub里面可以搜索到世界各地上传上来的镜像,当然你首先得有一个账户。

  1. 注册docker hub
  2. 在云仓库里找到whalesay,并在终端运行右侧的Docker Pull Command。
  3. 使用docker run docker/whalesay cowsay "hello,world!"运行镜像,让鲸鱼说话。
  4. 使用docker images查看本地镜像列表。

从上面可以看到,docker run第一次运行镜像的时候,先在本地查找,有就使用。如果不存在,才会去docker云上寻找。

更多的镜像,可以通过容器云仓库找到:

使用Dockerfile构建一个属于自己的镜像

# vi ~/work/mydockerbuild/dockerfile
FROM docker/whalesay:latest  #指定一个基础镜像,如果本地没有则寻找docker hub上的 
RUN apt-get -y update && apt-get install -y fortunes #运行一个安装命令,Ubuntu下使用apt-get。
CMD /usr/games/fortune -a | cowsay #执行指令,只能存在一次。

引用当前目录的dockerfile新建一个docker-whale的镜像

sudo docker build -t docker-whale . 

查看和运行镜像

sudo docker images
sudo docker run docker-whale

使用docker 打包一个lnmp环境

参考
docker docs
Docker入门实战

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.