ack 是一个代码搜索工具,作者 厌烦了 grep 复杂的语法,所以创造了 ack 来解决痛点。ack 使用 Perl 语言开发,使用友好,速度快。ack 在大量代码文件中的搜索效率极高。
sudo apt-get install ack-grep
默认情况下 ack-grep
会搜索当前目录下所有文件内容,只要包含关键字就会输出。
ack-grep keyword
ack-grep -l keyword # 只显示文件名
ack-grep -i keyword # 忽略大小写
ack-grep -w keyword # 强制要求 PATTERN 匹配整个单词
可以代替 find 加 grep,其实 ack 的 -f
选项表示的是打印所有将要被搜索的文件,事实上不会执行搜索,如果后面加 PATTERN ,那么就在路径中搜索文件名。-g
选项表示的是搜索当前路径下的符合 PATTERN 的文件。
ack-grep -f filename
ack-grep -g file*
可以使用 --python
选项来指定在 python 文件中搜索
ack-grep --python keyword
使用编译安装 Nginx,将 ngx_http_substitutions_filter_module
和 ngx_http_google_filter_module
两个模块编译进 Nginx。具体内容可以参考安装篇。
对于 Nginx 基本设置可以参考 配置篇 .
这篇主要演示 Nginx 作为一个反向代理服务器的基本设置。
Nginx 反向代理最重要的一个配置就是 proxy_pass
,该配置接受一个参数, URL ,也就是 Nginx 转发的目的地。Nginx 会自动将请求的 URI 替换为 proxy_pass
配置的 URI。
location /uri {
proxy_pass http://localhost:8083/newUri;
}
反向代理的常用配置选项
Directive | Explanation |
---|---|
proxy_connect_timeout |
向上游服务器请求超时时间 |
proxy_cookie_domain |
将请求头中 Set-Cookie 头内容替换成新域名 |
proxy_cookie_path |
替换 Set-Cookie 中路径 |
proxy_headers_hash_bucket_size |
请求头名最大size |
proxy_headers_hash_max_size |
从上游服务器接收到的所有 headers 总量 |
proxy_hide_header |
一组不会被传给 client 的 headers |
proxy_http_version |
和上游服务器通信使用的 HTTP 协议版本 |
proxy_ignore_client_abort |
如果设置为 on, Nginx 在client 停止请求时不会停止向上游服务器请求 |
proxy_ignore_headers |
处理上游服务器返回时设置一组不处理 headers |
proxy_intercept_errors |
设置开启, Nginx 将显示 error_page 配置的错误而不会向上游服务器请求 |
proxy_max_temp_file_size |
The maximum size of the overflow file, written when the response doesn’t fit into memory buffers. |
proxy_pass |
上游服务器 URL |
proxy_pass_header |
覆盖被 proxy_hide_header 配置禁用的 headers,允许他们发送给客户端 |
proxy_pass_request_body |
off 时阻止向上游服务器发送请求body |
proxy_pass_request_headers |
off 时阻止向上游服务器发送 headers |
proxy_read_timeout |
连接关闭前,向上游服务器两次读成功耗时 |
proxy_redirect |
Rewrites the Location and Refresh headers received from the upstream servers; useful for working around assumptions made by an application framework. |
proxy_send_timeout |
连接关闭前,向上游服务器两次写成功耗时 |
proxy_set_body |
修改请求body |
proxy_set_header |
修改请求 headers |
proxy_temp_file_write_size |
限制单个请求的临时文件大小, Nginx 不会在一个请求上被 block |
proxy_temp_path |
临时文件地址 |
Directive | Explanation |
---|---|
ip_hash |
使得客户端的请求能够均匀的分布 |
keepalive |
每一个 worker process 向上游服务器请求缓存的连接数,proxy_http_version 需要设置为 1.1 并且 proxy_set_header 设置为空 |
least_conn |
负载均衡算法,根据 active 连接数来选择下一个连接 |
server |
设置地址,域名或者 IP,或者 Unix-domain socket 一些选项 weight: 设置 server 的权重,max_fails : 重试最大次数,fail_timeout : 服务器超过该时间会被标记为 Down ,backup : 只有其他机器都 Down 情况下才会使用该服务器,down : 标记为 down 不会处理请求 |
以如下配置示例
upstream apache {
server 127.0.0.1:8080;
keepalive 32;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://apache;
}
假设定义了 apache upstream ,使用 Nginx 转发到本地 8080 端口, 设置了 keepalive 为 32。每一个 Nginx worker 只会在最初始化时TCP握手建立32个连接,Nginx 会保存连接,不会发送 close
。
如果需要超过 32 个连接, Nginx 会再新建连接满足需求,如果需求降低, Nginx 会自动将超过 32 个连接的请求,按照最近使用的连接关闭,直到将连接数降到 32 。
upstream 模块会使用三种算法来选择向哪一台上游服务器建立连接—- round-robin, IP hash, 或者是 least connections.
round-robin 算法是默认值,算法根据上一次选择的服务器决定下一次选择哪一条连接,算法公平的根据 turn by turn 的方式来保持平衡。
IP hash 算法,需要通过 ip_hash
指令开启
Nginx 使用 IPv4 地址的前三个字节或者是整个 IPv6 地址作为 hashing key 。因此一组IP地址永远被map到特定的上游服务器。因此这个机制不是设计为均匀分发请求,而是被设计成将客户端和上游服务器映射到一起。
第三种负载均衡算法叫做 least connections , 通过 least_conn
开启。该算法设计成将负载均匀的打到上游服务器中,通过选择活跃连接数最小的服务器。如果上游服务器不是具有相同的处理能力,可以通过指定 weight
来人为处理。算法会将不同 weight 的服务器纳入计算活跃连接数的考虑范畴。
创建一个 Ngixn 虚拟主机,我使用 https://g.einverne.info
来演示:
# 配置 google ip 地址,使用 nslookup google.com 来获取 Google 服务器地址,避免 Google 机器人检测
upstream www.google.com {
server XXX.XXX.XXX.XXX:443 weight=1; #把XXX替换成可用 IP
server XXX.XXX.XXX.XXX:443 weight=1;
server XXX.XXX.XXX.XXX:443 weight=1;
server XXX.XXX.XXX.XXX:443 weight=1;
server XXX.XXX.XXX.XXX:443 weight=1;
server XXX.XXX.XXX.XXX:443 weight=1;
server 216.58.216.163:443 weight=1; #hk
}
server {
listen 80;
listen [::]:80;
server_name g.einverne.info;
listen 443 ssl;
ssl_certificate path_to_ssl_crt; # 证书
ssl_certificate_key path_key; # key
# 自动 http 转 https
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
if ($http_user_agent ~* (baiduspider|360spider|haosouspider|googlebot|soso|bing|sogou|yahoo|sohu-search|yodao|YoudaoBot|robozilla|msnbot|MJ12bot|NHN|Twiceler)) {
return 403;
}
# 编译时加入 ngx_http_google_filter_module 模块,location 如下设置
location / {
google on;
}
access_log /var/log/nginx/g.einverne.info.access.log;
error_log /var/log/nginx/g.einverne.info.error.log;
}
如果编译时没有加入 ngx_http_google_filter_module
模块,则需要设置 location
location / {
proxy_redirect off;
proxy_cookie_domain google.com <domain.name>;
proxy_pass https://www.google.com;
proxy_connect_timeout 60s;
proxy_read_timeout 5400s;
proxy_send_timeout 5400s;
proxy_set_header Host "www.google.com";
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Referer https://www.google.com;
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Language "zh-CN";
proxy_set_header Cookie "PREF=ID=047808f19f6de346:U=0f62f33dd8549d11:FF=2:LD=en-US:NW=1:TM=1325338577:LM=1332142444:GM=1:SG=2:S=rE0SyJh2W1IQ-Maw";
subs_filter https://www.google.com.hk <domain.name>;
subs_filter https://www.google.com <domain.name>;
#subs_filter_types text/css text/xml text/javascript;
sub_filter_once off;
}
proxy_redirect
设置为 off ,不需要重写 Location 的 headerproxy-cookie-domain google <domain.name>;
将cookie作用域替换成自己的域名proxy_pass https://www.google.com;
反向代理到 upstream www.google.comproxy_set_header Accept-Encoding "";
防止谷歌返回压缩的内容,否则内容无法替换proxy_set_header Cookie
这一行 禁止即时搜索,设置为新窗口打开网站subs_filter https://www.google.com <domain.name>;
把Google域名替换,需要编译时加上 --with-http_sub_module
参数Nginx 的相关介绍及安装可以参考之前的一篇文章
Nginx 相关的配置, Nginx 中的配置有两种分类,一种为单纯的指令 (directive),另一种为上下文配置块 (configuration context)。
指令 (directive),包含名称和参数名,以分号结束,比如
gzip on;
上下文通常声明一个作用域,比如 server 块
server {
listen 80;
}
在上下文中使用相同的指令时需要小心,一般子级上下文中的指令会覆盖父级中定义的值。
Nginx 的全局配置是影响整个 WEB 服务器的配置。
主要有以下几个
Directive | Explanation |
---|---|
user | worker process 在配置的 user and group 下运行 |
workr_processes | 最多的 worker processes 数量,可支持并发数,通常的做法是指定和 CPU cores 数量一致 |
error_log | log |
pid | file where the process ID of the main process is written |
use | 连接方式 |
worker_connections | 连接数 |
配置 Nginx 运行的用户和用户组:
user user [group];
希望所有用户都可以启动 Nginx 进程,一种是直接注释该配置,或者
user nobody nobody;
Nginx 配置文件中,每一条配置都必须以分号结束。
worker process 是 Nginx 并发关键所在,设置的是 Nginx 的进程数,理论上 worker process 值越大,可支持并发数也越多,但实际也受到软件,操作系统,硬件(CPU 和磁盘)等资源的制约。建议设置为 CPU 核心数。
worker_processes number | auto;
Nginx 进程作为系统守护进程运行,在文件中保存当前运行程序主进程号,支持配置 PID
pid file_path;
file_path
为存放路径和文件名全局块、http 块 和 server 块都可以对 Nginx 日志进行配置
error_log file | stderr [debug | info | notice | warn | error |crit | alert | emerg];
Nginx 日志支持输出到文件 file, 或者标准错误输出 stderr.
日志级别可选,从低到高 debug, info, notice, warn, error, crit, alert, emerg ,需要注意的是 debug 需要编译时使用 --with-debug
开启。
Nginx 提供 include 配置来引入其他文件
include file;
include server/*
设置每一个 worker process 同时开启的最大连接数
worker_connections number;
只能在 events 块中配置
浏览器使用 MIME Type 来区分不同的媒体类型, Nginx 作为 Web 服务器,必须能够识别前端请求的资源类型。
默认的配置中,可以使用两种方式来配置
include mime.types;
default_type application/octet-stream
第一种方式引用外部文件。
mime.types
文件
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
image/svg+xml svg svgz;
image/webp webp;
application/font-woff woff;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.wap.wmlc wmlc;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
文件中包含了浏览器能够识别的 MIME 类型,以及对应的文件后缀名。
第二种方式使用 default_type mime-type
直接配置。
与 error_log
不同的是,Nginx 进程运行时访问日志,由 Nginx 提供服务过程中应答前端请求的日志。
Nginx 服务器支持对服务日志的格式、大小、输出等进行配置,需要使用两个配置 access_log
和 log_format
access_log path [format [buffer=size]];
log_format
配置指定好,直接引用格式名如果要取消记录日志功能,使用
access_log off;
自定义日志格式
log_format name string ...;
示例,配置如下两行
log_format exampleLog '$remote_addr - [$time_local] $request '
'$status $body_bytes_sent '
'$http_referer $http_user_agent';
access_log /var/log/nginx/access.log exampleLog;
查看日志 tailf /var/log/nginx/access.log
47.88.236.38 - [24/Oct/2017:10:25:30 +0800] GET /post/2017/10/things-to-do-after-install-wordpress.html?ajax_load=page HTTP/1.1 200 6961 https://www.einverne.info/ Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
可以查看到上面格式的日志,IP 本地时间 请求方法 请求路径 HTTP 状态 发送数据大小 以及 HTTP refer 和 User Agent
.
用户连接会话连接后, Nginx 服务器可以保持打开一段时间
keepalive_timeout timeout [header_timeout];
header_timeout
可选,在 Response 头部 Keep-Alive
域设置超时时间示例
keepalive_timeout 120s 100s;
限制用户通过某一个连接向 Nginx 发送请求次数
keepalive_requests number;
虚拟主机配置以 server
开头,server 内的配置都认为是 虚拟主机 配置。虚拟主机定义了一套由不同 server_name
配置区分的资源。虚拟主机一般由 listen
、server_name
等一组配置决定。
监听配置方法主要有三种:
第一种配置监听 IP 地址
listen address[:port] [default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [deferred] [accept_filter=filter] [bind] [ssl];
第二种配置监听端口
listen port [default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [ssl];
第三种配置 UNIX Domain Socket
listen unix:path [default_server] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ssl];
default_server
将虚拟主机地址设置为 address:port 为默认主机是指 server 块对外提供虚拟主机
server_name name ...;
名字就是域名,用空格隔开
server_name einverne.info www.einverne.info;
Nginx 规定第一个名称作为虚拟主机的主要名
name 中可以使用通配符 *
,但通配符只能放到首尾,name 中还能使用正则表达式,使用 ~
开始
server_name ~^ww\d+\.einverne\.info$;
匹配 ww1.einverne.info
但不匹配 www.einverne.info
对于不同的匹配方式,Nginx 按照如下优先级选择虚拟主机
server_name
server_name
成功server_name
成功在以上四种匹配方式中,如果 server_name
被处于同一优先级匹配方式匹配多次成功,则首次匹配成功的虚拟主机处理请求。
不是很常用,暂时略
location 指令在 virtual server 部分使用,用来比欧式 URI 怎么处理。
语法
location [ = | ~ | ~* | ^~ ] uri { ... }
其中,uri 变量是待匹配的请求字符串,可以是不含正则表达的字符串。
方括号中为可选项,不添加可选项时, Nginx 首先在 server 块多个 location 块中搜索是否有匹配,如果有多个匹配,就记录匹配度最高的一个。然后,Nginx 再用 location 块中的正则 uri 和请求匹配,当第一个正则匹配成功,结束搜索,并使用该 location 块处理请求,如果正则全部失败,则使用刚才记录的匹配度最高的 location 块处理该请求。
了解了 location 块匹配规则,再来看一下各个可选项的含义:
=
用于非正则 uri 前,要求字符串与 uri 严格匹配,如果匹配成功,则停止向下搜索,并立即处理此请求~
表示该 uri 包含正则,并且区分大小写~*
表示 uri 包含正则,不区分大小写^~
用于非正则 uri 前,Nginx 服务器找到标示 uri 和请求字符串匹配程度最高的 location 后立即使用该 location 处理请求,不再匹配 location 块的正则 url如果 uri 包含正则,则必须使用 ~
和 ~*
。 而对于 ^~
会对 uri 中的 urlencode 内容解码, %20
会被理解为空格。
Nginx 接受到请求之后,在服务器指定目录中寻求资源
root path;
path 为 Nginx 接受到请求之后查找资源的根目录路径。 path 变量可以包含 Nginx 服务器预设的大多数变量,但要注意 $document_root
和 $realpath_root
不可用。
该配置可以再 http 块、 server 块或者 location 块中进行配置。
在 location 块中,除了使用 root 命令指明请求处理根目录,还可以使用 alias 配置来改变 location 接收到的 URI 请求
alias path;
path 就是修改后的根路径。
示例
location ~ ^/data/(.+\.(htm|html)) $ {
alias /var/www/data/$1;
}
当 location 块接收到 /data/index.html
请求时,匹配成功,根据 alias 配置, Nginx 在 /var/www/data/
目录下找到 index.html
并响应请求。
在用户发出请求时,请求地址可以不填写首页完整路径
index file ...;
指定错误页面
error_page code ... [=[response]] uri
示例
error_page 404 /404.html
Nginx 支持两种途径的基本访问控制,一种是由 HTTP 标准模块的 ngx_http_access-modele
支持,通过 IP 来判断客户端是否拥有对 Nginx 的访问权限
allow 配置用于设置 Nginx 客户端 IP 访问
allow address | CIDR | all;
deny 配置,顾名思义
deny address | CIDR | all;
参数含义同上
Nginx 对于访问控制权限是顺序匹配,如果匹配成功就不会继续向下解析。
Nginx 支持 HTTP Basic Authentication 协议的认证,该协议是一种 HTTP 性质的认证办法,需要用户名和密码,认证失败的客户端不拥有访问 Nginx 服务器的权限。
开启或者关闭
auth_basic string | off;
off 关闭该功能
auth_basic_user_file file;
其中 file 为密码文件的绝对路径
使用如下命令创建用户名密码到文件
printf "yourusername:$(openssl passwd -apr1)" > /etc/nginx/passwords
记住替换 yourusername
,该命令会在 /etc/nginx
目录下创建 passwords 文件,该文件的格式为
yourusername:passwordencrypt
也可以使用 htpasswd
命令来生成,绝大部分语言提供 crypt()
函数来对加密密码
htpasswd -c -d /etc/nginx/passwords yourusername
然后添加如下配置
server {
# ...
auth_basic "Protected";
auth_basic_user_file passwords;
# ...
}
简单配置
server
{
listen 80;
server_name g.einverne.info;
location / {
proxy_pass http://www.google.com/; #反代的域名
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
######Nginx配置文件nginx.conf中文详解#####
#定义Nginx运行的用户和用户组
user www www;
#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;
#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /usr/local/nginx/logs/error.log info;
#进程pid文件
pid /usr/local/nginx/logs/nginx.pid;
#指定进程可以打开的最大描述符:数目
#工作模式与连接数上限
#这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
#现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
#这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
worker_rlimit_nofile 65535;
events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
#是Linux 2.6以上版本内核中的高性能网络I/O模型,linux建议epoll,如果跑在FreeBSD上面,就用kqueue模型。
#补充说明:
#与apache相类,nginx针对不同的操作系统,有不同的事件模型
#A)标准事件模型
#Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
#B)高效事件模型
#Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
#Epoll:使用于Linux内核2.6版本及以后的系统。
#/dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
#Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
use epoll;
#单个进程最大连接数(最大连接数=连接数*进程数)
#根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
worker_connections 65535;
#keepalive超时时间。
keepalive_timeout 60;
#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
#分页大小可以用命令getconf PAGESIZE 取得。
#[root@web001 ~]# getconf PAGESIZE
#4096
#但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
client_header_buffer_size 4k;
#这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache max=65535 inactive=60s;
#这个是指多长时间检查一次缓存的有效信息。
#语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
open_file_cache_valid 80s;
#open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
#语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location 这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
open_file_cache_min_uses 1;
#语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件时记录cache错误.
open_file_cache_errors on;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http
{
#文件扩展名与文件类型映射表
include mime.types;
#默认文件类型
default_type application/octet-stream;
#默认编码
#charset utf-8;
#服务器名字的hash表大小
#保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.
server_names_hash_bucket_size 128;
#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
client_header_buffer_size 32k;
#客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。
large_client_header_buffers 4 64k;
#设定通过nginx上传文件的大小
client_max_body_size 8m;
#开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
#sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
sendfile on;
#开启目录列表访问,合适下载服务器,默认关闭。
autoindex on;
#此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
tcp_nopush on;
tcp_nodelay on;
#长连接超时时间,单位是秒
keepalive_timeout 120;
#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#开启限制IP连接数的时候需要使用
#limit_zone crawler $binary_remote_addr 10m;
#负载均衡配置
upstream jh.w3cschool.cn {
#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
#nginx的upstream目前支持4种方式的分配
#1、轮询(默认)
#每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
#2、weight
#指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
#例如:
#upstream bakend {
# server 192.168.0.14 weight=10;
# server 192.168.0.15 weight=10;
#}
#2、ip_hash
#每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
#例如:
#upstream bakend {
# ip_hash;
# server 192.168.0.14:88;
# server 192.168.0.15:80;
#}
#3、fair(第三方)
#按后端服务器的响应时间来分配请求,响应时间短的优先分配。
#upstream backend {
# server server1;
# server server2;
# fair;
#}
#4、url_hash(第三方)
#按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
#例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
#upstream backend {
# server squid1:3128;
# server squid2:3128;
# hash $request_uri;
# hash_method crc32;
#}
#tips:
#upstream bakend{#定义负载均衡设备的Ip及设备状态}{
# ip_hash;
# server 127.0.0.1:9090 down;
# server 127.0.0.1:8080 weight=2;
# server 127.0.0.1:6060;
# server 127.0.0.1:7070 backup;
#}
#在需要使用负载均衡的server中增加 proxy_pass http://bakend/;
#每个设备的状态设置为:
#1.down表示单前的server暂时不参与负载
#2.weight为weight越大,负载的权重就越大。
#3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
#4.fail_timeout:max_fails次失败后,暂停的时间。
#5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
#nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
#client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
#client_body_temp_path设置记录文件的目录 可以设置最多3层目录
#location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
}
#虚拟主机的配置
server
{
#监听端口
listen 80;
#域名可以有多个,用空格隔开
server_name www.w3cschool.cn w3cschool.cn;
index index.html index.htm index.php;
root /data/www/w3cschool;
#对******进行负载均衡
location ~ .*.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
#图片缓存时间设置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}
#JS和CSS缓存时间设置
location ~ .*.(js|css)?$
{
expires 1h;
}
#日志格式设定
#$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
#$remote_user:用来记录客户端用户名称;
#$time_local: 用来记录访问时间与时区;
#$request: 用来记录请求的url与http协议;
#$status: 用来记录请求状态;成功是200,
#$body_bytes_sent :记录发送给客户端文件主体内容大小;
#$http_referer:用来记录从那个页面链接访问过来的;
#$http_user_agent:记录客户浏览器的相关信息;
#通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
#定义本虚拟主机的访问日志
access_log /usr/local/nginx/logs/host.access.log main;
access_log /usr/local/nginx/logs/host.access.404.log log404;
#对 "/" 启用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以下是一些反向代理的配置,可选。
proxy_set_header Host $host;
#允许客户端请求的最大单文件字节数
client_max_body_size 10m;
#缓冲区代理缓冲用户端请求的最大字节数,
#如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
#无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
client_body_buffer_size 128k;
#表示使nginx阻止HTTP应答代码为400或者更高的应答。
proxy_intercept_errors on;
#后端服务器连接的超时时间_发起握手等候响应超时时间
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
#后端服务器数据回传时间(代理发送超时)
#后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 90;
#连接成功后,后端服务器响应时间(代理接收超时)
#连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
proxy_read_timeout 90;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
#设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
proxy_buffer_size 4k;
#proxy_buffers缓冲区,网页平均在32k以下的设置
#设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
}
#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file confpasswd;
#htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
}
#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
pdf|xls|mp3|wma)$
{
expires 15d;
}
location ~ .*.(js|css)?$
{
expires 1h;
}
}
}
Ubuntu 下,GnuPG 2.0 的支持都在 gnupg2
这个 packages 下,通过下面命令安装:
sudo apt-get install gnupg2
GitHub 要求使用 GnuPG 2.1 及以后的版本。
在 Mac 下需要安装:
brew install gnupg
brew link --overwrite gnupg
brew install pinentry-mac # 密码输入管理器
然后在 shell 配置 (.bashrc
或 ~/.zshrc
) 中添加 export GPG_TTY=$(tty)
.
添加配置
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
killall gpg-agent
然后可以通过 echo "test" | gpg --clearsign
来验证一下。
Mac 下应该会弹出 GUI 窗口进行密码验证。
然后不要忘记配置 git config:
git config --global gpg.program gpg # 配置全局的 gpg
git config --global commit.gpgsign true # 配置每一个 commit 都需要 gpg
这里需要注意的一点是 Mac 下命令还叫做 gpg,但是在 Linux 下是 gpg2
.
使用如下命令生成签名:
gpg2 --full-gen-key
如果遇到尝试卡在生成签名的步骤,提示
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
可能需要安装 rng-tools
sudo apt install rng-tools
之后在执行上面的命令。
使用以下命令查看本地密钥
gpg2 --list-keys --keyid-format LONG
结果
/home/einverne/.gnupg/pubring.gpg
---------------------------
pub rsa4096/F80B65AAAAAAAAAA 2018-01-31 [SC]
uid [ultimate] Ein Verne (co) <email@address>
sub rsa4096/B63A4CAAAAAAAAAA 2018-01-31 [E]
将其中的第三行 sec 中 rsa4096
后面的 ID 记住(F80B65AAAAAAAAAA),拷贝出来。
然后使用
gpg2 --armor --export ID | xclip -sel c
来获取 GPG KEY,拷贝 -----BEGIN PGP PUBLIC KEY BLOCK-----
和 -----END PGP PUBLIC KEY BLOCK-----
之前,包括这两行的内容到 GitHub。
配合管道命令和 xclip
,使用 | xclip -sel c
可以直接将命令输出结果拷贝到系统粘贴板。
产生 GPG,并且已经添加到 GitHub 后台,那么需要本地配置,告诉 git 本地签名。查看本地 gpg
gpg2 --list-keys --keyid-format LONG
添加配置,这里记得使用公钥
# 设置 gitconfig 配置签名的公钥 key
git config --global user.signingkey F80B65AAAAAAAAAA
# 设置签名使用的 gpg 软件
git config --global gpg.program gpg2
# 默认全部签名
git config --global commit.gpgsign true
将 GPG 添加到 .bashrc
或 ~/.zshrc
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
在提交时使用 -S
选项,来本地签名提交
git commit -S -m your commit message
提交标签同理
git tag -s mytag
可以使用 -v
来验证
git tag -v mytag
生成 gpg key
gpg2 --full-generate-key
列出本地所有公钥
gpg2 --list-keys
查看秘钥
gpg2 --list-secret-keys
删除 uid 私钥
gpg2 --delete-secret-keys [uid]
删除 uid 公钥
gpg2 --delete-keys [uid]
使用过程中遇到的一些问题
在 git commit -S
时如果遇到:
gpg: signing failed: Operation cancelled
gpg: signing failed: Operation cancelled
error: gpg failed to sign the data
fatal: failed to write commit object
尝试
export GPG_TTY=$(tty)
git config --global commit.gpgsign true
对应如果选择关闭就直接使用 false 即可。
在一台电脑中生成的 gpg secret key 可以用于不同的电脑
gpg2 --list-secret-keys
来确认本机的私钥,需要记住私钥的 ID (在第二列)gpg2 --export-secret-keys $ID > my-private-key.asc
gpg2 --import my-private-key.asc
如果在第二台机器中已经有了公钥,私钥,那么需要分别删除 gpg2 --delete-keys
和 gpg2 --delete-secret-keys
如果熟悉 scp 可以直接将 ~/.gnupg
目录复制到新机器中:
scp -rp ~/.gnupg name@server_ip:~/
把 Spring 版本从 3.2.x 升级到了4.x ,这里记录一下。
Java 8 Support, 从 4.0 开始支持 Java 8,可以使用 lambda 表达式,等等 Java 8 的特性
Groovy DSL
新增 @RestController 注解,这样就不需要每个方法都使用 @ResponseBody
了。
更多内容可以查看: https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#spring-whats-new
加入spring-context-support,以前3的版本不用加,但是4要加上,否则就会报 ClassNotFoundException,
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
更换Spring jackson依赖,Spring MVC返回 json 的时候需要依赖jackson的jar包,以前是codehaus.jackson,现在换成了fasterxml.jackson 同时修改配置文件
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
同时还要修改Spring的配置文件
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringHttpMessageConverter" />
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
</list>
</property>
</bean>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
更换springxsd文件的版本,直接从 3.0 升级到 4.0 即可
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
修改quarz版本,用2以上的版本,maven依赖如下
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.2</version>
</dependency>
nodejs 安装其实非常简单,大部分情况下 Debian/Ubuntu 下只要使用包管理直接安装
sudo apt-get install nodejs
sudo apt-get install npm
即可。
可是今天网络环境太差,不是 npm package not found 就是 update 半天不动。
官网 提供的安装方式
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
也是网络环境无法安装。
更加详细的可以参考官网
所以使用 二进制 安装
在官网 https://nodejs.org/en/download/ 找到编译好的二进制文件
然后解压到 /usr/local
目录下
然后配置 vim ~/.zshrc
export NODE_HOME=/usr/local/node-v6.11.4-linux-x64/
export PATH=$NODE_HOME/bin:$PATH
使用命令检查
node -v
npm -v
输出即可。
在编写定时备份脚本时遇到一个需求,就是在 Bash 脚本中发送带附件的邮件。于是找到了 mutt。
Mutt 是一个命令行的邮件客户端,Mutt 能够轻松地在命令行发送和读取邮件。 Mutt 支持 POP 和 IMAP 协议。 尽管 Mutt 是基于命令的,但也同样有一个友好的界面。
如果不使用界面,使用 Mutt 命令发邮件也非常方便,只需要一条命令即可发送或者批量发送邮件。
E-mail 管理程序。
语法
mutt [-hnpRvxz][-a 文件][-b 地址][-c 地址][-f 邮件文件][-F 配置文件][-H 邮件草稿][-i 文件][-m 类型][-s 主题] 邮件地址
补充说明:mutt 是一个文字模式的邮件管理程序,提供了全屏幕的操作界面。
参数:
-a
文件 在邮件中加上附加文件。-b
地址 指定密件副本的收信人地址。-c
地址 指定副本的收信人地址。-f
邮件文件 指定要载入的邮件文件。-F
配置文件 指定 mutt 程序的设置文件,而不读取预设的.muttrc 文件。-h
显示帮助。-H
邮件草稿 将指定的邮件草稿送出。-i
文件 将指定文件插入邮件内文中。-m
类型 指定预设的邮件信箱类型。-n
不要去读取程序培植文件 (/etc/Muttrc)。-p
在 mutt 中编辑完邮件后,而不想将邮件立即送出,可将该邮件暂缓寄出。-R
以只读的方式开启邮件文件。-s
主题 指定邮件的主题。-v
显示 mutt 的版本信息以及当初编译此文件时所给予的参数。-x
模拟 mailx 的编辑方式。-z
与 -f 参数一并使用时,若邮件文件中没有邮件即不启动 mutt。Debian/Ubuntu/Linux Mint 安装
sudo apt-get install -y mutt
发送一封简单的邮件(可能会被主流邮箱认为垃圾邮件,垃圾箱查看一下)
echo "Email body" | mutt -s "Email Title" root@einverne.info
进入命令行交互界面之后使用如下快捷键操作
t
改变接受者邮件地址c
改变 Cc 地址a
来增加附件q
退出y
来发送邮件发送带附件的邮件
echo "body" | mutt -s "mysql backup" root@einverne.info -a /mysql.tar.gz
读取文本中的信息作为内容
mutt -s "Test" xxxx@qq.com
添加多个附件
echo "body" | mutt -s "web backup" root@einverne.info -a /mysql.tar.gz -a /web.tar.gz
抄送和密送
echo "body" | mutt -s "title" -c cc@gmail.com -b bcc@gmail.com root@einverne.info
-c
来抄送-b
来添加密送-s
来添加标题-a
来添加附件设置发件人
编辑配置文件
vi /etc/Muttrc
添加如下内容,防止被作为垃圾邮件
set from="mutt@einverne.info"
set use_from=yes
set envelope_from="yes"
set realname="Ein Verne"
mutt@einverne.info 为发信地址
mutt 发送邮件略慢,需要等待一分钟或者更长才能发送成功,作为备份工具好好利用。
Podcast 作为一种特殊的借助声音传播的媒体,有着特定的适用场景和范围。对于我来说每当我需要放空我自己,而又需要使用眼睛和手的时候,比如长时间走路,开车,再比如乘坐地铁等等情况下都会不自觉的打开一集播客。对于固定时间的上下班时间会听固定时长差不多在 1h 左右的内容,而其他时刻根据不同的时长可能会有短到 10 分钟,或者长 30 分钟的内容。
拿播客跟传统电台广播相比,播客的制作可能会更加精良,主题更加集中,信息密度更大一些,大部分往往是针对某一个话题进行介绍或者讨论。
推荐使用通用性客户端订阅收听,比如 Google Podcasts,或者 Pocket Casts 等等,后文有整理。
反派影评:个人看电影比较多,从偶然听到一期“观影风向标”开始就一直追随者波米到了“反派影评”,这些年陆陆续续也听过不少影评类节目,但只有反派让我一直坚持到现在仍然每期必听。如果你是一个观影爱好者,那就一定不能错过这一档节目。反派影评在 Podcast 上只更新长节目,短节目还是要上微信公众号的。
Self-Hosted 是一个关于如何自建各种服务,将自己的数字生活以及产生的数据自我管理的播客。
[[东腔西调]] 是一档由大观天下制作的文化对谈类播客。主播邀请来自不同领域的嘉宾学者聊聊他们关心的世界和生活,探寻社会文化背后的来龙去脉。
这是一个和 Python 相关的播客,但是又不止于 Python,还包括 Data Science,AI,Web development 等等话题。
This American Life is an American weekly hour-long radio program produced in collaboration with Chicago Public Media and hosted by Ira Glass. It is broadcast on numerous public radio stations in the United States and internationally, and is also available as a free weekly podcast.
学习基础韩国语的节目
从传统意义上这应该算是讲座了,因为《[[通往奴役之路]]》而在 YouTube 上得知这一个主题的演讲,所以下载之后转成音频在路上听了。演讲者是西北政法大学的副教授谌洪果,因为一些缘故辞职了。所以我们才能在 YouTube 上看到这一个系列的讲座,主讲的材料是基于《牛津人文通识》这样一套书籍,这一系列的书大多都是哲学类,或者哲学家相关的书籍,当然也有比如现代日本,美国大法官之类。这一个系列的讲座每一期围绕一本书进行一段分享,YouTube 上的内容不全,不过也陆陆续续听了 24 期,可以说每一期都非常值得听,现在依然记忆深刻的有,哈耶克的,美国最高法院,现代日本等等话题。
Acquired 是一个关注科技圈成功的收购和上市的节目,两位主持人 David 和 Ben 在投资界都有一定的经验 1, 能够听出来每一期节目都有非常充足的材料。有的时候他们也会分析一些国内的成功投资经验,比如 Tencent,Xiaomi,Alibaba 等等,也有一些非常热门的话题比如 Tesla,GitHub etc。
听“两个中老年人程序员” 聊天。就是更新时间非常不固定。
内核恐慌主持人 Rio 的另一档节目,年初刚开始听,果然质量还是不错的。
这是一档由 The Verge 推出的播客节目,听的第一期是因为想要了解更多关于 Airbnb 的内容,于是搜到了创始人 Brain Chesky 的访谈,发现这档节目不错
听不同人讲自己的故事。
青岛刘伟品质旅游主播的一档节目,主播是一位从事多年日本旅游工作的导游,从日本文化,历史,饮食,等等方面对日本做出一些介绍。当时就是随心所听,节目不长,声音录制设备也不是很好,但是内容短小精湛非常不错,在主播的推荐下陆陆续续接触了日本文化,甚至看了《日本论》《静观日本》等等书籍。
主播本人是一位职业导游,从 90 十年代开始从事中日导游,翻译工作,给国人定制深度旅游,也接待日方游客。节目内容重在文化,历史,从历史文化中了解日本人的礼仪,美学等等方面。
当时去了解 Medium 的创始人的时候搜索到的播客,后面陆陆续续还听了关于 Google Map 创始人的专题,是一档非常不错的、有一定深度的播客。后面就挑着感兴趣的继续听了。
硅谷从业人员聊科技相关的话题,在一些不熟悉的领域上给了我开阔眼界的机会。
一档中日韩三国记者的线上聊天节目,围绕着三国不同的政治、文化展开。
主题不固定,主要在于媒体,投资,互联网等等
或许直接去看讲述日本的书,要比直接听这个要好很多。个人不是非常喜欢这个频道。
这是一档台湾人做的双语国际新闻平台,当然听到后期就会发现主播们打着双语的旗号,其实更多的是在“聊天”,或者用他们自己的话说,就是“讲干话”。当然继续收听他们的节目主要是主播二人非常有趣。
国际新闻,双语,读书,闲聊,台湾
每一期会分享一本图书
朋友推荐,听了多抓鱼创始人的一集,确实不错,可以选择自己喜欢的话题和主题来听。通常情况下一集大概半个小时左右,会邀请以为专业人士就某一个话题进行演讲,看成是国内复刻版的 TED 吧。
看名字就知道是和桌游相关的内容了
一档和哲学,政治,经济,平民文化相关的电台
一档英语影评节目
时政
美国政治
综合新闻
纽约时报的 The Daily 专题报道
ABC The Dropout 听深度报道
欧洲政局变化
这档节目来自 NPR,绝对的明星节目。每期不到 30 分钟,把抽象的经济理论和政治决议与日常生活的种种现象结合,或者通过一个普通的生活事例分析出里面蕴含的经济学道理。听这档节目会上瘾。
每个人都个人的喜好,网上很多 list 也不都是我最喜欢的博客,我觉得能够找到方法找到自己喜欢的某一类播客就是很好的,授人以鱼不如授人以渔,就是这样,但是这些我听过,并不是非常喜欢的播客我也列出来,喜不喜欢可以自行判断。
早之前在 Android 的时候买过 Pocket Cast 可是竟然发现这家每个平台都要收费,不管是 Web ,还是 Android/iOS 客户端,每一个都是单独收费,尽管能够同步订阅列表,但后来转用 iOS 也就放弃了这个客户端,我用过的几个还不错的
至于其他人推荐的 Castro, Overcast 如果不缺钱的话买就行了。个人觉得重要的是内容,还有同步的功能,我希望我订阅的内容跟着账号走,而不是跟着设备走。其他国内的 app 比如 喜马拉雅,蜻蜓,荔枝 FM, 听伴 就凭着个人喜好选择即可。
至于为什么不推荐国内的这些 FM,是因为本来 Podcast 是一个公开分享的渠道,发布到 Podcast 上的内容可以被全世界的人访问到,而国内的 FM 都是闭门造车,封闭自己的用户,限制用户只能在他们的平台上传,听众也只有他们平台的账号才能收听,所有的内容就像是自家花园,外人不得入内。而放到 iTunes 的 Podcast 就像是放到了博物馆,全世界的人只要觉得有用就都能够收听到。而且封闭的环境导致审查异常严格,甚至聊电影都能碰到审查,同样也就导致了低智化内容泛滥,内容越没有思考越能得到平台的推荐,自此循环往复,推荐榜单就几乎没有能听的内容了。而在 Podcast 中反而一些很小众的 Channel 内容质量异常高,在某一个专业领域分享的知识,内容足够填满整个频道。
一个关于博客统计信息的站点
在使用 Spring Boot 构建一套 RESTful 接口的时候经常需要手工维护一份接口文档以提供给不同的客户端使用,有的时候手工维护成本太高,今天发现了一套自动化生成 RESTful 接口文档的工具 Swagger 。
Swagger 能根据 Spring Controller 接口自动生成一个文档页面,在代码中使用注解将接口文档注释,非常方便。 Swagger 整合到 Spring boot 项目中也非常方便。
io.springfox >= 3.0
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
访问地址是:http://localhost:8080/swagger-ui/#/
在 pom.xml
中添加
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
最新的版本可以在 mvnrepository 上查到,或者上官网或者 github。
在项目 package 根下新建如下 Class:
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket helloApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("info.einverne.springboot.demo"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 文档标题
.title("API 文档")
// 文档描述
.description("https://github.com/einverne/thrift-swift-demo/tree/master/spring-boot-demo")
.termsOfServiceUrl("https://github.com/einverne/thrift-swift-demo/tree/master/spring-boot-demo")
.version("v1")
.build();
}
}
通过@Configuration
注解,让 Spring 来加载该类配置。再通过@EnableSwagger2
注解来启用 Swagger2。
apiInfo()
用来创建 API 的基本信息,展现在文档页面中。select()
函数返回一个 ApiSelectorBuilder
实例用来控制哪些接口暴露给 Swagger ,这里使用定义扫描包路径来定义, Swagger 会扫描包下所有 Controller 的定义并产生文档内容,除了被 @ApiIgnore
注解的接口。@ApiOperation
注解来给 API 增加说明、通过 @ApiImplicitParams
、@ApiImplicitParam
注解来给参数增加说明。
一个简单的注释
@ApiOperation(value = "创建用户", notes = "根据 User 对象创建用户")
@ApiImplicitParam(name = "user", value = "用户详细实体 user", required = true, dataType = "User")
@RequestMapping(value = "", method = RequestMethod.POST)
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
详细的例子可以参考源代码 https://github.com/einverne/thrift-swift-demo
再添加注释后启动 Spring boot, 访问 http://localhost:8080/swagger-ui.html 即可看到 API 文档
@Api
注解用于类上,说明类作用
标记在方法上,对一个操作或 HTTP 方法进行描述。具有相同路径的不同操作会被归组为同一个操作对象。不同的 HTTP 请求方法及路径组合构成一个唯一操作。此注解的属性有:
注解 ApiImplicitParam 的容器类,以数组方式存储。
对 API 的单一参数进行注解。虽然注解 @ApiParam 同 JAX-RS 参数相绑定,但这个 @ApiImplicitParam 注解可以以统一的方式定义参数列表,也是在 Servelet 及非 JAX-RS 环境下,唯一的方式参数定义方式。注意这个注解 @ApiImplicitParam 必须被包含在注解 @ApiImplicitParams 之内。可以设置以下重要参数属性:
@RequestBody 这样的场景请求参数无法使用 @ApiImplicitParam 注解进行描述
增加对参数的元信息说明。这个注解只能被使用在 JAX-RS 1.x/2.x 的综合环境下。其主要的属性有:
提供对 Swagger model 额外信息的描述。在标注 @ApiOperation 注解的操作内,所有的类将自动被内省(introspected),但利用这个注解可以做一些更加详细的 model 结构说明。主要属性有:
对 model 属性的注解,主要的属性值有:
响应配置
多个 Response
考虑到安全的问题,每次请求 API 需要对用户进行验证与授权。目前主流的验证方式采用请求头部(request header)传递 token,即用户登录之后获取一个 token,然后每次都使用这个 token 去请求 API。如果想利用 swagger-UI 进行 API 测试,必须显式为每个需要验证的 API 指定 token 参数。这时可以为每个操作添加一个注解 @ApiImplicitParams,具体代码如下:
@ApiImplicitParams({@ApiImplicitParam(name = "TOKEN", value = "Authorization token", required = true, dataType = "string", paramType = "header")})
Swagger 提供了 enable
方法,可以通过设置该方法来选择开启 Swagger 来在线上环境禁用 Swagger。
@Bean
public Docket customImplementation(){
return new Docket(SWAGGER_2)
.apiInfo(apiInfo())
.enable(environmentSpeficicBooleanFlag) //<--- Flag to enable or disable possibly loaded using a property file
.includePatterns(".*pet.*");
}
如果使用 Spring @Profile 也可以
@Bean
@Profile("production")
public Docket customImplementation(){
return new Docket(SWAGGER_2)
.apiInfo(apiInfo())
.enable(false) //<--- Flag set to false in the production profile
.includePatterns(".*pet.*");
}
From: https://stackoverflow.com/a/27976261/1820217
平时在 Linux 上查看磁盘信息都使用 df -lh
, -l
显示本地文件系统, -h
来表示 human readable 。虽然 df 在一定程度上能够满足查询磁盘剩余空间的需求,但是这里要介绍一款强大于 df 的命令 —- di 。
使用如下命令安装
sudo apt install di
di 命令是 disk information 的缩写,直接运行 di 会有如下结果
di
Filesystem Mount Size Used Avail %Used fs Type
/dev/sda1 / 901.2G 188.3G 667.1G 26% ext4
tmpfs /dev/shm 7.8G 0.1G 7.6G 2% tmpfs
tmpfs /run 1.6G 0.1G 1.5G 4% tmpfs
cgmfs /run/cgmanager/ 0.1M 0.0M 0.1M 0% tmpfs
tmpfs /run/lock 5.0M 0.0M 5.0M 0% tmpfs
tmpfs /run/user/0 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /run/user/1000 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /sys/fs/cgroup 7.8G 0.0G 7.8G 0% tmpfs
/dev/sda1 /var/lib/docker 901.2G 188.3G 667.1G 26% ext4
di
默认的输出就是比较人性化的了。
看 di 的使用介绍 man di
就会发现 di 是这么介绍自己的
> di Displays usage information on mounted filesystems. Block values are reported in a human readable format. If the user or group has a disk quota, the values reported are adjusted according the quotas that apply to the user.
di -A
Mount fs Type Filesystem
Options
Size Used Free %Used %Free
Size Used Avail %Used %Free
Size Used Avail %Used
Inodes IUsed IFree %IUsed
/ ext4 /dev/sda1
rw,relatime,errors=remount-ro,data=ordered
901.2G 188.3G 712.9G 21% 79%
901.2G 234.1G 667.1G 26% 74%
855.4G 188.3G 667.1G 22%
60014592 1372538 58642054 2%
/dev/shm tmpfs tmpfs
rw,nosuid,nodev
7.8G 0.1G 7.6G 2% 98%
7.8G 0.1G 7.6G 2% 98%
7.8G 0.1G 7.6G 2%
2036725 741 2035984 0%
/run tmpfs tmpfs
rw,nosuid,noexec,relatime,size=1629380k,mode=755
1.6G 0.1G 1.5G 4% 96%
1.6G 0.1G 1.5G 4% 96%
1.6G 0.1G 1.5G 4%
2036725 777 2035948 0%
/run/cgmanager/fs tmpfs cgmfs
rw,relatime,size=100k,mode=755
0.1M 0.0M 0.1M 0% 100%
0.1M 0.0M 0.1M 0% 100%
0.1M 0.0M 0.1M 0%
2036725 14 2036711 0%
/run/lock tmpfs tmpfs
rw,nosuid,nodev,noexec,relatime,size=5120k
5.0M 0.0M 5.0M 0% 100%
5.0M 0.0M 5.0M 0% 100%
5.0M 0.0M 5.0M 0%
2036725 4 2036721 0%
/run/user/0 tmpfs tmpfs
rw,nosuid,nodev,relatime,size=1629380k,mode=700
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0%
2036725 4 2036721 0%
/run/user/1000 tmpfs tmpfs
rw,nosuid,nodev,relatime,size=1629380k,mode=700,uid=1000,gid=1000
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0%
2036725 36 2036689 0%
/sys/fs/cgroup tmpfs tmpfs
rw,mode=755
7.8G 0.0G 7.8G 0% 100%
7.8G 0.0G 7.8G 0% 100%
7.8G 0.0G 7.8G 0%
2036725 18 2036707 0%
/var/lib/docker/aufs ext4 /dev/sda1
rw,relatime,errors=remount-ro,data=ordered
901.2G 188.3G 712.9G 21% 79%
901.2G 234.1G 667.1G 26% 74%
855.4G 188.3G 667.1G 22%
60014592 1372538 58642054 2%
使用 -c
选项分割输出
di -c
s,m,b,u,v,p,T
"/dev/sda1","/","901.2G","188.3G","667.1G",26%,"ext4"
"tmpfs","/dev/shm","7.8G","0.1G","7.6G",2%,"tmpfs"
"tmpfs","/run","1.6G","0.1G","1.5G",4%,"tmpfs"
"cgmfs","/run/cgmanager/fs","0.1M","0.0M","0.1M",0%,"tmpfs"
"tmpfs","/run/lock","5.0M","0.0M","5.0M",0%,"tmpfs"
"tmpfs","/run/user/0","1.6G","0.0G","1.6G",0%,"tmpfs"
"tmpfs","/run/user/1000","1.6G","0.0G","1.6G",0%,"tmpfs"
"tmpfs","/sys/fs/cgroup","7.8G","0.0G","7.8G",0%,"tmpfs"
"/dev/sda1","/var/lib/docker/aufs","901.2G","188.3G","667.1G",26%,"ext4"
c 是 --csv-output
的缩写,为了便于程序解析
-t
参数在最后增加统计行
di -t
Filesystem Mount Size Used Avail %Used fs Type
/dev/sda1 / 901.2G 188.4G 667.0G 26% ext4
tmpfs /dev/shm 7.8G 0.1G 7.6G 2% tmpfs
tmpfs /run 1.6G 0.1G 1.5G 4% tmpfs
cgmfs /run/cgmanager/ 0.1M 0.0M 0.1M 0% tmpfs
tmpfs /run/lock 5.0M 0.0M 5.0M 0% tmpfs
tmpfs /run/user/0 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /run/user/1000 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /sys/fs/cgroup 7.8G 0.0G 7.8G 0% tmpfs
/dev/sda1 /var/lib/docker 901.2G 188.4G 667.0G 26% ext4
Total 1.8T 0.4T 1.3T 26%
di -s
默认更具 mount point 输出
di -sm
默认 mount pontdi -sn
不排序,按照挂载表 /etc/fstab 中顺序di -ss
按照特殊设备di -st
根据 filesystem typedi -sr
逆序输出排序方式可以组合使用,如:di –stsrm
:按照类型、设备、挂载点逆序排序。
di –strsrm
:按照类型、设备逆序、挂载点逆序排序。
di -fM
Mount
/
/dev/shm
/run
/run/cgmanager/fs
/run/lock
/run/user/0
/run/user/1000
/sys/fs/cgroup
/var/lib/docker/aufs
只打印 mount point
更多的 f 的选项可以直接参看 man di
虽然 di 提供了比 df 更多更强大的功能,但是也有其缺点,大部分的 Linux 发行版默认是没有预装的。