Nginx 配置详解

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 连接数

配置用户用户组

设置用户的配置

user user [group];
  • user, 可运行 Nginx 服务器的用户
  • group, 指定可运行用户组

希望所有用户都可以启动 Nginx 进程,一种是直接注释该配置,或者

user nobody nobody;

Nginx 配置文件中,每一条配置都必须以分号结束。

配置 worker process 数

worker process 是 Nginx 并发关键所在,理论上 worker process 值越大,可支持并发数也越多,但实际也受到软件,操作系统,硬件(CPU 和磁盘)等资源的制约。

worker_processes number | auto;
  • number, 指定 Nginx 进程最多可产生的 worker process 数
  • auto Nginx 自动

PID 存放路劲

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;
  • file 是要引入的配置文件,支持相对路劲和正则匹配

最大连接数

设置每一个 worker process 同时开启的最大连接数

worker_connections number;

只能在 events 块中配置

定义 MIME TYPE 类型

浏览器使用 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 直接配置。

Server section

自定义 Access 日志

error_log 不同的是,Nginx 进程运行时访问日志,由 Nginx 提供服务过程中应答前端请求的日志。

Nginx 服务器支持对服务日志的格式、大小、输出等进行配置,需要使用两个配置 access_loglog_format

access_log path [format [buffer=size]];
  • path, 配置服务日志的文件存放路劲及名称
  • format 可选,自定义日志格式,也可以通过 log_format 配置指定好,直接引用格式名
  • size 临时存放日志的内存缓存区大小

如果要取消记录日志功能,使用

access_log off;

自定义日志格式

log_format name string ...;
  • name 格式字符串的名字,默认为 combined
  • 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];
  • timeout 对连接的保持时间
  • header_timeout 可选,在 Response 头部 Keep-Alive 域设置超时时间

示例

keepalive_timeout 120s 100s;

设置单连接请求数上限

限制用户通过某一个连接向 Nginx 发送请求次数

keepalive_requests number;

虚拟主机配置

虚拟主机配置以 server 开头,server 内的配置都认为是 虚拟主机 配置。虚拟主机定义了一套由不同 server_name 配置区分的资源。虚拟主机一般由 listenserver_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 为默认
  • setfib 不常用
  • backlog 设置监听函数 listen() 最多运行多少网络连接同时处于挂起状态
  • rcvbuf 监听 socket 接受缓存区大小
  • sndbuf 监听 socket 发送缓存区大小
  • ssl 回话使用 SSL 模式

配置虚拟主机名称

主机是指 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 被处于同一优先级匹配方式匹配多次成功,则首次匹配成功的虚拟主机处理请求。

基于 IP 的虚拟主机配置

不是很常用,暂时略

配置 location 块

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 的 URI

在 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 并响应请求。

关于 root 和 alias 的区别 可以参考这篇文章

设置网站默认首页

在用户发出请求时,请求地址可以不填写首页完整路劲

index file ...;

设置错误页面

指定错误页面

error_page code ... [=[response]] uri
  • code 要处理的 HTTP 错误代码
  • response 可选项,将 code 指定的错误转化为新的错误代码 response
  • uri 错误页面的路劲或者网站地址

示例

error_page 404 /404.html

基于 IP 配置 Nginx 访问权限

Nginx 支持两种途径的基本访问控制,一种是由 HTTP 标准模块的 ngx_http_access-modele 支持,通过 IP 来判断客户端是否拥有对 Nginx 的访问权限

allow 配置用于设置 Nginx 客户端 IP 访问

allow address | CIDR | all;
  • address 允许访问的客户端 IP,不支持同时设置多个
  • CIDR 允许访问的客户端 CIDR 地址, 202.112.18.23/25,前 32 位 IP 地址,后面 ”/25“ 表示前 25 位是网络,其余代表主机部分
  • all 代表允许所有客户端访问

deny 配置,顾名思义

deny address | CIDR | all;

参数含义同上

Nginx 对于访问控制权限是顺序匹配,如果匹配成功就不会继续向下解析。

配置密码设置 Nginx 访问权限

Nginx 支持 HTTP Basic Authentication 协议的认证,该协议是一种 HTTP 性质的认证办法,需要用户名和密码,认证失败的客户端不拥有访问 Nginx 服务器的权限。

开启或者关闭

auth_basic string | off;
  • string 开启该认证功能,并验证配置时显示的提示信息
  • 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;
	}
}

reference

  • Nginx 高性能 Web 服务器详解

2017-10-23 nginx , web , server , linux , proxy

GitHub 使用 gpg 签名

Ubuntu 下,GnuPG 2.0 的支持都在 gnupg2 这个 packages 下,通过下面命令安装:

sudo apt-get install gnupg2

GitHub 要求使用 GnuPG 2.1 及以后的版本。

生成 GPG 签名

使用如下命令生成签名:

gpg2 --full-gen-key
  1. 选择默认 RSA and RSA
  2. 推荐 4096
  3. 过期时间
  4. 相关信息包括 Real name, Email, Comment(comment 可以写一些标示)
  5. 密码

如果遇到尝试卡在生成签名的步骤,提示

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
---------------------------
sec   rsa4096/F80B65AAAAAAAAAA 2018-01-31 [SC]
uid                 [ultimate] Ein Verne (co) <email@address>
ssb   rsa4096/B63A4CAAAAAAAAAA 2018-01-31 [E]

将其中的第三行 sec 中 rsa4096 以后的 ID 记住,拷贝出来。

然后使用

gpg2 --armor --export ID | xclip -sel c

来获取 GPG KEY,拷贝 -----BEGIN PGP PUBLIC KEY BLOCK----------END PGP PUBLIC KEY BLOCK----- 之前,包括这两行的内容到 GitHub。

使用 | xclip -sel c 可以直接将命令输出结果拷贝到系统粘贴板。

配置 GPG

产生 GPG,并且已经添加到 GitHub 后台,那么需要本地配置,告诉 git 本地签名。查看本地 gpg

gpg2 --list-keys --keyid-format LONG

添加配置,这里记得使用公钥

git config --global user.signingkey F80B65AAAAAAAAAA
git config --global gpg.program gpg2

将 GPG 添加到 bashrc

echo 'export GPG_TTY=$(tty)' >> ~/.bashrc

签名 commit

在提交时使用 -S 选项

git commit -S -m your commit message

来本地签名提交

提交标签同理

git tag -s mytag

可以使用 -v 来验证

git tag -v mytag

其他 gpg 命令

列出公钥

gpg2 --list-keys

查看秘钥

gpg2 --list-secret-keys

删除 uid 私钥

gpg2 --delete-secret-keys [uid]

删除 uid 公钥

gpg2 --delete-keys [uid]

问题

使用过程中遇到的一些问题

提交 commit 时 failed to sign the data

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 提交使用 gpg 加密

git config --global commit.gpgsign true

对应如果选择关闭就直接使用 false 即可。

导出私钥用于不同电脑之间同步

在一台电脑中生成的 gpg secret key 可以用于不同的电脑

  • 首先运行 gpg2 --list-secret-keys 来确认本机的私钥,需要记住私钥的 ID (在第二列)
  • 导出私钥 gpg2 --export-secret-keys $ID > my-private-key.asc
  • 拷贝私钥到目标机器 (scp)
  • 导入私钥 gpg2 --import my-private-key.asc

如果在第二台机器中已经有了公钥,私钥,那么需要分别删除 gpg2 --delete-keysgpg2 --delete-secret-keys

如果熟悉 scp 可以

scp -rp ~/.gnupg name@server_ip:~/

reference


2017-10-20 github , git , gpg , linux

升级 Spring MVC 3.2.x 到 4.x 注意事项

把 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 MVC jackson 依赖

更换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>

xsd 文件版本

更换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 版本

修改quarz版本,用2以上的版本,maven依赖如下

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.2</version>
</dependency>

2017-10-19 Spring , Java , Web

Linux 安装 nodejs

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

输出即可。

reference


2017-10-18 linux , nodejs , npm , js , javascript

使用 mutt 在 Bash 中发送邮件及附件

在编写定时备份脚本时遇到一个需求,就是在 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 发送邮件略慢,需要等待一分钟或者更长才能发送成功,作为备份工具好好利用。

reference


2017-10-17 linux , email , mutt

Podcast 频道推荐

Podcast 作为一种特殊的借助声音传播的媒体,有着特定的适用场景和范围。对于我来说每当我需要放空我自己,而又需要使用眼睛和手的时候,比如长时间走路,开车,再比如乘坐地铁等等情况下都会不自觉的打开一集播客。对于固定时间的上下班时间会听固定时长差不多在 1h 左右的内容,而其他时刻根据不同的时长可能会有短到 10 分钟,或者长 30 分钟的内容。

拿播客跟传统电台广播相比,播客的制作可能会更加精良,主题更加集中,信息密度更大一些,大部分往往是针对某一个话题进行介绍或者讨论。

推荐使用通用性客户端订阅收听,比如 Google Podcasts,或者 Pocket Casts 等等,后文有整理。

每期必听

反派影评

反派影评:个人看电影比较多,从偶然听到一期“观影风向标”开始就一直追随者波米到了“反派影评”,这些年陆陆续续也听过不少影评类节目,但只有反派让我一直坚持到现在仍然每期必听。如果你是一个观影爱好者,那就一定不能错过这一档节目。反派影评在 Podcast 上只更新长节目,短节目还是要上微信公众号的。

  • 主题内容:每期主题一部电影,根据这部电影展开,从导演到演员等等
  • 时长:1h 以上
  • 更新周期:每周,但时间不固定

Talk Python to me (by Michael Kennedy)

这是一个和 Python 相关的播客,但是又不止于 Python,还包括 Data Science,AI,Web development 等等话题。

  • 官网:https://talkpython.fm/
  • 主题内容:Python 相关
  • 时长: 1h 左右
  • 更新周期:大致为一周

Talk to me in Korean

学习基础韩国语的节目

  • 主题内容:韩语基础会话
  • 时长: less than 10min
  • 更新周期:大致为一周

牛津人文通识解读

从传统意义上这应该算是讲座了,因为《通往奴役之路》而在 YouTube 上得知这一个主题的演讲,所以下载之后转成音频在路上听了。演讲者是西北政法大学的副教授谌洪果,因为一些缘故辞职了。所以我们才能在 YouTube 上看到这一个系列的讲座,主讲的材料是基于《牛津人文通识》这样一套书籍,这一系列的书大多都是哲学类,或者哲学家相关的书籍,当然也有比如现代日本,美国大法官之类。这一个系列的讲座每一期围绕一本书进行一段分享,YouTube 上的内容不全,不过也陆陆续续听了 24 期,可以说每一期都非常值得听,现在依然记忆深刻的有,哈耶克的,美国最高法院,现代日本等等话题。

  • 主题内容:围绕牛津人文通识读本每期分享一期
  • 时长:1h-2h
  • 更新周期:不固定

Acquired

Acquired 是一个关注科技圈成功的收购和上市的节目,两位主持人 David 和 Ben 在投资界都有一定的经验 1, 能够听出来每一期节目都有非常充足的材料。有的时候他们也会分析一些国内的成功投资经验,比如 Tencent,Xiaomi,Alibaba 等等,也有一些非常热门的话题比如 Tesla,GitHub etc。

  • 官网:https://www.acquired.fm/
  • 主题内容:Exploring, Analyzing, and Grading Technology Acquisitions and IPOs
  • 时长:2h 左右
  • 更新周期:Season 季播,更新时周更

内核恐慌

听“两个中老年人程序员” 聊天。

  • 主题内容:程序,Mac,设计,字体,软件包等等
  • 时长:100 分钟以上
  • 更新周期:节目更新时间不固定

故事 FM

听不同人讲自己的故事。

  • 主题内容:不定
  • 时长:小于 30 min
  • 更新周期:每 3 天左右

日本自由行

青岛刘伟品质旅游主播的一档节目,主播是一位从事多年日本旅游工作的导游,从日本文化,历史,饮食,等等方面对日本做出一些介绍。当时就是随心所听,节目不长,声音录制设备也不是很好,但是内容短小精湛非常不错,在主播的推荐下陆陆续续接触了日本文化,甚至看了《日本论》《静观日本》等等书籍。

主播本人是一位职业导游,从 90 十年代开始从事中日导游,翻译工作,给国人定制深度旅游,也接待日方游客。节目内容重在文化,历史,从历史文化中了解日本人的礼仪,美学等等方面。

  • 主题内容:日本文化,旅游,自由行
  • 时长:30 分钟左右
  • 更新周期:前期节目不固定,后面固定为每周三更新

非每期必听但值得一提

忽左忽右

主题不固定,主要在于媒体,投资,互联网等等

  • 主题内容:不固定
  • 时长:30 分钟到 1 小时不定
  • 更新周期:不固定

静说日本 徐静波

或许直接去看讲述日本的书,要比直接听这个要好很多。个人不是非常喜欢这个频道。

  • 主题内容:日本
  • 时长:20 分钟以下
  • 更新周期:大概每周

百靈果 NEWS

这是一档台湾人做的双语国际新闻平台,当然听到后期就会发现主播们打着双语的旗号,其实更多的是在“聊天”,或者用他们自己的话说,就是“讲干话”。当然继续收听他们的节目主要是主播二人非常有趣。

国际新闻,双语,读书,闲聊,台湾

  • 主题内容:不固定
  • 时长:30 分钟到 1 小时不定
  • 更新周期:不固定

陌声人

每一期会分享一本图书

一席

朋友推荐,听了多抓鱼创始人的一集,确实不错,可以选择自己喜欢的话题和主题来听。通常情况下一集大概半个小时左右,会邀请以为专业人士就某一个话题进行演讲,看成是国内复刻版的 TED 吧。

  • 主题内容:
  • 时长:
  • 更新周期:

Breaking into Board Games

看名字就知道是和桌游相关的内容了

  • 主题内容:
  • 时长:
  • 更新周期:

翻转电台

一档和哲学,政治,经济,平民文化相关的电台

  • 主题内容:哲学、政治、经济、平民文化
  • 时长:30min~1h 不等
  • 更新周期:每周

InSession Film Podcast

一档英语影评节目

  • 主题内容:电影,演员,导演
  • 时长:1h 以上不等
  • 更新周期:Every 2 or 3 days.

政见合集

时政

选 美

美国政治

欧罗万象

NPR Up first

综合新闻

The Daily

纽约时报的 The Daily 专题报道

The Dropout

ABC The Dropout 听深度报道

欧洲政局变化

Planet Money

这档节目来自 NPR,绝对的明星节目。每期不到 30 分钟,把抽象的经济理论和政治决议与日常生活的种种现象结合,或者通过一个普通的生活事例分析出里面蕴含的经济学道理。听这档节目会上瘾。

曾经听过但个人不是很推荐

每个人都个人的喜好,网上很多 list 也不都是我最喜欢的博客,我觉得能够找到方法找到自己喜欢的某一类播客就是很好的,授人以鱼不如授人以渔,就是这样,但是这些我听过,并不是非常喜欢的播客我也列出来,喜不喜欢可以自行判断。

  • 代码时间
  • 电影不无聊
  • 闲侃日本
  • 新闻酸菜馆

Podcast 客户端推荐

早之前在 Android 的时候买过 Pocket Cast 可是竟然发现这家每个平台都要收费,不管是 Web ,还是 Android/iOS 客户端,每一个都是单独收费,尽管能够同步订阅列表,但后来转用 iOS 也就放弃了这个客户端,我用过的几个还不错的

  • Podcasts 苹果自身的客户端,虽然设计和使用都不是那么美观和人性化,但只要订阅了就会默默在 wifi 下帮你下载好,不用每一次上路了才想起来
  • Castbox,一款新出的客户端,客户端全免费,甚至网页版还提供博客平台的托管,虽然国内使用速度略慢,但是是我用过的里面体验比较好的了

至于其他人推荐的 Castro, Overcast 如果不缺钱的话买就行了。个人觉得重要的是内容,还有同步的功能,我希望我订阅的内容跟着账号走,而不是跟着设备走。其他国内的 app 比如 喜马拉雅,蜻蜓,荔枝 FM, 听伴 就凭着个人喜好选择即可。

至于为什么不推荐国内的这些 FM,是因为本来 Podcast 是一个公开分享的渠道,发布到 Podcast 上的内容可以被全世界的人访问到,而国内的 FM 都是闭门造车,封闭自己的用户,限制用户只能在他们的平台上传,听众也只有他们平台的账号才能收听,所有的内容就像是自家花园,外人不得入内。而放到 iTunes 的 Podcast 就像是放到了博物馆,全世界的人只要觉得有用就都能够收听到。而且封闭的环境导致审查异常严格,甚至聊电影都能碰到审查,同样也就导致了低智化内容泛滥,内容越没有思考越能得到平台的推荐,自此循环往复,推荐榜单就几乎没有能听的内容了。而在 Podcast 中反而一些很小众的 Channel 内容质量异常高,在某一个专业领域分享的知识,内容足够填满整个频道。

Podcast Hosting

其他站点

一个关于博客统计信息的站点

  • https://chartable.com/
  • https://github.com/guipdutra/awesome-geek-podcasts#in-chinese
  • https://wanqu.co/b/57/2017-03-03-podcasts.html

reference


2017-10-17 podcast , audio , castbox , pocket-cast , google-podcasts

在 Spring Boot 中使用 Swagger

在使用 Spring Boot 构建一套 RESTful 接口的时候经常需要手工维护一份接口文档以提供给不同的客户端使用,有的时候手工维护成本太高,今天发现了一套自动化生成 RESTful 接口文档的工具 Swagger 。

Swagger 能根据 Spring Controller 接口自动生成一个文档页面,在代码中使用注解将接口文档注释,非常方便。 Swagger 整合到 Spring boot 项目中也非常方便。

添加依赖

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 注解

@Api 注解用于类上,说明类作用

  • value url
  • description
  • tags 设置该值,value 会被覆盖
  • basePath 基本路劲不可配置
  • position
  • produces “application/json”
  • consumes “application/json”
  • protocols http, https, wss
  • authorizations 认证
  • hidden 是否在文档隐藏

ApiOperation 注解

标记在方法上,对一个操作或 HTTP 方法进行描述。具有相同路径的不同操作会被归组为同一个操作对象。不同的 HTTP 请求方法及路径组合构成一个唯一操作。此注解的属性有:

  • value 对操作的简单说明,长度为 120 个字母,60 个汉字。
  • notes 对操作的详细说明。
  • httpMethod HTTP 请求的动作名,可选值有:”GET”, “HEAD”, “POST”, “PUT”, “DELETE”, “OPTIONS” and “PATCH”。
  • code 默认为 200,有效值必须符合标准的 HTTP Status Code Definitions

ApiImplicitParams

注解 ApiImplicitParam 的容器类,以数组方式存储。

ApiImplicitParam

对 API 的单一参数进行注解。虽然注解 @ApiParam 同 JAX-RS 参数相绑定,但这个 @ApiImplicitParam 注解可以以统一的方式定义参数列表,也是在 Servelet 及非 JAX-RS 环境下,唯一的方式参数定义方式。注意这个注解 @ApiImplicitParam 必须被包含在注解 @ApiImplicitParams 之内。可以设置以下重要参数属性:

  • name 参数名称
  • value 参数的简短描述
  • required 是否为必传参数
  • dataType 参数类型,可以为类名,也可以为基本类型(String,int、boolean 等)
  • paramType 参数的传入(请求)类型,可选的值有 path, query, body, header or form。

@RequestBody 这样的场景请求参数无法使用 @ApiImplicitParam 注解进行描述

ApiParam

增加对参数的元信息说明。这个注解只能被使用在 JAX-RS 1.x/2.x 的综合环境下。其主要的属性有:

  • required 是否为必传参数
  • value 参数简短说明

ApiModel

提供对 Swagger model 额外信息的描述。在标注 @ApiOperation 注解的操作内,所有的类将自动被内省(introspected),但利用这个注解可以做一些更加详细的 model 结构说明。主要属性有:

  • value model 的别名,默认为类名
  • description model 的详细描述

ApiModelProperty

对 model 属性的注解,主要的属性值有:

  • value 属性简短描述
  • example 属性的示例值
  • required 是否为必须值
  • hidden 隐藏该属性

ApiResponse

响应配置

  • code http 状态码
  • message 描述

ApiResponses

多个 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

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

reference


2017-10-16 Spring , Swagger , Java

每天学习一个命令: Linux 查看磁盘信息命令 di

平时在 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.

一些简单的使用

A 选项打印所有挂载设备

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 选项逗号分割

使用 -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 参数增加统计行

-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%      

s 参数对结果排序

di -s 默认更具 mount point 输出

  • di -sm 默认 mount pont
  • di -sn 不排序,按照挂载表 /etc/fstab 中顺序
  • di -ss 按照特殊设备
  • di -st 根据 filesystem type
  • di -sr 逆序输出

排序方式可以组合使用,如:di –stsrm :按照类型、设备、挂载点逆序排序。 di –strsrm :按照类型、设备逆序、挂载点逆序排序。

f 选项自定义格式

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 发行版默认是没有预装的。


2017-10-16 linux , 磁盘管理 , disk , df

SonarQube continuous code quality

关键字提取,开源,代码质量管理,多语言支持。

SonarQube is an open-source platform developed by SonarSource for continuous inspection of code quality to perform automatic reviews with static analysis of code to detect bugs, code smells, and security vulnerabilities on 20+ programming languages.

开源协议:Lesser GNU General Public License

SonarQube 可以从以下七个维度检测代码质量,而作为开发人员至少需要处理前 5 种代码质量问题

  • 不遵循代码标准 SonarQube 可以通过 PMD,CheckStyle,Findbugs 等等代码规则检测工具规范代码编写。
  • 潜在的缺陷 SonarQube 可以通过 PMD,CheckStyle,Findbugs 等等代码规则检测工具检测出潜在的缺陷。
  • 糟糕的复杂度分布 文件、类、方法等,如果复杂度过高将难以改变,这会使得开发人员难以理解它们,且如果没有自动化的单元测试,对于程序中的任何组件的改变都将可能导致需要全面的回归测试。
  • 重复 显然程序中包含大量复制粘贴的代码是质量低下的,SonarQube 可以展示源码中重复严重的地方。
  • 注释不足或者过多 没有注释将使代码可读性变差,特别是当不可避免地出现人员变动时,程序的可读性将大幅下降 而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,亦违背初衷。
  • 缺乏单元测试 SonarQube 可以很方便地统计并展示单元测试覆盖率。
  • 糟糕的设计 通过 SonarQube 可以找出循环,展示包与包、类与类之间的相互依赖关系,可以检测自定义的架构规则 通过 SonarQube 可以管理第三方的 jar 包,可以利用 LCOM4 检测单个任务规则的应用情况, 检测耦合。

reference


2017-10-11

jenkins setup and introduction

Jenkins 是什么

Jenkins 是一个独立的开源自动化服务器,可用于自动化各种任务,如构建,测试和部署软件。Jenkins 可以通过本机系统包 Docker 安装,甚至可以通过安装 Java Runtime Environment 的任何机器独立运行。

Jenkins 有什么作用

用于持续、自动构建,测试项目,监控外部任务运行等。

模板类型

新建模板类型

  • Freestyle project 基础功能,执行构建任务
  • Pipeline,真实工作环境可能会包含,代码检查,编译,单元测试,部署等等任务,这个模板就是串行执行任务
  • Multi-configuration project job 跑在不同的机器上

问题

master/slave 节点配置

  • https://www.howtoforge.com/tutorial/ubuntu-jenkins-master-slave/

2017-10-10 jenkins , ci-cd , ci

电子书

最近文章

  • Linux 下使用 emoji Ubuntu 或者其他一些 Linux 发行版会内置 Google Noto Color emoji font
  • 理解 GraphQL Schema 结构定义 在上一篇 GraphQL 使用 中了解了 GraphQL 大致用法,如果要更加深入的了解 GraphQL ,那就不得不重新从 Schema 来认识 GraphQL,说到底 GraphQL 还是一个强类型定义,客户端可操作的类型都是需要提前定义好的,这个结构就是这篇文章的重点 Schema.
  • 从 MySQL 迁移到 PostgreSQL 方案调研 之前的文章 PostgreSQL 初识 和 PostgreSQL 数据类型 大致的把 PostgreSQL 了解了一下,那么接下来就是真正地把它用起来。
  • GraphQL 使用 很多人都知道 GraphQL 起源于 Facebook,但是似乎很少中文材料提到 GraphQL 出现的契机,我在看完这个纪录片 之后才对 GraphQL 的出现有更加深刻的了解。都知道当年 Facebook 的移动客户端都是网页,随着移动互联网发展,Facebook 网页实现的客户端性能和体验受到非常严重的影响,所以后来不得不去做原生的应用。那么这个时候就遇到了一个问题,原来直接使用网页,那么不同客户端用的接口都是给网页用的,最多做一下屏幕的适配,但是如果使用原生的应用,那么必然会需要设计不同的 API,而 Facebook 的工程师发现,对于复杂的 Feed 流,评论等等,用 RESTful 接口将是一个灾难,所以一帮人开始设计一种查询语言,这就是后来的 GraphQL。也应该纠正一下 Facebook 那帮工程师,只是开源了一份设计和一份实现,但他们万万没有想到开源社区的力量,就像片中 Nick Schrock 说的那样,他低估了社区的力量,在短短的几个月,几年时间中,GraphQL 就已经有了非常多语言的支持,周边应用也非常丰富。原来在脑海里的想法,都没有到生产环境中用过,就这样在所有社区的人的努力下成为了改变这个行业的一部分。
  • Drools : Guided Decision Table Column