Coder Social home page Coder Social logo

blog's Introduction

Hi there 👋

🎉 Welcome to my GitHub profile, it's great to meet you here!

👨🏻‍💻 I'm Luffy - a PHP/Go developer and Open source contributor.

💬 You can contact me on Twitter or Email:[email protected]

Operating System

macOS centOS

🚀💻 Technologies & Tools

Git GitHub PHP Golang IntelliJ Redis MySQL Elasticsearch RabbitMQ

Projects

ReadMe Card ReadMe Card
ReadMe Card ReadMe Card
ReadMe Card ReadMe Card

guanhui07 Blog Email Follow on Twitter

GitHub Snake Light

blog's People

Contributors

guanhui07 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

Linux Performance Analysis in 60s

uptime/w --------------------> load average
dmesg | tail ----------------> kernel errors
vmstat 1 --------------------> overall stats every second
mpstat -P ALL 1 -------------> CPU balance
pidstat 1 -------------------> process usage, every second
iostat -xz 1 ----------------> disk I/O
free -m ---------------------> memory usage
sar -n DEV 1 ----------------> network I/O
sar -n TCP,ETCP 1 -----------> TCP stats
top/htop -------------------------> check overview

nginx重新编译安装

是指已经安装成功, 但想对 nginx 添加个模块或者修改配置时需要重新编译

1. 下载对应版本 (如果不想更新版本可以忽略)

可以使用 nginx -V 查看当前程序的编译参数

# 下载
wget http://nginx.org/download/nginx-1.11.13.tar.gz

# 解压
tar xzf nginx-1.11.13.tar.gz

2. 重新编译

# 配置
./configure --prefix=xxx 你的新参数

# 编译
[sudo] make

这时侯切记不要make install, 因为make install就会把文件复制到安装目录

3. 复制程序

# 新复制老版本, 以防出错
cp /path/nginx /path/nginx.back

# 停止服务
/path/nginx -s stop

# 复制新版本到安装目录
cp objs/nginx /path/nginx

# 查看新版本
/path/nginx -t

# 启动新版本
/path/nginx

注意: 如果在运行中直接覆盖nginx会报: cp: 无法创建普通文件"nginx": 文本文件忙

nginx echo模块

使用nginx echo模块 如果是openresty默认支持这个模块

nginx echo模块是在nginx程序上扩展了echo输出字符的功能, 对于调试很方便, 项目地址: https://github.com/openresty/echo-nginx-module

安装

目前支持nginx-1.11.2, 高版本可能安装失败, 我装1.11.13失败了, 更多支持nginx的版本见: https://github.com/openresty/echo-nginx-module#compatibility

release 下载最新的安装包, 并解压.

在配置nginx时用: ./configure --add-module=/你的解压路径, 并编译安装

使用

只是研究了一些常用的

echo - 输出字符

  • 语法: echo [options] <string>...
  • 默认值: no
# 简单的hello, world!
server {
    location = /api/hello {
        echo "hello, world!";
    }
}

默认echo会自动换行, 不需要换行可以: echo -n xxx;;

echo_before_body, echo_after_body - 页面前、后插入内容

  • 语法: echo_before_body [options] [argument]...
  • 默认值: no
server {
    # 简单的输出
    location = /api/hello {
        echo_before_body echo_before_body;
        echo "hello, world!";
        echo_after_body echo_after_body;
    }

    # 常见于代理页面前、后插内容
    location = /api/proxy_before_after {
        echo_before_body echo_before_body;
        echo_before_body echo_before_body;
        proxy_pass http://127.0.0.1;
        echo_after_body echo_after_body;
        echo_after_body echo_after_body;
    }
}

echo_sleep - 请求等待

  • 语法: echo_sleep <seconds>
  • 默认值: no
server {
    # 简单的输出
    location = /api/sleep {
        echo 1;

        # 等待1秒
        echo_sleep 1;

        echo 2;
    }
}

echo_location_async, echo_location - 请求指定路径

  • 语法: echo_location_async <location> [<url_args>]
  • 默认值: no
location /main {
    # 异步调用/sub
    echo_location_async /sub;

    echo world;
}

location /main2 {
    # 同步调用/sub
    echo_location_async /sub;

    echo world;
}

location /sub {
    echo hello;
}

异步跟同步的区别是:

  1. 异步会并行的去请求
  2. 同步等待当前请求结束才会往下执行

下面这个整个时间为2s, 因为新路径最大是2s:

 location /main {
     echo_location_async /sub1;
     echo_location_async /sub2;
     echo "took $echo_timer_elapsed sec for total.";
 }
 location /sub1 {
     echo_sleep 2;
 }
 location /sub2 {
     echo_sleep 1;
 }

下面这个整个时间为3s, 因为需要等待/sub1完成才进入/sub2:

 location /main {
     echo_location /sub1;
     echo_location /sub2;
     echo "took $echo_timer_elapsed sec for total.";
 }
 location /sub1 {
     echo_sleep 2;
 }
 location /sub2 {
     echo_sleep 1;
 }

可以通过第二个参数传querystring: echo_location_async /sub 'foo=Foo&bar=Bar';

echo_foreach_split - 分隔循环

  • 语法: echo_foreach_split <delimiter> <string>
location /split {
    echo_foreach_split ',' $arg_list;
        echo "item: $echo_it";
    echo_end;
}

上面配置当访问: /split?list=cat,dog,mouse 时会输出:

item: cat
item: dog
item: mouse

$arg_list是对应$args.list

那么配置全echo_location_async可以做成nginx-combo服务了, 如:

location = /api/combo {
    echo_foreach_split ',' $query_string;
        echo "/* combo: $echo_it */";
        echo_location_async $echo_it;
        echo;
    echo_end;
}

访问: /api/combo?/a.js,/b.js, 需要注意的是文件的路径必须以/开始, 因为匹配的location

"真的nginx-combo"服务请看: nginx-http-concat


其他变量官网查看~

link

MySQL中如果发现乱码的情况该如何判断原因及修复

1、直接修改法. alter或者pt-osc等其他工具直接对数据进行修改。
2、备份修改法. 利用mysqldump或者其他逻辑备份进行备份,备份的结果集再利用iconv进行转换
3、跳过字符集备份.利用mysqldump备份的时候跳过字符集-t --skip-set-charset。在恢复的时候指定表的字符集。

那么应该如何避免乱码呢
1、首先要从应用端到MySQL,采用统一编码格式utf8,多字节用utf8mb4(真正的utf8)支持emoji
2、在MySQL的配置中,指定编码格式。
3、在上线或者导入SQL的时候,要注意本地的编码集。

nginx 反向代理和负载均衡

upstream ser_pool{
    server 127.0.0.1:3002;
    #server  127.0.0.1:8081 weight=10;
}

server {
    listen       80;
    server_name  test.test.com;
    access_log logs/test.log;
    error_log logs/test.error;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://ser_pool;
    }
}

服务端如果使用nodejs运行服务,由于端口不能同时多个服务占用,而服务器中可能又是多个网站,那么可以使用nginx反向代理 ,比如有这些网站域名和端口:

域名 端口
www.xxoo.com 8001
www.xo.com 8002
www.xo.cn 8003

当然一个服务器上的网站可能还有更多,可以通过配置nginx转发来代理这些端口分发,如:

# 配置 www.xxoo.com的8001代码
server {
    server_name www.xxoo.com;
    listen 80;

    # 设置这个网站的根目录
    root /wwwroot/www.xxoo.com/;

    # 由于下面配置了文件不存在则代码到nodejs中,那么直接访问目录(不带默认主页)的话会有问题,这里做下判断
    # 如果访问目录下有index.html文件,则直接重写到该文件
    # break表示重写且停止,但url不变,而permanent表示301重定向,url会更新
    if ( -f $request_filename/index.html ){
        rewrite (.*) $1/index.html break;
    }

    # 如果请求的文件不存在,则代理到node
    if ( !-f $request_filename ){
        rewrite (.*) /index.js;
    }

    # 代理node服务 8001
    location = /index.js {
        # 设置一些代理的header信息,这些信息将被透传到nodejs服务的header信息里
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        # 代理服务
        proxy_pass http://127.0.0.1:8001$request_uri;

        # 忽略其他重写
        proxy_redirect off;
    }
}

配置之后,比如你网站根目录里有index.html文件,访问url如:

访问链接 解析过程 备注
www.xxoo.com/index.html nginx 由于文件存在,直接使用nginx输出
www.xxoo.com nginx 由于判断该目录下有index.html文件,则自动重写到该文件,但url不变
www.xxoo.com/xx.html nginx -> nodejs:8001 由于文件不存在,使用nginx代理到nodejs的8001端口
www.xxoo.com/xxoo/ nginx -> nodejs:8001 首先判断该目录是否存在
如果存在再判断是否有index.html文件
一旦不成立,直接代理到node

wss websocket ssl

upstream websocket {
    server 127.0.0.1:11521;
}

server {
    server_name phalcon.app;
    listen 443;
    ssl on;
    ssl_certificate /your/path/to/phalcon.pem;
    ssl_certificate_key /your/path/to/phalcon.key;
    # 若ssl_certificate_key使用33iq.key,则每次启动Nginx服务器都要求输入key的密码。
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !MEDIUM";

    root   /_html/html/phalcon/yixin-home/public;
    index  index.html index.htm index.php;

    client_max_body_size 8M;

    proxy_set_header    Host                $host:$server_port;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Real-PORT         $remote_port;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        if (!-e $request_filename) {
        rewrite "^/(.*)$" /index.php?_url=/$1 last;
        }
    }

    location /wss {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #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(.*)$  {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;

        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO  $fastcgi_path_info;
        fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;

        include        fastcgi_params;
    }
}


文章:
https://www.xiaoz.me/archives/10578
https://blog.csdn.net/physicsdandan/article/details/45667357
https://github.com/moonbingbing/openresty-best-practices/blob/master/ngx/reverse_proxy.md
https://www.jianshu.com/p/bed000e1830b

Nginx limit_req

limit_req_zone $binary_remote_addr zone=req_zone:10m rate=10r/s;

location /api {
    limit_req zone=req_zone burst=10 nodelay;
}

rate 限定单位时间内的请求数,burst 限定缓冲队列长度。上面配置是用 client IP 做请求限制,单 IP 限制每秒钟最多十个请求,也就是每 100ms 只能有一个请求,如果 100ms 内有超过一个的请求到达,会被放进 buffer 队列,大小由 burst 指定,所以 100ms 内的第 11 个请求会被 503。

https://www.nginx.com/blog/rate-limiting-nginx/

pip 阿里云镜像源

linux下运行命令
vi ~/.pip/pip.conf
然后写入如下内容并保存

[global]
trusted-host = mirrors.aliyun.com
index-url = https://mirrors.aliyun.com/pypi/simple

Centos7安装pip工具

下载

wget --no-check-certificate https://github.com/pypa/pip/archive/1.5.5.tar.gz
# wget获取https的时候要加上:--no-check-certificate

安装解压

tar -zvxf 1.5.5.tar.gz    #解压文件
cd pip-1.5.5/
python setup.py install

nmap

nmap扫自己vps 阿里云 开放端口,直接

nmap  ip 

扫描 TCP 端口 22, 80:

nmap -sS -p22,80 192.168.1.0/24

-sS 表示扫描 TCP 端口, -sU 表示 UDP 端口
-p 端口范围可以用 -p1-500 的形式制定范围, -p- 表示所有端口。
nmap 会先发送 ICMP echo 来判断目标是否存在。对于 TCP 端口扫描,nmap 再发送 SYN 包,等待 SYN/ACK 回复。

可以用 nmap 发送不合法的包:

-sN null scan
-sX Xmas scan
--mut chop packets into little fragments
--badsum send invalid checksum
不合法的包可以用来判断 OS 类型,下面的命令可以探测 OS 类型::

nmap -sS -O 192.168.1.0/24

检查到端口打开后还可以更进一步:

-sV 检查服务器软件版本 (version detection subsystem)
其他:

--source-port 指定 nmap 发出的 TCP/UDP 包的端口
-S TCP idle scan (高级玩意)
nmap 支持 XML 等输出格式
nmap 还有用 Lua 写的插件

nginx配置浏览器缓存

配置浏览器缓存

  1. 浏览器缓存简介
    浏览器缓存遵循HTTP协议定义的缓存机制(如:Expires;Cache-control等)。

浏览器缓存校验过期机制
校验是否过期 Cache-Control(max-age)、Expires
协议中Etag头信息校验 Etag
Last-Modified头信息校验 Last-Modified

ngx_http_headers_module
语法
Syntax: expires [modified] time;
expires epoch | max | off;
Default: expires off;
Context: http, server, location, if in location

“Expires”头信息中的过期时间为当前系统时间与您设定的 time 值时间的和。如果指定了 modified 参数,则过期时间为文件的最后修改时间与您设定的 time 值时间的和。
“Cache-Control”头信息的内容取决于指定 time 的符号。可以在time值中使用正数或负数。
当 time 为负数,“Cache-Control: no-cache”;
当 time 为正数或0,“Cache-Control: max-age=time”,单位是秒。

使用expires参数

不缓存

server {
    expires -1;
}

输出Response Headers:

Cache-Control:no-cache

当文件没有变更时会返回304, 有变更时会是200, 如果强制命中200可以再添加: if_modified_since off; 忽略 Request Headers 里的 If-Modified-Since 字段

缓存

server {
    expires 1d;
}

1d为1天, 单位如下:

ms  milliseconds
s   seconds
m   minutes
h   hours
d   days
w   weeks
M   months, 30 days
y   years, 365 days

如果希望最大缓存可以:

server {
    expires max;
}

输出Response Headers:

Cache-Control:max-age=315360000

根据链接设置缓存时间

server {
    # 设置为1月
    set $expires_time           1M;

    # 针对后台不缓存
    if ($request_uri ~* ^/admin(\/.*)?$) {
        set $expires_time       -1;
    }

    # 针对静态文件缓存最大
    if ($request_uri ~* ^/static(\/.*)?$) {
        set $expires_time       max;
    }

    # 设置吧
    expires $expires_time;
}
[root/etc/nginx]# curl -I  ip/hello.txt
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Tue, 17 Jul 2018 07:12:11 GMT
Content-Type: text/plain
Content-Length: 12
Last-Modified: Tue, 17 Jul 2018 07:07:22 GMT
Connection: keep-alive
ETag: "5b4d95aa-c"
Expires: Wed, 18 Jul 2018 07:12:11 GMT
Cache-Control: max-age=86400
Accept-Ranges: bytes

重点查看 Expires 和 Cache-Control两个字段,可见,hello.txt 的缓存时间为1天。

sed command

sed workflow
4 spaces of sed

Input Stream
Pattern Space
Hold Buffer
Output Stream
Basic work flow of sed

Read from input stream input until ‘\n’, put content into pattern space (not ‘\n’ is not put into)
Operate on pattern space. Hold buffer is temporary buffer for we to use.
Output to the output stream, add a ‘\n’
Useful options
-n option tells sed not to output the pattern space by default. Use p command to force output.
-i is dangerous, safer to use the file extension to create a copy before modifying the content, e.g. -i.bak.
-e to combine multiple command. Or use ; to separate command.

The following 2 are the same:

sed -n 's/foo/bar/; p'
sed -n -e 's/foo/bar/' -e 'p'

-r use extended regular expression, make characters like + magic character

Specifying command range
Line number (similar with Vim’s command range command)

Replace on line 5 to 10:

sed '5,10s/pat/foo/'

Print only line 5 to 10:

sed -n '5,10p'

Invert range, replace except line 5 to line 10:

sed '5,10!s/pat/foo/'

$ means the last line

Use regular expression (similar with awk)

This emulates grep:

sed -rn '/\d*/p'

Can use regex to specify range. Example, delete lines from the first line which matches /foo/ to the first line matches /bar/, inclusive

sed '/foo/,/bar/d'

Hold buffer
Suppose you have a problem where you want to print the line before the line that matches a regular expression. How do you do this? Hold buffer can solve this problem.

h copy pattern space to hold buffer
g copy hold buffer to pattern space
x exchange pattern space and hold buffer
Solving the problem:

sed -n '/regex/{x;p;x}; h'

Note command grouping here: {x;p;x} is a command group, and only get executed when the pattern matches the regex, while the h is executed for each line.

This does not work if the first line matches the regex, fix it:

sed -n '/regex/{x;1!p;x}; h'

替换/home下所有文件中的www.admin11.net为admin11.net

sed -i "s/www.admin11.net/admin11.net/g" `grep www.admin11.net -rl /home`
grep 'img.res.test.com/commonres/static' -rl . | xargs sed -i "s/img.res.test.com\/commonres\/static/test.res.test.com\/resources\/teststatic/g" 

nginx配置https

首先配置支持https必须让nginx开启http_ssl_module模块,可以使用nginx -V查看是否开启TLS SNI support enabled

购买/生成ssl证书,可以使用免费的证书,比如:Let's Encrypt,免费好用的 HTTPS 证书, 签发免费 SSL 泛域名证书

# 配置https

# 配置个http的站点,用来做重定向,当然如果你不需要把http->https可以把这个配置删了
server {
    listen       80;
    # 配置域名
    server_name www.xxoo.com xxoo.com;

    # 添加STS, 并让所有子域支持, 开启需慎重
    add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';

    # 配置让这些http的访问全部301重定向到https的
    rewrite ^(.*) https://www.xxoo.com$1 permanent;
}

# 配置https
server {
    # 配置域名
    server_name www.xxoo.com xxoo.com;

    # https默认端口
    listen 443;

    # 添加STS, 并让所有子域支持, 开启需慎重
    add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';

    # https配置
    ssl on;
    ssl_certificate /xxoo/www.xxoo.com.crt;
    ssl_certificate_key /xxoo/www.xxoo.com.key;

    # 其他按正常配置处理即可...
}

注意,这里证书的格式是.crt

配置后的访问规则

输入链接 最终访问链接
http://www.xxoo.com https://www.xxoo.com
http://www.xxoo.com/404/500 https://www.xxoo.com/404/500
http://xxoo.com https://www.xxoo.com
https://www.xxoo.com -(原链接不变)
https://xxoo.com/500 https://www.xxoo.com/500

以太坊开发平台 geth install

之前Ubuntu上 以太坊开发平台geth install 的记录

sudo apt-get install git

sudo apt-get install nodes
sudo apt-get install npm
sudo apt-get install go
sudo apt-get install nginx

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

参考
https://blog.csdn.net/u013137970/article/details/52255001

http://www.xiqjv.com/2018/03/centos-7-%E6%90%AD%E5%BB%BA%E4%BB%A5%E5%A4%AA%E5%9D%8A%EF%BC%88etherum%EF%BC%89%E7%8E%AF%E5%A2%83/

https://www.linuxidc.com/Linux/2017-02/140417.htm 安装supervisor

nohup geth --datadir /ethereum/data --rpc --rpcaddr 127.0.0.1 --rpcport 8989 --port 3001 --rpcapi=db,eth,net,web3,personal &

nohup node /data/www/eth-api/app.js &

files = supervisord/conf.d/*.ini

[program:geth]
command=geth --datadir /ethereum/data --rpc --rpcaddr 127.0.0.1 --rpcport 8989 --port 3001 --rpcapi=db,eth,net,web3,personal
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/geth.log
stderr_logfile=/var/log/supervisor/geth.log

supervisord -c /etc/supervisor/supervisord.conf

omni:::
/data/tmp/omnicore-0.3.0/bin/omnicored -daemon -txindex

[program:omnicored]
command=/data/tmp/omnicore-0.3.0/bin/omnicored -daemon -txindex
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/omnicore.log
stderr_logfile=/var/log/supervisor/omnicore.log

http://blog.fens.me/bitcoin-install-geth/

PHP优化(转)

转自https://huoding.com/2014/12/25/398

listen
虽然 Nginx 和 PHP 可以部署在不同的服务器上,但是实际应用中,多数人都习惯把它们部署在同一台服务器上,如此就有两个选择:一个是 TCP,另一个是 Unix Socket。
和 TCP 比较,Unix Socket 省略了一些诸如 TCP 三次握手之类的环节,所以相对更高效,不过需要注意的是,在使用 Unix Socket 时,因为没有 TCP 对应的可靠性保证机制,所以最好把 backlog 和 somaxconn 设置大些,否则面对高并发时会不稳定。

pm
进程管理有动态和静态之分。动态模式一般先启动少量进程,再按照请求数的多少实时调整进程数。如此的优点很明显:节省资源;当然它的缺点也很明显:一旦出现高并发请求,系统将不得不忙着 FORK 新进程,必然会影响性能。相对应的,静态模式一次性 FORK 足量的进程,之后不管请求量如何均保持不变。和动态模式相比,静态模式虽然消耗了更多的资源,但是面对高并发请求,它不需要执行高昂的 FORK。

对大流量网站而言,除非服务器资源紧张,否则静态模式无疑是最佳选择。

pm.max_children
启动多少个 PHP 进程合适?在你给出自己的答案之前,不妨看看下面的文章:

php-fpm的max_chindren的一些误区
Should PHP Workers Always Equal Number Of CPUs
一个 CPU 在某一个时刻只能处理一个请求。当请求数大于 CPU 个数时,CPU 会划分时间片,轮流执行各个请求,既然涉及多个任务的调度,那么上下文切换必然会消耗一部分性能,从这个意义上讲,进程数应该等于 CPU 个数,如此一来每个进程都对应一个专属的 CPU,可以把上下文切换损失的效率降到最低。不过这个结论仅在请求是 CPU 密集型时才是正确的,而对于一般的 Web 请求而言,多半是 IO 密集型的,此时这个结论就值得商榷了,因为数据库查询等 IO 的存在,必然会导致 CPU 有相当一部分时间处于 WAIT 状态,也就是被浪费的状态。此时如果进程数多于 CPU 个数的话,那么当发生 IO 时,CPU 就有机会切换到别的请求继续执行,虽然这会带来一定上下文切换的开销,但是总比卡在 WAIT 状态好多了。

那多少合适呢?要理清这个问题,我们除了要关注 CPU 之外,还要关注内存情况:

top 命令的结果中和内存相关的列分别是 VIRT,RES,SHR。其中 VIRT 表示的是内存占用的理论值,通常不用在意它,RES 表示的是内存占用的实际值,虽然 RES 看上去很大,但是包含着共享内存,也就是 SHR 显示的值,所以单个 PHP 进程实际独立占用的内存大小等于「RES – SHR」,一般就是 10M 上下。以此推算,理论上 1G 内存能支撑大概一百个 PHP 进程,10G 内存能大概支撑一千个 PHP 进程。当然并不能粗暴认为越多越好,最好结合 PHP 的 status 接口,通过监控活跃连接数的数量来调整。

http://blog.haohtml.com/archives/15614

http://blog.9ong.com/?p=413

http://www.osetc.com/archives/4857.html

http://www.cdlin.com/29833

redis RDB and AOF

redis中的数据都是存储在内存中的,所以对于数据的持久化是绕不开的话题。
redis的持久化有两种方案,一是RDB,二是AOF。其中前者大概意思就是将内存数据全部快照然后存储到硬盘上,后者则是类似于mysql的二进制日志方案。
这次我打算结合redis的配置文件来分别记录一下两种备份方式。

  • RDB,会定时触发然后将redis存储在内存中的数据以快照的方式全量持久化到硬盘上。在redis-cli控制台下输入命令save就可以实时触发这个操作,此时redis将会被阻塞,不会再响应客户端的其余任何请求,所以为了避免这种被阻塞,可以用bgsave来触发rdb备份。这两个区别就是bgsave以后redis的主进程会fork出一个子进程来做快照持久化,而主进程可以继续相应客户端的任何请求。默认情况下,redis是fork出一个子进程来完成的快照持久化。那么,redis自己何时会触发持久化呢?看下redis中关于rdb所有配置项:

    • // 默认情况下从redis.conf文件的第196行开始
    • // save 秒数 发生变化的key的数量。所以下面三行的意思就是60秒内如果至少10000个key发生了改变、300秒内至少10个key发生了改变、900秒内至少1一个key发生了改变,那么就会触发bgsave
    • save 900 1
    • save 300 10
    • save 60 10000
    • // 如果bgsave遇到错误时停止写入
    • stop-writes-on-bgsave-error yes [ 另一个选项自然就是no了 ]
    • // 开启rdb文件压缩,可以有效减少rdb文件的体积。开启压缩需要付出的代价自然就是cpu点数了,如果你为了节省cpu资源,可以关闭压缩
    • rdbcompression yes
    • // 开启crc64校验可以让rdb文件具备更好的完整性,但是也是需要cpu点数的,可以选择关闭
    • rdbchecksum yes
    • // rdb文件的名字
    • dbfilename dump.rdb
    • // redis的工作目录,上面的rdb文件就会保存在redis的工作目录中
    • dir /var/lib/redis
  • 所以

  • AOF,全称是Append Only File,翻译过来大概就是 “ 只可追加的文件 ”,其实这种方式跟mysql中的binlog很类似,aof文件中记录都是在redis中执行过的命令,比如set user:1 jim、set user:2 tom两条命令会被记录下来,它并不记录数据本身,这个时候大家可能会看出问题来就是:假如我连续set了10000次,但是最后这10000个key我又全部删除了,aof文件岂不是会记录20000条命令?所以为了解决这个问题,针对aof还有个很重要的rewrite机制,从而避免刚才出现那种尴尬境地,记录了20000条命令最终却实际上没有任何数据。将命令追加到aof这个过程redis官方称之为fsync,fsync这个过程是子线程来做的,主线程依然用来处理客户端的请求。下面还是结合配置文件说明aof:

    • // 是否开启aof
    • appendonly no
    • // aof文件名称
    • appendfilename "appendonly.aof"
    • // fsync时间间隔
    • appendfsync everysec
    • // 当子进程在对aof文件进行rewrite的时候暂停主进程对fsync的append操作,避免产生冲突。因为aof的时候,是子进程来做的,此时如果主进程来append新的指令了,两个进程同时操作一个文件会产生冲突,所以此时主进程要append的指令会被缓存到内容中,当子进程rewrite完成后会向主进程发送一个信号来通知rewrite已完成,然后主进程再将放到内存中的append指令追加到aof文件尾部
    • no-appendfsync-on-rewrite no
    • // 触发aof文件rewrite的条件
    • // 当当前aof文件大小超过上次aof文件体积100%后,才会启动rewrite
    • auto-aof-rewrite-percentage 100
    • // 开启rewrite的aof文件最小体积,也就说只有当aof文件超过了64mb后,才会可能产生rewrite。用程序语言表达就是 只有当aof文件体积大于64mb并且当前aof文件体积比上次变化超过了100% 才会产生rewrite。如果aof文件体积小于64mb,那么即便文件变化率超过了100%,也不会发生rewrite。
    • auto-aof-rewrie-min-size 64mb
    • // 忽略aof文件中错误的不完整的日志,如果该选项为no,那么redis会加载aof失败。损坏的aof文件可以尝试用redis-check-aof来修复
    • aof-load-truncated yes
    • // 这是redis 4.0出现的新特性,集成了rdb和aof的优点的一个产物。大家知道在aof rewrite的时候还是要全量读取一次所有的数据,然后rewrite期间缓存下的命令。既然都要全量读取一次了,为何不在这次全量读取的时候就索性以rdb格式写入到文件呢?然后再追加rewrite期间产生的新aof指令。这样,数据不仅恢复快,还能保证数据完整性。默认情况下,该选项处于关闭状态。
    • aof-user-rdb-preamble no
  • TIPS:

  • rdb恢复速度快,aof恢复速度相对要慢一些。

  • 如果aof开启了,那么redis在启动时会选择根据aof文件恢复数据而不是rdb,所以一定要保存好rdb文件。

  • rdb和aof可以同时开启,最大可能地保证数据完整性。如果redis中的数据都是缓存类数据,可以考虑只选择一样即可。

  • 检测修复rdb文件的工具叫做redis-check-rdb,检测修复aof文件的工具叫做redis-check-aof。

  • 如果你有1G的redis数据,那么理论上讲做一次bgsave操作最大需要2G内存,但实际上得益于Copy-On-Write(写时拷贝,COW机制),并不一定会需要2G内存,只有在当主进程将所有的key全部修改过的情况下,才会需要2G内存。

  • 建议redis内存使用量在30%-50%之间,超过50%这个限制就要留心注意下了。

Ubuntu18.04修改阿里云源

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

sudo vim /etc/apt/sources.list

lsb_release -c 本系统的系统代号

Ubuntu 12.04 (LTS)代号为precise。

Ubuntu 14.04 (LTS)代号为trusty。

Ubuntu 15.04 代号为vivid。

Ubuntu 15.10 代号为wily。

Ubuntu 16.04 (LTS)代号为xenial。

Ubuntu18.04版 bionic

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

sources.list文件的条目都是有格式的(通过上面的内容大家也看的出来),一般有如下形式

所以后面几个参数是对软件包的分类(Ubuntu下是main, restricted,universe ,multiverse这四个)

把内容写成

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed universe multiverse

也是可以的

更新软件列表
sudo apt-get update

更新软件包
sudo apt-get upgrade

参考
gong_xucheng_blog

centos7 install php72报错记录

服务器上安装 php72

./configure \
--prefix=/usr/local/php72 \
--with-config-file-path=/usr/local/php71/etc \
--enable-fpm \
--with-fpm-user=www  \
--with-fpm-group=www \
--enable-inline-optimization \
--disable-debug \
--disable-rpath \
--enable-shared  \
--enable-soap \
--with-libxml-dir \
--with-xmlrpc \
--with-openssl \
--with-mcrypt \
--with-mhash \
--with-pcre-regex \
--with-sqlite3 \
--with-zlib \
--enable-bcmath \
--with-iconv \
--with-bz2 \
--enable-calendar \
--with-curl \
--with-cdb \
--enable-dom \
--enable-exif \
--disable-fileinfo \
--enable-filter \
--with-pcre-dir \
--enable-ftp \
--with-gd \
--with-openssl-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib-dir  \
--with-freetype-dir \
--enable-gd-native-ttf \
--enable-gd-jis-conv \
--with-gettext \
--with-mhash \
--enable-json \
--enable-mbstring \
--enable-mbregex \
--enable-mbregex-backtrack \
--with-libmbfl \
--with-onig \
--enable-pdo \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-zlib-dir \
--with-pdo-sqlite \
--with-readline \
--enable-session \
--enable-shmop \
--enable-simplexml \
--enable-sockets  \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--enable-opcache

make ZEND_EXTRA_LIBS='-liconv'
make install

中间make时候报错如下
collect2: ld returned 1 exit status

谷歌错误
vim Makefile
EXTRA_LIBS 行末加
-lcrypt -liconv -llber

顺便装上了redis扩展吧
wget https://pecl.php.net/get/redis-4.1.1.tgz

/usr/local/php72/bin/phpize
./configure --with-php-config=/usr/local/php72/bin/php-config
make && make install

在php.ini 加配置这里不写了

附:扩展到官方找
https://pecl.php.net/

配置 nginx CORS 跨域

设置允许所有的请求

server {
    location / {
        add_header 'Access-Control-Allow-Origin' '*';
    }
}

只允许GET请求

server {
    location / {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Request-Method' 'GET';
    }
}

请求白名单

server {
    location / {
        # 白名单
        if ($http_origin ~* (baidu\.com|github.xuexb.com)$) {
            add_header 'Access-Control-Allow-Origin' '$http_origin';

            # 允许cookie
            add_header 'Access-Control-Allow-Credentials' true;

            # 只允许某些方法
            add_header 'Access-Control-Request-Method' 'GET, POST, OPTIONS';

            # 支持获取其她字段, 需要前端设置 `xhr.withCredentials = true`
            add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        }
    }
}

阮一峰的 跨域资源共享 CORS 详解

nginx map

map $room $room_server {
    default 192.168.1.101:8080;
    1 192.168.1.101:8080;
    2 192.168.1.102:8080;
}

server {
    listen  80;

    location ~ /api/(\d+)/room {
        set $room $1;
        echo $room_server;
    }
}

openresty

openresty repl使用

之前的记录
ngx_lua 一般都是log日志调试
lua-resty.repl 使用 调试直接在终端 打印变量
在nginx.conf引入

master_process off;#
daemon off;#
error_log stderr notice;

再killall nginx , nginx 启动 ,不让其后台运行终端 不退

代码require('resty.repl').start()

写个一个路由m2

content_by_lua_block {
    local a = 3
    require('resty.repl').start()
    ngx.say(a)
}

访问 localhost/m2

nginx 启动 ,不让其后台运行 终端,print a 或 直接输入a 则可调试

文章

后面写入 ngx.req.get_headers() 和 ngx.req.get_uri_args()之类的命令后可以看到

nginx设置目录浏览

当一个目录内没有默认主页的文件时, 直接访问目录会报403 Forbidden错误, 而启用目录浏览功能后可以直接列出当前目录下的文件/文件夹, 如:

server {
    root /data/www; #网站根目录;

    # 优先使用默认主页
    index index.php index.html index.htm;

    # 当默认主页不存在时直接列出目录内文件树
    autoindex on;
}

但多autoindex相关可官方文档: http://nginx.org/en/docs/http/ngx_http_autoindex_module.html

注意, 线上运行环境最好别开启该配置, 因为这将直接暴露你的文件.

wget command

wget
之前只有一直当简单下载wget url

Download all content under a directory of some URL:

wget -r -p -E -k -nH -np --cut-dirs=1 -P <output dir> URL

-r 递归获取
-p —page-requisites 下载正确显示页面需要的文件,如 CSS,图片等
-E —html-extension 将 cgi 脚本之类的文件转换成 html 文件以便本地阅读
-k —convert-links 转换链接以适合本地阅读
-nH 不把主机名放在下载的目录名中
-nd 把所有下载的文件都放在一个目录下(我更愿意保留服务器上的目录结构,不然一个目录下会有太多文件)
—cut-dirs= 保留服务器上目录结构,但是截去几层目录。主机名域名后面的第一个目录为第一层,如果 n = 0,则保留服务器上完整的目录结构
-I : 获取指定目录下的文件,列表用逗号分隔。用 -np 来限制只获取子目录更为简单吧。
-X : 不要获取的目录
-np —no-parent: 不要获取父目录中内容
-P —directory-prefix 下载到指定目录

ffmpeg

刚看到有人问ffmpeg ,好几年前在ubuntu里使用过ffmpeg
现在在mac一样使用,记录一下

ffmpeg 是一个处理视频和音频内容的开源工具库,可以实现编码、解码、转码、流媒体和后处理等服务。

视频剪切

裁剪前 10 秒:
ffmpeg -ss 0:0 -t 0:10 -i input.mov output.mp4
-ss 开始时间
-t 持续时间

裁剪最后 10 秒
ffmpeg -sseof -0:10 -i input.mov output.mp4
-sseof 相对于文件末尾的开始时间

加速/减速视频
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5PTS[v];[0:a]atempo=2[a]" -map "[v]" -map "[a]" output.mp4
setpts=0.5
PTS 中的 0.5 是视频速度放慢一半
atempo=2 中的 2 是相对应的音频速度(=1/视频速度)

提取视频的视频 音频
ffmpeg -i input.mov -vcodec copy -an output.mp4
-vcodec copy 复制视频编码
-an 禁止音频输出

提取音频
ffmpeg -i input.mov -write_xing 0 output.mp3

视频gif转换
ffmpeg -i input.mov -r 10 output.gif
-r fps 帧率

gif转视频
ffmpeg -f gif -i input.gif output.mp4
-f gif 强制输入文件识别为 GIF 格式

每秒输出一张图
ffmpeg -i input.mov -vf fps=1 -q:v 2 output%03d.png

输出第10秒的截图
ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 output.jpg

每秒截图,大小为原视频的一半,输出一张 10x3 的网格图:
ffmpeg -y -i input.mp4 -vf "fps=1,scale=iw/2:-1,tile=10x3" -an output.jpg

加水印
ffmpeg -i my.mp4 -i watermark.png -pix_fmt yuv420p -preset veryslow -crf 18 -filter_complex "overlay=W-w-5:H-h-5" "51. test.mp4"

curl Notes

curl -H 'User-Agent: FakeUA' URL: set HTTP header
curl -I URL: show header only
curl -L URL: follow 30x redirect
curl -o new_name/-O URL: save response to file
curl -X POST --data "data=xxx" URL: POST data to URL

eg:

POST
curl -X POST  'https://etherhub.io/web3relay' -H 'content-type: application/json;charset=UTF-8'  -d '{"block":"6250836"}'

图片上传
curl --form pic=@/root/test.png --form press=OK 'http://test.com/image/upload?access_token=9574f3307a4b79b73b8abd4d626ba572'  | python -mjson.tool

curl -X POST 'http://gw.api.taobao.com/router/rest' \
-H 'Content-Type:application/x-www-form-urlencoded;charset=utf-8' \
-d 'app_key=12129701' \
-d 'format=json' 

curl -I -H "Host:test.com" "http://183.61.xxx.xxx/file_create_config.php?key=xxxx"

more see man curl

nginx-http-concat

nginx-http-concat是一个nginx扩展模块, 用来合并http请求

1. 下载

访问 https://github.com/alibaba/nginx-http-concat/releases 官网下载最新的源包, 如:

# 下载
wget https://github.com/alibaba/nginx-http-concat/archive/1.2.2.tar.gz

# 解压并记录解压后的目录
tar xzf 1.2.2.tar.gz

2. 安装

# 配置
./configure 其他编译参数 --add-module=/刚才解压的目录

# 安装
[sudo] make
[sudo] make install

如我的配置:

./configure --prefix=/home/work/local/nginx-1.11.2 
    --conf-path=/home/work/local/nginx-conf/conf/nginx.conf 
    --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock 
    --http-client-body-temp-path=/var/cache/nginx/client_temp 
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp 
    --user=nginx 
    --group=nginx 
    --with-http_ssl_module 
    --with-http_realip_module 
    --with-http_dav_module 
    --with-http_gzip_static_module 
    --with-http_v2_module 
    --add-module=/home/work/src/nginx-http-concat-1.2.2

如果有多个 --add-module 分别对应写上即可

3. 配置

使用 location 匹配到你想要匹配的路径, 对其设置参数:

server {
    location /static/css/ {
        concat on;
        concat_types text/css;
        concat_max_files 20;
    }
        
    location /static/js/ {
        concat on;
        concat_types application/javascript;
        concat_max_files 30;
    }
}

重启服务, 如: nginx -s reload

更新配置项点击: https://github.com/alibaba/nginx-http-concat#module-directives

4. 使用

现在就可以通过url中的??来合并了, 比如: /static/css/??a.css,path/b.css

tee

read from stdin, write to stdout AND files.

curl https://github.com/guanhui07 | tee -a ~/test/test.txt

pyenv和virtualenv 使用

mac和 linux 服务器 ,pyenv和virtualenv安装 谷歌的
pip install virtualenv

以下是之前记录的使用
pyenv install 3.6.5

pyenv --help

virtualenv -p ~/.pyenv/versions/3.6.5/bin/python venv
source venv/bin/activate

查看项目package安装列表
pip freeze

python -vvvvv manage.py runserver

chrome Vimium

习惯了vim
然后各种ide 编辑器(sublime vscode,phpstrom pycharm)也装了 vim插件
一直使用vimium 也用了2年多了
但也只是用到 jk gg G

刚按了下? 展示了help 各种命令
常用的按键

j:向下细微滚动窗口 k:向上细微滚动窗口
J:(Shift+j的意思,以下大写全部表示加Shift) 下一个标签页 K:上一个标签页
d:向下滚动半个屏幕 u:向上移动半个屏幕
g+g(连续按两下g):回到顶部
G:到达页面底部
H:后退 L: 前进

f:将当前网页上的所有可见链接/输入框分配一个快捷键如图再按快捷键则可跳转,输入后就可以打开或者跳转到对应的输入框。如果按的是F,那么将在新窗口中打开页面

g+i:将光标 定位到输入框,如果有多个可以按Tab键切换

x:关闭当前页面 X:恢复刚刚关闭的页面

o:相当于Chrome中的地址栏,可以匹配历史记录、收藏夹并在当前窗口打开,或者直接打开一个网址或者搜索一个关键字,如果按的是O,则可以在新窗口中打开,非常非常方便!

g+s:查看网页的源代码
r:重新载入当前网页

其他的后面再研究

linux中编译安装和配置nginx

目录约定

首先约定下一些常用的目录,如:

# 根目录挂载
/约定目录/

    # 安装包目录,存放一些常用的安装包
    ./src/
        ./nginx-1.11.1.tar
        ./node-6.2.2.tar
        ./zlib-1.2.8.tar.gz
        ...

    # 程序目录,存放一些编译后(运行中)的程序,以版本区分
    ./local/
        ./nginx-1.11.1/
        ./nginx-1.0.0/
        ./node-6.2.2/
        ...

    # nginx的配置,先有这个目录,具体作用下面说
    ./nginx-conf/

    # 网站总目录,网站是以域名为文件名存放在该目录下
    ./wwwroot/
        ./www.xuexb.com/
        ./www.a.com/
        ...

编译安装nginx

下载安装包并解压

# 进入约定的安装包目录
cd /约定目录/src/

# 下载nginx安装文件,这里以 nginx-1.11.1 为例,其他的nginx包可以去官网查找
wget http://nginx.org/download/nginx-1.11.1.tar.gz

# 把安装包解压,会自动解压到 /home/src/nginx-1.11.1/ 文件夹里
tar xzf nginx-1.11.1.tar.gz

nginx的配置文件

其实完全可以使用nginx的默认配置文件,默认配置文件编译后的地址在程序目录/conf/nginx.conf,但如果你会频繁的更新nginx版本的话配置文件最后"分离",类似前后端分离一样,这样可以少"吵架"(解耦合),我们单独的把nginx的所有配置,包括所有站点的配置、ssl证书都放在/home/nginx-conf/目录里,如:

/约定目录/local/nginx-conf/

    # nginx配置文件
    ./nginx.conf

    # nginx的其他配置
    ./mime.types

    # 站点配置
    ./conf/
        # www.xxoo.com网站的配置文件
        ./www.xxoo.com.conf
        ./www.a.com.conf
        ...

/约定目录/local/nginx-conf/conf/目录里存放以网站为单位的配置文件,文件名以网站域名命名,这样可以配置分离,互不影响,而且好定位问题。

配置nginx安装参数

# 创建对应版本的程序目录,这个目录用来存放编译后的文件
mkdir -p /约定目录/local/nginx-1.11.1/

# 进入安装包解压后的目录
cd /约定目录/src/nginx-1.11.1/

# 开始配置
./configure --prefix=/home/local/nginx-1.11.1 --conf-path=/home/local/nginx-conf/vhost/nginx.conf --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_dav_module --with-http_gzip_static_module --with-http_v2_module

配置里的一些详情介绍:

--prefix 指向安装目录
--conf-path 指向配置文件(nginx.conf),我们不管后续如何升级nginx,配置文件永远用那一个,这样就分离了
--user= 指定程序运行时的非特权用户
--group= 指定程序运行时的非特权用户组
--with-http_realip_module 启用ngx_http_realip_module支持(这个模块允许从请求标头更改客户端的IP地址值,默认为关)
--with-http_dav_module 启用ngx_http_dav_module支持(增加PUT,DELETE,MKCOL:创建集合,COPY和MOVE方法)默认情况下为关闭,需编译开启
--with-http_gzip_static_module 启用gzip功能

以下是2个可选的,可以删了
--with-http_v2_module 开始http2功能,nginx 1.9.5之后支持该功能,之前叫http_spdy_module
--with-http_ssl_module 开启ssl功能,也就是https,当然你可以删除该参数,开启她需要openssl的依赖,openssl你先看下本机有没有装,没有就下个,百度一堆方法

其他的安装编译配置可点击:nginx编译参数

编译nginx

# 开始编译并安装,可能需要sudo权限
[sudo] make
[sudo] make install

验证是否安装成功

# 进入nginx执行目录
cd /约定目录/local/nginx-1.11.1/sbin/

运行./nginx -v查看版本,结果如:

nginx version: nginx/1.11.1

如果你有开启http_ssl_module,可运行:./nginx -V查看是否支持,结果如:

nginx version: nginx/1.11.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
...

更新版本

当你想升级nginx版本时,可下载、配置、编译安装即可,配置全用/约定目录/local/nginx-conf的,这样对网站的配置无影响,非常方便~

记一次ipython error

ipython
/usr/local/Cellar/ipython/6.3.1/libexec/bin/ipython: line 3: requires: command not found

/usr/local/opt/python/bin/python3.6 

这个找不到

第一反应
python3.6升级到了python3.7

ls /usr/local/opt/python/bin/
果然只有python3.7的文件

好吧让ipython也用python3.7

brew uninstall ipython

brew install python

开发还是使用自定义版本pyvenv python3.6

Things use in mac 2018

Things use in mac 2018 -08

work:

brew
vim
zsh
mycli
phpstorm
SecureCRT
Sublime
Vscode
Atom
Sequel Pro
Marta
CotEditor
Pycharm
MindNote
Mou
Xmind
rdm
Evernote
Vmware
Snipaste
Shadowsocks
f.lux
Snipaste
ngrok
openresty
mysql5.7
redis
php72
python3.7
mongodb
postgresql
ipython
bpython

chrome扩展:
Vimium
Server ip
Auto Refresh
Evernote Web Clipper
EditThisCookie
iFormatTool
JSONView
LastPass
Ohrz IP
OneTab
Set Character Encoding
v2ex plus
WEB前端助手(FeHelper)
新浪微博图床
网页截图:注释&录屏
postman
Octotree
MetaMast
google translate
右键搜
oscnews
Momentum
SwitchyOmega

mac很多软件都收费,贴个地址开源软件
https://github.com/serhii-londar/open-source-mac-os-apps/blob/master/README.md

https://jeffjade.com/2017/01/23/118-chrome_awesome_plug-in/?hacpai

nginx设置主域301重定向

配置文件核心:

server {
    # 设置多个域名
    server_name www.test.com test.com;
    #return 301 https://$host$request_uri;
    # 判断host是不是test.com,如果不是则直接301重定向,permanent表示301
    if ( $host != 'test.com' ){
        rewrite ^/(.*)$ http://test.com/$1 permanent;
    }
}

nginx配置url重写

url重写是指通过配置conf文件,以让网站的url中达到某种状态时则定向/跳转到某个规则,比如常见的伪静态、301重定向、浏览器定向等

rewrite

语法

在配置文件的server块中写,如:

server {
    rewrite 规则 定向路径 重写类型;
}
  • 规则:可以是字符串或者正则来表示想匹配的目标url
  • 定向路径:表示匹配到规则后要定向的路径,如果规则里有正则,则可以使用$index来表示正则里的捕获分组
  • 重写类型:
    • last :相当于Apache里德(L)标记,表示完成rewrite,浏览器地址栏URL地址不变
    • break;本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变
    • redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
    • permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址

简单例子

server {
    # 访问 /last.html 的时候,页面内容重写到 /index.html 中
    rewrite /last.html /index.html last;

    # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配
    rewrite /break.html /index.html break;

    # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中
    rewrite /redirect.html /index.html redirect;

    # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中
    rewrite /permanent.html /index.html permanent;

    # 把 /html/*.html => /post/*.html ,301定向
    rewrite ^/html/(.+?).html$ /post/$1.html permanent;

    # 把 /search/key => /search.html?keyword=key
    rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}

last和break的区别

因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:

  • last一般写在server和if中,而break一般使用在location中
  • last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
  • break和last都能组织继续执行后面的rewrite指令

location里一旦返回break则直接生效并停止后续的匹配location

server {
    location / {
        rewrite /last/ /q.html last;
        rewrite /break/ /q.html break;
    }

    location = /q.html {
        return 400;
    }
}
  • 访问/last/时重写到/q.html,然后使用新的uri再匹配,正好匹配到locatoin = /q.html然后返回了400
  • 访问/break时重写到/q.html,由于返回了break,则直接停止了

if判断

只是上面的简单重写很多时候满足不了需求,比如需要判断当文件不存在时、当路径包含xx时等条件,则需要用到if

语法

if (表达式) {
}
  • 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
  • 直接比较变量和内容时,使用=或!=
  • 正则表达式匹配,*不区分大小写的匹配,!~区分大小写的不匹配

一些内置的条件判断:

  • -f和!-f用来判断是否存在文件
  • -d和!-d用来判断是否存在目录
  • -e和!-e用来判断是否存在文件或目录
  • -x和!-x用来判断文件是否可执行

内置的全局变量

$args :这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同。

如:

访问链接是:http://localhost:88/test1/test2/test.php 
网站路径是:/var/www/html

$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php

例子

# 如果文件不存在则返回400
if (!-f $request_filename) {
    return 400;
}

# 如果host不是test.com,则301到test.com中
if ( $host != 'test.com' ){
    rewrite ^/(.*)$ https://test.com/$1 permanent;
}

# 如果请求类型不是POST则返回405
if ($request_method = POST) {
    return 405;
}

# 如果参数中有 a=1 则301到指定域名
if ($args ~ a=1) {
    rewrite ^ http://example.com/ permanent;
}

在某种场景下可结合location规则来使用,如:

# 访问 /test.html 时
location = /test.html {
    # 默认值为xiaowu
    set $name xiaowu;

    # 如果参数中有 name=xx 则使用该值
    if ($args ~* name=(\w+?)(&|$)) {
        set $name $1;
    }

    # 301
    rewrite ^ /$name.html permanent;
}

上面表示:

  • /test.html => /xiaowu.html
  • /test.html?name=ok => /ok.html?name=ok

location

语法

server块中使用,如:

server {
    location 表达式 {
    }
}

location表达式类型

  • 如果直接写一个路径,则匹配该路径下的
  • ~ 表示执行一个正则匹配,区分大小写
  • ~* 表示执行一个正则匹配,不区分大小写
  • ^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location。
  • = 进行普通字符精确匹配。也就是完全匹配。

优先级

  1. 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
  2. ^~类型表达式。一旦匹配成功,则不再查找其他匹配项。
  3. 正则表达式类型(~ ~*)的优先级次之。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个。
  4. 常规字符串匹配类型。按前缀匹配。

例子 - 假地址掩饰真地址

server {
    # 用 xxoo_admin 来掩饰 admin
    location / {
        # 使用break拿一旦匹配成功则忽略后续location
        rewrite /xxoo_admin /admin break;
    }

    # 访问真实地址直接报没权限
    location /admin {
        return 403;
    }
}

匹配小提示

server {
    # 用if匹配任何以 403 开头的, 会匹配到 /4034444  /403aaa /403/
    if ($request_uri ~* ^/403) {
        return 403;
    }

    # 用location匹配 /500/ /500, 但不匹配 /500/1
    location ~* "^/500/?$" {
        return 500;
    }

    # 用if匹配以 /501/ 开头的, 匹配 /501/1, /501/1/2 但不匹配 /501
    if ($request_uri ~* ^/501/) {
        return 501;
    }

    # 用location匹配 /502/ /502 /502/1 /502/1/2
    location ~* "^/502(/.*)?$" {
        return 502;
    }

    # 用location只匹配 /503
    location = /503 {
        return 503;
    }

    # 用location只匹配 /503
    location = /503 {
        return 503;
    }

    # 用location匹配 /504/  /504/1  但不匹配 /504
    location /504/ {
        return 504;
    }
}

参数链接

参考 Nginx location在配置中的优先级

nginx配置泛域名转发

有的时候,我们需要配置一些自定义的子域名,如:

  • test.user.demo.com
  • a01.user.demo.com

这时候就需要域名的 DNS 解析一个泛域名 *.user.demo.com 到服务器,Nginx 可以配置如下:

子域名转发到子目录

server {
    listen       80;
    server_name ~^([\w-]+)\.user\.demo\.com$;

    location / {
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        Host $http_host;
        proxy_set_header        X-NginX-Proxy true;
        proxy_pass              http://127.0.0.1:8080/$1$request_uri;
    }
}

以上配置表示:

  • test.user.demo.com/path?a=1 -> 127.0.0.1:8080/test/path?a=1
  • a01.user.demo.com/path?a=1 -> 127.0.0.1:8080/a01/path?a=1

这样后端就可以根据子目录解析不同的规则,甚至 Nginx 可以再进行链接重写。

子域名配置不同的目录

server {
    listen       80;
    server_name ~^([\w-]+)\.user\.demo\.com$;

    root /home/user/wwwroot/user/$1;
}

以上配置可以把不同的子域名分发到不同的目录中,做到路径分离的功能,如:

  • test.user.demo.com -> /home/user/wwwroot/user/test;
  • a01.user.demo.com -> /home/user/wwwroot/user/a01;

MacOS 清除DNS缓存

MacOS Hight Sierra清除DNS缓存

在Mac机器Terminal终端通过ping命令探测域名的时候,一直卡顿ping没有响应;但是通过ping服务器IP的时候却能正常ping通。

这个时候需要检查域名是否正确指向到该服务器IP,如果也做好了域名解析,还是ping不通的话。可以通过下面的命令试着清除一下Mac的DNS缓存。

sudo dscacheutil -flushcache;sudo killall -HUP mDNSResponder;

上面的命令如果没有返回值则表示执行成功。请在Terminal终端再尝试ping域名试试?

参考地址

Unicode and utf8

Unicode预订的编码空间大小为0x0-0x10FFFF,最多可以容纳1114112(100多万)个字符

实际上并不能使用这么多的空间,于是编码方式出现了两种,ucs-2(BMP)和ucs-4 编码方式
其中,bmp是Basic Multilingual Plane的简写.

一个字符的Unicode编码(码点)是唯一确定的,但由于不同系统平台实现方式的不同(如字节序的不同),或基于传输或节省存储空间等各种因素考虑,Unicode的实现方式各不相同,Unicode的实现方式称为Unicode转换格式(Unicode Translation Format,简称为UTF)

如UTF-16
UTF-16采用双字节对UCS-2字符进行编码,由于UCS-2本身也是双字节编码,故一般UTF-16编码和UCS-2编码可等同对待,但由于不同平台对字节序的理解不同,
UTF-16又分为UTF-16 BE(Big-Endian, 简写为UTF-16 BE)和UTF-16 LE(Little-Endian,简写为UTF-16 LE)两种编码方式.

UTF-16编码的优点:编码效率高,寻址快。
由于所有字符都采用双字节编码,可以快速对字符进行定位及计算,如一个文本文件,可以通过获得其文件大小/2即可计算得知包含的字符数。Java默认使用UTF-16 BE编码。

那么为什么会出现utf-8呢:
1)、和ASCII码不兼容,而且不太好移植(Not Portable)
例如:char *s=“Good ,北京”;该C语言代码采用UTF-16编码后,字节序列中间有许多’\0’,’\0’ 会被识别为字符串的终止,strlen()函数不起用了。
2)、存储空间较大,造成存储及带宽的极大浪费
极端情况下,英文存储空间会Double!
为了解决这些现实生活中遇到的问题,UTF-8编码应运而生!

言归正传,对于UTF-8
UTF-8是针对Unicode(UCS-2或UCS-4)的可变长度编码方式,是一种前缀码,它可用来编码Unicode中的任何一个字符。UTF-8编码和ASCII码全兼容,自应用以来逐渐成为电子邮件、网页及其他存储或传送文字应用中,最优先采用的Unicode编码方式。

如果有兴趣,可以延伸阅读RFC:
http://www.rfc-editor.org/rfc/rfc3629.txt

谈论个php面试题

看到个讨论面试题

echo '1' . print(2) + 3;

输出啥

鸟哥说:运行下,不就知道。

分析下:
print(2)+3

先输出5
print 不是函数 可以不用括号括起来,是语言结构

'1'.print(2)+3 相当于'1'.'1'

print 返回值是1

5是由 print输出的,先执行了
11 是由 "1"."1" 得到的 后一个1,是print的返回值

这样写有什么好处么
面试要出这样的题
这样写有提高性能吗?

并不会

自定义函数实现了一下这道题

echo '1' . _print((2) + 3);
function _print($a){
    echo $a;
    return 1;
}

消遣下还行,拿来面试和写代码真是作死

511

nginx配置图片防盗链

防盗链是指当图片不是自己网站打开时返回403或者指定图片,是通过请求的来路判断是否是自己的站点来设置响应

语法

valid_referers none | blocked | server_names | string

  • none: 表示没有来路
  • blocked: 表示有来路
  • server_names: 来路里包含当前域名
  • string(忽略端口)

以上参数可以叠加一起使用

例子

server {

    # 配置所有图片
    location ~* \.(gif|jpg|png|bmp)$ {
        # 验证可以是没有来路、或者有来路时来路匹配test.com、或者匹配当前域名
        valid_referers none blocked *.test.com server_names;

        # 如果验证不通过则返回403
        if ($invalid_referer) {
            return 403;
        }
    }
}

mysql command notes : show status

命令: show status;

命令:show status like '%下面变量%';

关键字 说明
Aborted_clients 由于客户没有正确关闭连接已经死掉,已经放弃的连接数量。
Aborted_connects 尝试已经失败的MySQL服务器的连接的次数。
Connections 试图连接MySQL服务器的次数。
Created_tmp_tables 当执行语句时,已经被创造了的隐含临时表的数量。
Delayed_insert_threads 正在使用的延迟插入处理器线程的数量。
Delayed_writes 用INSERT/DELAYED写入的行数。
Delayed_errors 用INSERT/DELAYED写入的发生某些错误(可能重复键值)的行数。
Flush_commands 执行FLUSH命令的次数。
Handler_delete 请求从一张表中删除行的次数。
Handler_read_first 请求读入表中第一行的次数。
Handler_read_key 请求数字基于键读行。
Handler_read_next 请求读入基于一个键的一行的次数。
Handler_read_rnd 请求读入基于一个固定位置的一行的次数。
Handler_update 请求更新表中一行的次数。
Handler_write 请求向表中插入一行的次数。
Key_blocks_used 用于关键字缓存的块的数量。
Key_read_requests 请求从缓存读入一个键值的次数。
Key_reads 从磁盘物理读入一个键值的次数。
Key_write_requests 请求将一个关键字块写入缓存次数。
Key_writes 将一个键值块物理写入磁盘的次数。
Max_used_connections 同时使用的连接的最大数目。
Not_flushed_key_blocks 在键缓存中已经改变但是还没被清空到磁盘上的键块。
Not_flushed_delayed_rows 在INSERT/DELAY队列中等待写入的行的数量。
Open_tables 打开表的数量。
Open_files 打开文件的数量。
Open_streams 打开流的数量(主要用于日志记载)
Opened_tables 已经打开的表的数量。
Questions 发往服务器的查询的数量。
Slow_queries 要花超过long_query_time时间的查询数量。
Threads_connected 当前打开的连接的数量。
Threads_running 不在睡眠的线程数量。
Uptime 服务器工作了多少秒。

配置nginx前置缓存

http {
    # 定义缓存名称、目录、类型
    proxy_cache_path    /home/proxy/cache levels=1:2 keys_zone=nginx_cache:100m inactive=30d max_size=1g;
    proxy_temp_path     /home/proxy/temp;
    proxy_cache_key     $host$uri$is_args$args;   

    server {
        # 定义缓存的规则
        location ~ ^/(static|upload)\/(.*)$ {
            proxy_connect_timeout    10s;
            proxy_read_timeout       10s;
            proxy_cache              nginx_cache;
            proxy_cache_valid        200 30d;
            proxy_cache_lock         on;
            proxy_cache_lock_timeout 5s;
            proxy_cache_use_stale    updating error timeout invalid_header http_500 http_502;

            # 添加缓存的标识到header头
            add_header               X-Cache "$upstream_cache_status from cache.xuexb";

            expires                  1d;
            proxy_set_header Connection "";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;

            # 目标机器
            proxy_pass  http://blog;
        }
    }
}

nginx日志切割-shell

nginx日志切割-shell脚本

由于nginx的日志(包括access和error)默认都是存放在一个文件内, 当时间长了, 日志文件体积越来越大, 不易管理, so, 可以自己写个shell脚本来处理, 其实就是定时定点去把日志移动下位置...

#!/bin/sh

# 日志源目录
sourceDir='/var/log/nginx/test.com/last'

# 日志备份目录
backDir='/var/log/nginx/test.com/back'

echo "split-logs start: $(date +%Y-%m-%d %H:%M:%S)"

ls $sourceDir | while read filename
do
    mkdir -p "$backDir/$(date +%Y%m%d)/"
    mv "$sourceDir/$filename" "$backDir/$(date +%Y%m%d)/"
    echo "$sourceDir/$filename => $backDir/$(date +%Y%m%d)/$filename"
done

# 刷新nginx
kill -USR1 `cat /var/run/nginx.pid`

echo "split-logs end: $(date +%Y-%m-%d %H:%M:%S)"
echo "----------------"

有几个注意:

  1. 日志源目录 - 该目录存放日志文件, 如 access.log, error.log, 当然如果你的站点比较多, 可以用域名来命名, 比如: test.com.access.log, test.com.error.log
  2. 日志备份目录 - 会以Ymd命名文件夹名存放在该目录
  3. 刷新nginx - 由于是直接移动日志文件, 移动后需要刷新下nginx使其再生成日志文件, 当然也可以nginx -s reload, 但reload要比kill的慢
  4. 定时任务 - 使用crontab -e插入一条定时任务, 定时23:55开始分割, 后面是把错误和信息输出到指定文件, 方便调试, 如:
55 23 * * * sh /你的目录/split-log >> /var/log/nginx/crontab.log 2>&1

这只是日志切割的一种, 还有很多种方法~

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.