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.

via XDG Base Directory Specification

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.

Development in Startup

dev-culture

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:

技术的作用从短期来看往往被高估,但是从长期来看又往往容易被低估。