XDG Base Directory
XDG 是 X Desktop Group 的简称,现在叫 Freedesktop.org,致力于推动 *nix 桌面环境的标准规范化。其中 XDG Base Directory 定义了文件配置基本目录:
$XDG_CONFIG_HOME
是配置文件目录,默认$HOME/.config
$XDG_DATA_HOME
是用户文件的基本保存目录,默认$HOME/.local/share
$XDG_DATA_DIRS
定义$XDG_DATA_HOME
以外的文件基础目录,是一个有序目录集合,默认/usr/local/share/:/usr/share/
$XDG_CONFIG_DIRS
同理,是扩展的配置文件目录,默认/etc/xdg
,需要注意的是目录顺序很重要,$XDG_CONFIG_HOME
优先级最高$XDG_CACHE_HOME
缓存目录,默认$HOME/.cache
$XDG_RUNTIME_DIR
指定非必需运行时文件保存目录
Neovim 支持 XDG Base Directory,配置文件是 $HOME/.config/nvim/init.vim
,shada 文件在 $HOME/.local/share/nvim
.
Verify SSL certificate and key
You can use OpenSSL
to verify whether a SSL certificate and a key is matched:
openssl x509 -noout -in certificate.crt | openssl md5
openssl rsa -noout -in privateKey.key | openssl md5
openssl req -noout -in CSR.csr | openssl md5
If both commands return same hash, the certificate and key is matched.
Fix "Enter passphrase for key" on macOS
You will be asked ‘Enter passphrase for key’ when doing SSH operation:
Enter passphrase for key ‘/Users/fannheyward/.ssh/id_rsa’:
On macOS you can fix this by ssh-add -K
.
pushd / popd
cd -
can goto last directory that you just leave, -
means $OLDPWD
. This only support one directory.
pushd / popd / dirs
works on multiple directories, as a directory stack:
pushd [dir1] # add dir to stack
popd [dir1] # pop dir from stack
dirs # list stack
dirs -c # cleanup stack
Ansible notes
Ansible 是基于 SSH 的自动化配置管理和部署工具,更多请参考官方文档。
ansible -i hosts.ini all -m ping
ansible-playbook -i hosts.ini playbook.yaml
用 Ansible + Supervisor 部署/更新应用:
- hosts: server
tasks:
- name: check if exists
stat: path=/path/to/app
register: check_path
- name: clone
shell: git clone XXX && git checkout -b release
when: check_path.stat.exists == false
- name: pull
shell: cd /path/to/app && git pull origin release
when: check_path.stat.exists
- name: is already running ?
stat: path=/tmp/supervisord.pid
register: supervisord_stat
- name: restart
command: supervisorctl -c supervisord.conf restart all
args:
chdir: /path/to/app
when: supervisord_stat.stat.exists
- name: start
command: supervisord -c supervisord.conf
args:
chdir: /path/to/app
when: supervisord_stat.stat.exists == false
TLS 1.2+ in Nginx
小程序要求 HTTPS 并且 TLS 1.2 以上,不然会报错:
小程序要求的 TLS 版本必须大于等于 1.2
Nginx 下需要用新版 OpenSSL 重新编译 Nginx。官网下载新版 OpenSSL 和 Nginx:
./configure —with-http_ssl_module —with-openssl=/home/page/soft/openssl-1.0.2k -j8
make -j8
make install
重启 Nginx 即可。
Golang sync.WaitGroup
sync.WaitGroup
waits for a collection of goroutines to finish. 类似一个计数器,添加任务加一,完成任务减一,非零即阻塞。
- Add(x) 添加到计数器,需要注意的是必须在 main goroutine 执行
- Done() 计数器减一
- Wait() 阻塞 main goroutine 执行,直到所有 goroutine 执行完成。
var wg sync.WaitGroup
var urls = []string{
"http://www.google.com/",
"http://fann.im/",
}
var errChan = make(chan error, len(urls))
for _, url := range urls {
wg.Add(1)
go func(url string) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
errChan <- err
}
defer resp.Body.Close()
}(url)
}
wg.Wait()
close(errChan)
for err := range errChan {
if err != nil {
log.Println(err.Error())
}
}
errgroup 提供了类似的功能:
var g errgroup.Group
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
}
for _, url := range urls {
// Launch a goroutine to fetch the URL.
url := url // https://golang.org/doc/faq#closures_and_goroutines
g.Go(func() error {
// Fetch the URL.
resp, err := http.Get(url)
if err == nil {
resp.Body.Close()
}
return err
})
}
// Wait for all HTTP fetches to complete.
if err := g.Wait(); err == nil {
fmt.Println("Successfully fetched all URLs.")
}
六六
清明节假期带六六回老家,很多好玩的:
- 高铁上,六六趴窗户上说:爸爸这地铁飞得好快!
- 她现在已经不会说家乡话,尽管还能听懂,但一开口就是普通话。六六追着邻居小朋友问:小朋友们,你们还记得我吗?
- 有一个小孩比她就大一两岁,按辈份得叫人姑姑,六六就不:是小姐姐,不是姑姑!
- “爸爸爸爸,我给小朋友分饼干吃”。作为一个小吃货,能这样还挺让我意外。
- 会主动跟小朋友分享玩具,包括自己最喜欢的玩具琴。
- 去朋友家玩,会把小弟弟的玩具收起来,敢开口跟人打招呼,走的时候会跟所有人拜拜。
- 上山看见桃花,“爸爸我要那花”,我去摘花的时候在后面大叫 “爸爸 你小心一点”。
- 摔跤擦破了手,哭着找每个人求安慰,最后找爸爸擦药,哭的那叫一个伤心,忽然瞅见玩具小人的头在地上,瞬间不哭捡起来一本正经的说“这个头怎么掉了?”,然后又看着爸爸举着手哭。
- 走之前收拾行李,六六拿了一个塑料袋也要收拾行李,“爸爸,我把这个小鸭子带着吧,小鸭子最可爱了”,于是我们就把她那两个很早以前的小鸭子带到了北京。
The Role of Technology
@Fenng:
技术的作用从短期来看往往被高估,但是从长期来看又往往容易被低估。