looking a wood sprite in the forest
let's encrypt
Let’s Encrypt 已经公开测试,不需要再提交测试域名表单,直接就能申请
小项目以后都能用这玩意开 https 不用花钱买证书哦啦啦
照 文档 做一遍给域名签上证书还挺简单的
# 获取项目代码
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
# 安装依赖
./letsencrypt-auto
# 获取证书
./letsencrypt-auto certonly --standalone -d www.example.com -d example.com
# 配置 nginx
server {
listen 443 ;
ssl on;
ssl_certificate_key /etc/letsencrypt/live/youdomain/privkey.pem;
ssl_certificate /etc/letsencrypt/live/youdomain/fullchain.pem;
}
需要注意的是 dnspod 等国内服务解析域名有问题
我这里直接切回 domains.google.com 就行了
使用 standalone 模式需要先停掉默认的 nginx
文档里提到可以使用 webroot 模式不用停
但我创建验证文件失败了 :(
默认90天过期,建议 crontab 定时更新
###Update
使用 acme.sh
- An ACME protocol client written purely in Shell (Unix shell) language.
- Fully ACME protocol implementation.
- Simple, powerful and very easy to use. You only need 3 minutes to learn.
- Bash, dash and sh compatible.
- Simplest shell script for Let’s Encrypt free certificate client.
- Purely written in Shell with no dependencies on python or Let’s Encrypt official client.
- Just one script, to issue, renew and install your certificates automatically.
或者 caddyserver
…simple crawler
半夜看了本小说觉得翻页太累
首先要解决的问题是找一个质量还过得去的小说站 然后写个脚本去把它爬下来章节合并到一起
import fs from "fs";
import { argv } from "process";
import request from "request";
import cheerio from "cheerio";
import iconv from "iconv-lite";
import sanitize from 'sanitize-html';
class main {
constructor() {
Object.assign(this, {
path: './chapter.json',
html: './reader.html',
url: {
list: 'http://www.piaotian.net/html/6/6658/'
},
store: []
})
}
fetch(url, callback) {
request.get(url, {encoding: null}, (error, response, body)=> {
if (!error && response.statusCode == 200) {
let $ = cheerio.load(iconv.decode(body, 'GBK'));
callback($, body);
} else {
console.log(url);
}
})
}
runchapter() {
this.store.map(d=> {
if (!d.content) {
this.fetch(this.url.list + d.href, ($, body)=> {
let content = iconv.decode(body, 'GBK');
d.content = sanitize(content);
this.save();
})
} else {
console.log('runchapter fail: ', d.id, d.title);
}
})
this.output();
}
output() {
//let content = this.store.slice(0, 2)
let content = this.store
.map(d=> d.content)
.join('<hr />');
let html = `<html>
<head>
<meta charset="utf8" />
<style>
ul, table, div {
display: none;
}
hr {
height: 1px;
margin: 4rem 0;
}
body {
padding: 0 20%;
font:24px/1.5 'Songti Sc';
}
</style>
</head>
<body>${content}</body></html>`;
fs.writeFileSync(this.html, html, 'utf8');
}
reload() {
this.fetch(this.url.list, ($)=> {
this.store = [];
$('.mainbody .centent ul li a').map((id, d)=> {
let el = $(d);
let href = el.attr('href');
if (!href.endsWith('.html')) {
return
}
this.store.push({ id, href, title: el.text() })
})
this.save();
this.runchapter();
})
}
config(force){
if (force) {
this.reload();
} esle {
let text = fs.readFileSync(this.path, 'utf8').toString();
this.store = JSON.parse(text);
this.runchapter();
}
}
save() {
fs.writeFileSync(this.path, JSON.stringify(this.store), 'utf8');
}
init() {
let force = argv[2] === '-f';
console.log('run: ', argv[2], force);
this.config(force);
}
}
new main().init();
于是就水出来一篇日志啦
…send notification when task finish
终端里运行长时间任务(比如 make systemimage
)的时候经常会切换到其他环境做别的事情
容易忘记查看之前的任务是否完成, 查到一些方法用在任务结束时发出通知
#C-z 切到后台运行
fg; tput bel
# Mac OS X
#系统弹窗
osascript -e 'tell app "System Events" to display alert "Build Completed" message "The checkout and build have completed."'
say "Job finished" #语音播报
#notification center
osascript -e 'display notification "Job finished" with title "Alert"'
sudo gem install terminal-notifier
terminal-notifier -message "Job finished!" -title "Alert"
# Ubuntu
notify-send "Job finished!"
# KDE
kdialog --passivepopup 'Job finished'
还有 iterm2 trigger 也能用来触发通知, 高亮文字
…create CNAME with internationalized domain name
Read more ⟶
xtag-and-shadowdom
最近在做的项目重构, 原本打算用 reactjs, 写了一些实验代码后心累无爱 找了个 domdiff 配合自定义标签和 shadowdom 的独有作用域也是爽 YY
可惜的是测试红米上的 android webview 版本(32?)不支持 ::shadow 伪类 inline 方式覆盖样式略嫌繁琐
示例代码
xtag.js
let dom = {
shadow(el) {
return el.createShadowRoot ? el.createShadowRoot() : el.webkitCreateShadowRoot();
},
attr(el, prefix='') {
return Object.keys(el.dataset).map((d)=> `${prefix}${d}="${el.dataset[d]}"`).join(' ')
}
}
document.registerElement('x-image', {
prototype: Object.create(HTMLElement.prototype, {
createdCallback: {
value() {
//xtag 嵌套时这里读不到attr, 放到 attach
console.log('onCreate::image');
}
},
attachedCallback: {
value() {
console.log('onAttach::image');
let shadow = dom.shadow(this);
shadow.innerHTML = `<style>
img { max-width: 100%; }
</style>
<img ${dom.attr(this)} />`;
this.onclick = (e) => {
console.log(this);
}
}
}
})
});
// other x-tag;
index.js
import 'babel/polyfill';
import './xtag.js';
class BaseView {
constructor(opt) {
Object.assign(this, {
root: dom('#app')
}, opt);
}
mount() {
console.log('event::mount');
}
onCreate() {
console.log('event::create');
}
onUpdate() {
console.log('event::update');
}
}
export default class BannerView extends BaseView {
init(...args) {
this.mount(...args);
}
render() {
return `<x-image data-src="${this.src}"
data-href="${this.redirect_url}" />`;
}
}
links
http://www.html5rocks.com/en/tutorials/webcomponents/customelements/ http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/
…remote pbcopy with netcat
Quick start
while (true); do nc -l 2224 | pbcopy; done
#If your laptop is running linux, replacing pbcopy with xcopy should work:
#while (true); do nc -l 2224 | xcopy; done
echo "This text gets sent to clipboard" | nc localhost 2224
echo "RemoteForward 2224 localhost:2224" >> ~/.ssh/config
ssh remote -t 'cat blablabla | nc -q0 localhost 2224'
Daemonizing pbcopy
launchctl load ~/Library/LaunchAgents/local.pbcopy.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>localhost.pbcopy</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/pbcopy</string>
</array>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<false/>
</dict>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockServiceName</key>
<string>2224</string>
<key>SockNodeName</key>
<string>127.0.0.1</string>
</dict>
</dict>
</dict>
</plist>
Remote pbcopy
scp pbcopy remote:/path_to/pbcopy
chmod a+x path_to/pbcopy
#!/bin/bash
[ -n "$SSH_CLIENT" ] && SESSION_TYPE="remote"
if [[ $SESSION_TYPE == "remote" ]]; then
cat | nc -q0 localhost 2224
else
cat | pbcopy
fi
links
http://brettterpstra.com/2014/02/19/remote-pbcopy-on-os-x-systems/
…forward email by postfix
sudo aptitude install postfix
hostname -f
# sudo vim /etc/postfix/main.cf
myhostname = example.com
myorigin = example.com
mydestination = example1.com, example2.com, ...
virtual_alias_maps = hash:/etc/postfix/virtual
# sudo vim /etc/postfix/virtual
@example1.com name@forward.com
@example2.com name@forward.com
sudo postmap /etc/postfix/virtual
sudo /etc/init.d/postfix reload
https://wiki.debian.org/Postfix#Forward_Emails
https://www.linode.com/docs/email/postfix/basic-postfix-email-gateway-on-debian-6-squeeze
…mitmproxy
mitmproxy 是个命令行下查看/修改 http 请求的交互式工具
#截图
#安装
sudo apt-get install python-dev libffi-dev
pip install mitmproxy
#使用
ubuntu 上启动 mitmproxy
mitmproxy –host
手机 设置 -> WLAN -> 代理
主机名: ubuntu 的 ip
端口: 8080
然后访问网络就会在 mitmproxy 里看到请求记录(如截图)
#快捷键
j,k 上下移动
enter 进入
tab 切换 request/response
#参考
http://mitmproxy.org/doc/mitmproxy.html
http://blog.philippheckel.com/2013/07/01/how-to-use-mitmproxy-to-read-and-modify-https-traffic-of-your-phone/
brick intro
#Introducing Brick: Minimal-markup Web Components for Faster App Development #介绍 brick: 用于快速开发 webapp 的自定义标签组件
Those of you on the cutting HTML5 edge may have already heard of the exciting Web Components specification. If you haven’t, you’ll probably want to read up on what makes this so exciting, but long story short, Web Components promise to open up a new realm of development by letting web developers write custom, reusable HTML tags. Think of them as JavaScript plugins without the need for additional code initialization or boilerplate markup/styling.
…my osx setup
#setting
# Enable full keyboard access for all controls
defaults write NSGlobalDomain AppleKeyboardUIMode -int 3
# Disable menu bar transparency
defaults write NSGlobalDomain AppleEnableMenuBarTransparency -bool false
# Allow quitting Finder via ⌘ + Q; doing so will also hide desktop icons
defaults write com.apple.finder QuitMenuItem -bool true
# Avoid creating .DS_Store files on network volumes
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
# Disable the warning when changing a file extension
defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false
# Enable tap to click (Trackpad)
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
# Enable Safari’s debug menu
defaults write com.apple.Safari IncludeInternalDebugMenu -bool true
# To pin the dock to the right bottom
defaults write com.apple.dock pinning -string end
defaults write com.apple.dock orientation -string right
# Only Show Open Applications In The Dock
defaults write com.apple.dock static-only -bool true
defaults write com.apple.dock tilesize -int 24
defaults write com.apple.finder QLEnableTextSelection -bool true
# disable dashboard
defaults write com.apple.dashboard mcx-disabled -boolean true
#xcode with Command Line Tools
…