PuTTY
2019-01-30
参考:https://github.com/altercation/solarized/blob/master/putty-colors-solarized/solarized_dark.reg
Colour21\255,255,255\
Colour20\187,187,187\
Colour19\85,255,255\
Colour18\0,187,187\
Colour17\255,85,255\
Colour16\187,0,187\
Colour15\85,85,255\
Colour14\0,0,187\
Colour13\255,255,85\
Colour12\187,187,0\
Colour11\85,255,85\
Colour10\0,187,0\
Colour9\255,85,85\
Colour8\187,0,0\
Colour7\85,85,85\
Colour6\0,0,0\
Colour5\0,255,0\
Colour4\0,0,0\
Colour3\85,85,85\
Colour2\0,0,0\
Colour1\255,255,255\
Colour0\187,187,187\
Colour0\131,148,150\
Colour1\147,161,161\
Colour2\0,43,54\
Colour3\7,54,66\
Colour4\0,43,54\
Colour5\238,232,213\
Colour6\7,54,66\
Colour7\0,43,56\
Colour8\220,50,47\
Colour9\203,75,22\
Colour10\133,153,0\
Colour11\88,110,117\
Colour12\181,137,0\
Colour13\101,123,131\
Colour14\38,139,210\
Colour15\131,148,150\
Colour16\211,54,130\
Colour17\108,113,196\
Colour18\42,161,152\
Colour19\147,161,161\
Colour20\238,232,213\
Colour21\253,246,227\
Email
2019-01-14
紧急程度 X-Priority
有另一个 Priority 头,不知道为什么没有使用。
根据网上的一些资料,这几个头已经被垃圾邮件滥用,导致可能会被拦截。
不过,企业邮箱使用应该没有问题。
网易邮箱发送的时候勾选重要,就会设置 X-Priority: 1。
需要发送回执 Disposition-Notification-To
效果就是客户端会提示:“是否发送回执”,确认 or 取消。
注意,不是所有客户端会支持回执。
mdn-request-header = "Disposition-Notification-To" ":" 1#mailbox
# mailbox 就是 local-poart@domain 这种格式
# RFC 中的这个 1# 我也不知道是干嘛用的
值是正常的邮件地址格式就行了,比如:
Disposition-Notification-To: admin@example.com
Disposition-Notification-To: =?utf-8?b?566h55CG5ZGY?= admin@example.com
注意:会和 Return-Path 的域名部分做对比,如果不一致,不会发送回执。
参考:https://www.rfc-editor.org/rfc/rfc2298.html
回执参考
主要是有这么一段:
Content-Type: message/disposition-notification; name="MDNPart2.txt"
Content-Disposition: inline
Content-Transfer-Encoding: 7bit
Reporting-UA: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0
Final-Recipient: rfc822;huang@example.com
Original-Message-ID: <2ec11bc0.59a.1803f61e0f9.Coremail.admin@example.com>
Disposition: manual-action/MDN-sent-manually; displayed
参考资料与拓展阅读
Python
2019-01-13
今天研究 secure cookie (安全的 Cookie) 的时候发现这个问题,觉得很好玩,之前还没有遇到过,没有注意。
a = b'hello'
a[0]
# 104
Python3 对 Bytes 类型索引取值返回的是一个整数!!!
这个以后需要小心,如果要像我们预期的那样,取一个字符的话,应该这样:
a = b'hello'
a[0:1]
# h
WebDev Cookie 安全 Tornado
2019-01-13
本文讲的是 Tornado 框架中的 “secure cookie” 实现。
Email
2019-01-10
介绍
iCal 历史
-
Versit 联盟阶段
1995 年,为了解决不同设备、不同程序之间交互个人数据(联系人、日程)困难的问题,苹果、AT&T、IBM 等公司组成 Versit 联盟,旨在制定个人信息交换(PDI)的开放标准。
后来,该组织设计了以下两个标准:
- vCard,用于交换名片信息,包括姓名、地址、电话号码、邮箱地址等。
- vCalender,用于交换日历信息,如日程、会议等。
基本格式都是这样,只是里面的字段定义不同:
BEGIN:type
key1:value1
key2:value2
END:type
-
IMC 联盟阶段
1996 年,为了促进上面两项标准的推广,Versit 联盟将相关格式所有权移交给了互联网邮件联盟(Internet Mail Consortium,IMC)。
PS:IMC 可能是 Versit 联盟成员拉拢更多公司组成的一个更大的联盟。
PS:2002 年,IMC 组织关门。
IMC closed down in 2002.
-
IETF 阶段
1998 年,IMC 将两个标准提交给 Internet Engineering Task Force (IETF) 标准化。
PS:vCalendar 经过 IETF 标准化之后改名 iCalendar 了。
支持情况
经过测试,至少 QQ 和 网易邮箱的 WebMail 都提供了日程的支持。
Thunderbird 只能通过日历 App 打开附件 (ics 文件) 的方式添加日程。
效果

原理
在邮件中插入了一个 text/calendar 类型的附件:
Content-Type: text/calendar; charset=utf-8; method=REQUEST;
name=ATT1547083200618.ics
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="ATT1547083200618.ics"
解析出来这样一个 iCal 文件:
BEGIN:VCALENDAR
PRODID:-//Netease//WebMail
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
SUMMARY:日程:上午十点的面试
LOCATION:小会议室
DTSTART:20190110T013000Z
DTEND:20190110T023000Z
UID:11c27eb7-adab-4549-8aea-efadcec7bb6c
SEQUENCE:0
STATUS:CONFIRMED
ORGANIZER;CN=张三:mailto:zhangsan@example.com
ATTENDEE:mailto:lisi@example.com
END:VEVENT
END:VCALENDAR
回复
这个回复就各异了,没有同意的格式。
QQ 邮件只会有一个 自动回复: xxxx,不知道是接受还是拒绝。
QQ 企业邮件会有详细的信息,附带了原日程,并有一句话:xxx 已经接受你的邀请: 日程:xxx。
参考资料与拓展阅读
WebDev 缓存
2019-01-06
Apache,Nginx 都有缓存功能,再加上 Redis 做动态数据的缓存,再加上 CDN,所以我还没有用过专门的缓存服务。
但是这些服务真是大名鼎鼎,即便不用,我也可以先列出来做个简单的了解。
Git
2019-01-03
命令
usage: git submodule [--quiet] [--cached]
or: git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: git submodule [--quiet] init [--] [<path>...]
or: git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...]
or: git submodule [--quiet] set-branch (--default|--branch <branch>) [--] <path>
or: git submodule [--quiet] set-url [--] <path> <newurl>
or: git submodule [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: git submodule [--quiet] foreach [--recursive] <command>
or: git submodule [--quiet] sync [--recursive] [--] [<path>...]
or: git submodule [--quiet] absorbgitdirs [--] [<path>...]
相关文件
-
.gitmodules
[submodule "<moduleName>"]
path = <moduleDir>
url = <repoAddr>
-
.git/config 中有相近的 section:
[submodule "<moduleName>"]
active = true
url = <repoAddr>
-
.git 目录在 .git/modules/<moduleName>
克隆
参考:https://stackoverflow.com/questions/3796927/how-to-git-clone-including-submodules
git clone --recurse-submodules -j8 github.com:shouce/shouce.git # 2.13+
git clone --recursive -j8 github.com:shouce/shouce.git # 1.6.5+
-j 表示子模块并发操作,每次 n 个子模块。
针对更老的版本或者以存在的库:
git clone github.com:shouce/shouce.git
cd shouce
git submodule update --init --recursive
发现一个 clone 参数 --[no-]shallow-submodules,可以使每个子模块仓库的克隆 deepth 为 1,应该是用得上的。
已存在的项目
可能是克隆的时候没有克隆子仓库,也可能是后面添加进来的子仓库。
$ git submodule init
Submodule '<moduleName>' (<repoAddr>) registered for path '<moduleDir>'
$ git submodule update
Cloning into '<moduleFullPath>'...
Submodule path '<moduleDir>': checked out '<commitID>'
或者二合一:
git submodule update --init --recursive
后面有更新就进入子模块 git pull。
添加子模块
git submodule add -b dev --name devtools gitee.com:catroll/devtools tools/dev
# [submodule "devtools"]
# path = tools/dev
# url = gitee.com:catroll/devtools
# branch = dev
删除子模块
$ git submodule deinit <moduleDir>
Cleared directory '<moduleDir>'
Submodule '<moduleName>' (<remoteAddr>) unregistered for path '<moduleDir>'
作用:
- 清空子模块目录下的所有文件
- 去掉 .git/config 子模块配置
这个操作之后:git status 没有任何变化,.gitmodule 还保留着。
然后:
- 修改 .gitmodules
- 删除子模块目录
- 提交变更
- 推送到远程仓库
ORM 软件开发
2019-01-01
:) 本文正在编辑中,暂时不提供浏览...
Python Pipenv Virtualenv Crontab
2018-12-20
部署
# curl: (35) SSL connect error
# StackOverflow: You are using a very old version of curl.
# yum upgrade curl
# 安装 pyenv
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
# 可用版本列表
pyenv install -l
# 使用国内 Python 镜像,相当于给 pyenv 加速
wget https://mirrors.sohu.com/python/3.6.7/Python-3.6.7.tar.xz -P ~/.pyenv/cache/
# 安装(优先使用缓存目录中的文件,会检查缓存校验码是否正确)
pyenv install 3.6.7
运行方式
假定:
- 项目路径:
/path/to/project/
- 定时任务命令:
python main.py
crontab 配置
早上 01:15 执行某某定时任务:
15 1 * * * /bin/bash /path/to/project/cron.sh
脚本 cron.sh
pyenv + pip 模式
#!/bin/bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
cd /path/to/project/
# 创建并激活虚拟环境,安装依赖
# $PYENV_ROOT/versions/3.6.7/envs/tasks/
pyenv virtualenv 3.6.7 tasks
if [ $? -ne 0 ]; then
pyenv activate tasks
pip install -r requirements.txt
else
pyenv activate tasks
fi
# 运行脚本
python main.py
pyenv + pipenv 模式
#!/bin/bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
cd /path/to/project/
# 选择 Python 版本
pyenv local 3.6.7
pip show pipenv > /dev/null
if [ $? -ne 0 ]; then
# 安装 pipenv
pip install pipenv
# 创建虚拟环境,安装依赖
pipenv install
fi
# 运行脚本
pipenv run python main.py
WebDev SSO OpenLDAP CAS Auth
2018-12-16
这套方案名气比较大,了解看看。