根据时间自动切分 Nginx.log

之前是用脚本配合 crontab 来做日志切分:

#!/bin/bash
# This script run at 00:00

# The Nginx logs path
logs_path="/usr/local/webserver/nginx/logs/"

mkdir -p ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/
mv ${logs_path}access.log ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/access_$(date -d "yesterday" +"%Y%m%d").log
kill -USR1 `cat /usr/local/webserver/nginx/nginx.pid`

最近发现可以直接在 nginx.conf 里通过 $time_iso8601 提取时间进行设置:

if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})") {
    set $year $1;
    set $month $2;
    set $day $3;
}

access_log /var/log/nginx/$year-$month-$day-access.log;

时间粒度可以更为精细:

if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})") {
    set $year $1;
    set $month $2;
    set $day $3;
    set $hour $4;
    set $minutes $5;
    set $seconds $6;
}

via Log rotation directly within Nginx configuration file

28

28.

六六陪爸爸过的第一个生日,妈妈代笔写了贺卡,我 28 了。

Monthly Review 2015-07

  1. 长岛休假半个月。圈个海岸就收钱,沙滩特别差,不推荐去玩。
  2. 第一次带老婆去海边,所以尽管环境不行,前几天玩的还算开心。
  3. 按老家习俗给六六过了一岁生日,农历。
  4. 接六六来北京,尽管很难,尽管很多阻力,至少走出这一步,希望一切向好的方面发展。

Monthly Review 2015-06

  1. 用 Angular Material 写了个管理平台,体验很赞。
  2. Gin 改写了部分接口,现在是 Python+ngx_lua+Go,目前情绪稳定。
  3. Gin 是个不错的框架,够轻量,middleware 扩展,封装适度,性能也不错。另一个是 Goji,两个都是我比较喜欢的。
  4. gorm 不错,目前项目比较简单,就直接通过 gorm 新建表结构,之前一个项目 Python+Go 都会涉及数据库,采取的策略是手动建表,ORM 只负责读写。
  5. 前两天看《非你莫属》,20岁小哥,完全没有互联网从业经验,就因为看现在 O2O 火了,自以为有很多 ideas,要转投移动互联网,应聘产品经理。PM 就是这么被毁的啊。
  6. 6月24日,六六一岁了。

Angular Material

又尝试了点新东西,Angular Material,写了一个的管理后台。

  1. Angular Material 是基于 Flexbox 做布局,在此基础上添加了 layout HTML 属性,写起来非常清爽:layout="row" 横向,layout="column" 纵向。
  2. build-in directives 很丰富,一整套界面写下来,目前最欠缺一个日期时间选择器。
  3. material-start 快速上手包,完整的 Angular Material 实例。
  4. 迭代更新很快,相对来说文档更新差一步,有时候需要看 demo 源码。
  5. 自带主题支持。
  6. 体积较大,min css+js 将近 400K。

5 Years in Beijing

5 years in Beijing. 5 years in Appwill.

Monthly Review 2015-05

  1. 线上环境加上 InfluxDB 作为日志存储,可以实时查看缓存命中率,在线用户数,关键请求数量,但是还没想好日志数据的进一步挖掘,所以说技术没有转化成产品前,并没有什么卵用。
  2. InfluxDB 还是有不少坑,0.9+ 在无限 RC 中,配套工具比如 Grafana 还不支持。0.8 疑似有内存泄漏,数据量稍大的查询很慢(百万级总量,10m 粒度)。还需要一些摸索,然后转化为产品指标。
  3. 又一次写前端,完整项目,这次简化开发流程,放弃 Yeoman/Grunt/Bower 等工具,过于强大到很多功能都用不上,只用 npm 作为包管理和构建工具,npm run 完全可以满足需要。
  4. 给六六做了图片 blog,按时间顺序贴照片,时间过的真快,马上就一岁了。
  5. Google Photos 是个好产品,almost the best,存储了过去十年我几乎所有照片。

避免 rm 误操作

规避 rm -rf * 操作:

目录下新建 -i 文件, touch -- -i or touch ./-i

但是对于 rm -rf ./* 无效。

safe-rm 加持保护。

不要 alias rm='rm -i',一旦习惯后在没有 alias 的机子上很容易误伤,可以新建别名,比如 alias del='rm -i',然后习惯用 del 代替 rm.

最后,不要偷懒而滥用 root

One-Time Password

两步验证是基于 HOTP/TOTP 算法的验证方案,在登录的时候除了密码,也需要提供动态数字(一般是六位数)验证。其中 HOTP(HMAC-based One-time Password) 是计数器令牌,一定次数内有效,TOTP(Time-based One-time Password) 只是一定时间内有效。

可以用两步验证的思路做一个没有固定密码,只有动态密码的注册登录流程:

  1. 发送用户邮箱到服务器,检查邮箱对应的用户是否存在。
  2. 用户不存在,新建用户,根据邮箱生成密钥并保存,引导用户通过 Google Authenticator/Authy 等保存密钥,可以验证一次确保密钥成功保存,注册成功并登录。
  3. 用户存在,提示用户填写 Google Authenticator/Authy 生成的验证码,服务器验证是否有效。
  4. 如果用户密钥忘记或被盗,可以通过邮件进行验证,然后重新设置密钥并保存。

整个流程和手机短信验证类似,不同的是通过软件保存密钥并生成验证码,而不是手机短信获取。其中 根据邮箱生成密钥是关键,如果算法过于简单,别人知道邮箱后很容易就能猜出密钥,进而得到验证码。初步想到的算法:邮箱+时间戳,SHA/MD5/AES/RC4 等加密计算。

当然这套验证的前提条件是没有物理接触:如果服务被攻陷或拿到密钥算法,整个就完蛋。如果用户手机被拿到,自然就能随便登录。

Nginx/OpenResty 指令的执行顺序

  1. http, 可以通过 init_by_lua 加载公共函数,比如 lua-resty-core.
  2. server selection,listen,server_name.
  3. post read, ngx_realip.
  4. server rewrite, set, rewrite, return, set_by_lua.
  5. server rewrite tail, rewrite_by_lua.
  6. server access, allow, deny.
  7. server access tail, access_by_lua.
  8. server try_files.
  9. location:
    1. prefix strings 遵循 最长子串匹配原则
    2. regular expressions 遵循 先定义优先匹配原则
    3. location = {exact_url} 精准匹配
    4. location ~ {case-sensitive regex} 区分大小写
    5. location ~* {case-insensitive regex} 不区分大小写
    6. location ^~ {prefix_string_if_any} 一旦字符匹配成功,就不再正则匹配
    7. 尽量不要 if,换用 try_files
    8. -f 检测文件是否存在,-d 目录,-e 文件/目录/符号链接,-x 可执行文件
  10. location rewrite, set, rewrite, return, set_by_lua.
  11. location rewrite tail, rewrite_by_lua.
  12. preaccess, degradation, limit_zone, limit req, ngx_realip.
  13. location access, allow, deny, auth_basic.
  14. location access tail, access_by_lua.
  15. content, ngx_echo, proxy_pass, content_by_lua.
    1. 请求具体处理阶段,只能有一个 内容处理程序(content handler)
    2. 多个 echo 可以共存,因为同属于 ngx_echo 模块,但 ngx_lua 限制只能有一个 content_by_lua.
    3. ngx_echo 的 echo_before_body/echo_after_body 可以和其他模块共存
    4. 如果没有 ngx_echo, proxy_pass, content_lua 这些 content handler,Nginx 会根据 URL 将请求映射到静态资源服务模块,依次是 ngx_index, ngx_autoindex, ngx_static.
    5. ngx_index/ngx_autoindex 处理以 / 结尾的请求,ngx_static 正好相反。
  16. output header filter, more_set_headers 输出 Headers.
  17. output filter echo_before_body, echo_after_body, body_filter_by_lua.
  18. log, access_log, error_log, log_by_lua.
  19. post action.