机械境

这里只是我的后花园,随性而写

环境变量换行

1
2
3
4
# base64 编码
export PRIVATE_KEY=$(cat ~/private_key.gpg | base64)
# 用的时候,base64解码
echo -e "${PRIVATE_KEY}" | base64 -d >"$key_file"

常用别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# ------------------------------------
# Docker alias and function
# ------------------------------------

# Get latest container ID
alias dl="docker ps -l -q"

# Get container process
alias dps="docker ps"

# Get process included stop container
alias dpa="docker ps -a"

# Get images
alias di="docker images"

# Get container IP
alias dip="docker inspect --format '{{ .NetworkSettings.IPAddress }}'"

# Run deamonized container, e.g., $dkd base /bin/echo hello
alias dkd="docker run -d -P"

# Run interactive container, e.g., $dki base /bin/bash
alias dki="docker run -i -t -P"

# Execute interactive container, e.g., $dex base /bin/bash
alias dex="docker exec -i -t"

# Stop all containers
dstop() { docker stop $(docker ps -a -q); }

# Remove all containers
drm() { docker rm $(docker ps -a -q); }

# Stop and Remove all containers
alias drmf='docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)'

# Remove all images
dri() { docker rmi $(docker images -q); }

# Dockerfile build, e.g., $dbu tcnksm/test
dbu() { docker build -t=$1 .; }

# Show all alias related docker
dalias() { alias | grep 'docker' | sed "s/^\([^=]*\)=\(.*\)/\1 => \2/"| sed "s/['|\']//g" | sort; }

# Bash into running container
dbash() { docker exec -it $(docker ps -aqf "name=$1") bash; }

---EOF---

缘起

之前一个项目做预研的时候搞了个树莓派 3B,测试完之后,一直处于吃灰状态。刚好最近经常给小朋友打印东西,家里那台老的 HP P1106 不支持无线打印,每次都接 USB 才能打印,让人无比烦躁。于是乎抽空把打印机接到树莓派上,利用 cups 做成无线打印。

安装系统

烧镜像

  • 官网 下载最新的镜像
  • 可以通过 dd 把镜像复制到 SD 卡中,具体方法参考 官方指南
  • 也可以通过 Etcherbrew cask install balenaetcher 即可,傻瓜式操作
    Read more »

    思路

    cgo 交叉编译 中通过 xgo + Docker 实现 Cgo 的交叉编译。由于原版 xgo 不支持 go mod,而且作者貌似也没支持的打算,所有我自己维护了一个 xgo。使用了一段时间下来看,除了编译速度有点慢意外,其他还好。这也是跟我们的使用方式有关,我们需要根据不同的 tags 来编译不不同的版本,xgo 每次编译都要构建一个 Docker 实例,然后下载引用的库等等一大堆重复操作,导致整个编译时间拉长。

    既然有很多重复操作,那就换个思路,只构建一个实例,把编译环境准备好,然后在这个实例中把要编译的内容,一次编译出来。goreleaser,支持编译发布 golang 的二进制文件,同时也支持发布 Docker 镜像,但是这不是重点,这里不再赘述。

    实践

    由于需要支持 macOS 就需要安装 OSX 的 SDK,在 xgo 是自己构建的基础镜像。这里通过 Docker 官方提供的 golang-cross 来作为基础镜像支持 macOS 平台,顺便规避一下版权的问题。在此基础上安装 mingw 支持 Windows x64/i386,以及 arm-gcc 等。剩下的就是一些常规操作了,比如安装 goreleaser,更新 golang 运行时等,完整的 Dockerfile

    使用

    1
    2
    3
    4
    5
    docker run --rm --privileged \
    -v $PWD:/go/src/github.com/qlcchain/go-qlc \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -w /go/src/github.com/qlcchain/go-qlc \
    goreng/golang-cross goreleaser --snapshot --rm-dist

    当然也是可以添加到 makefile 中的

    1
    2
    3
    4
    5
    6
    7
    8
    snapshot:
    docker run --rm --privileged \
    -v $(CURDIR):/go-qlc \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v $(GOPATH)/src:/go/src \
    -w /go-qlc \
    goreng/golang-cross:$(GO_BUILDER_VERSION) \
    goreleaser --snapshot --rm-dist

    使用的时候,只需要执行 make snapshot 即可。

    小结

    使用新的镜像之后,整体编译速度有了比较大幅度的提升,得益于 goreleaser 对打包的支持,原来自己实现 shell 打包生成 checksum 的操作,都有现成的支持。

    ---EOF---

    前面在 traefik 配置 docker 容器支持 HTTPS 中介绍了如果使用 traefik 为 docker 提供支持 SSL 的反向代理。在示例中,qlc_wallet_server 中 HTTP 和 WebSocket 共用了一个端口,该端口支持 SSL,可以通过 https://api.example.comwss://api.example.com 访问。但是如果在同一个容器中使用不同的端口呢?如果支持,如果实现?

    答案显然是可以支持的,但是我翻遍官方文档也没找到具体的说明。其实在 基于 Treafik 部署 Bitwarden RS 中部署 Bitwarden 的时候,已经使用了,在一个容器中,bitwarden-RS 通过 80 端口提供 RESTful 的接口,同时通过 3012 端口提供 Websocket 连接用来推送数据变化的通知。

    1
    2
    3
    4
    5
    6
    7
    8
    labels:
    - traefik.enable=true
    - traefik.web.frontend.rule=Host:bitwarden.example.com
    - traefik.web.port=80
    - traefik.hub.frontend.rule=Host:bitwarden.example.com;Path:/notifications/hub
    - traefik.hub.port=3012
    - traefik.hub.protocol=ws
    - traefik.docker.network=traefik

    定义两个不同的实例,webhub,分别指定端口,hub 是 WebSocket ,需要手动指定 protocol。一定要注意的是,千万不能手动指定 backend。要不然 traefik 就会这个容器中对这两个端口做负载均衡。

    --EOF---

    GitHub Actions 由 GitHub 官方推出的工作流工具。典型的应用场景应该是 CI/CD,类似 Travis 的用法。这里介绍响应 git push 事件触发 Hexo 编译静态页面并推送到 GitHub Pages 的用法。

    准备工作

    • 生成 ssh 部署私钥
      1
      ssh-keygen -t ed25519 -f ~/.ssh/github-actions-deploy
    • 在 GitHub repo 的 Settings/Deploy keys 中添加刚刚生成的公钥
    • 在 GitHub repo 的 Settings/Secrets 中添加 GH_ACTION_DEPLOY_KEY,值为刚刚生成的私钥

    编写 GitHub Actions

    • 在项目的根目录添加 deploy.yml,目录结构如下

      1
      2
      3
      .github
      └── workflows
      └── deploy.yml
    • 步骤

      • 添加部署私钥到 GitHub Actions 执行的容器中
      • 在容器中安装 Hexo 以及相关的插件
      • 更新主题 NexT 的配置
      • 编译静态页面
      • 推送编译好的文件到 GitHub Pages
    • 编写部署的 action

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      name: Main workflow

      on:
      push:
      branches:
      - raw

      jobs:
      build:

      runs-on: ubuntu-18.04

      steps:
      - uses: actions/checkout@v2
      - name: Use Node.js lts
      uses: actions/setup-node@v2-beta
      with:
      node-version: '12.x'
      - name: prepare build env
      env:
      GH_ACTION_DEPLOY_KEY: ${{ secrets.GH_ACTION_DEPLOY_KEY }}
      NEXT_VERSION: v8.0.0-rc.2
      run: |
      mkdir -p ~/.ssh/
      echo "$GH_ACTION_DEPLOY_KEY" > ~/.ssh/id_rsa
      chmod 600 ~/.ssh/id_rsa
      ssh-keyscan github.com >> ~/.ssh/known_hosts
      git config --global user.name 'gythialy'
      git config --global user.email 'gythialy@users.noreply.github.com'
      npm i -g hexo-cli
      npm i
      git clone --branch ${NEXT_VERSION} --depth=10 git@github.com:next-theme/hexo-theme-next.git themes/next
      git checkout -b ${NEXT_VERSION}
      git clone git@github.com:next-theme/theme-next-three --depth=1 themes/next/source/lib/three
      # git clone git@github.com:next-theme/theme-next-fancybox3 --depth=1 themes/next/source/lib/fancybox
      git clone git@github.com:next-theme/theme-next-pace --depth=1 themes/next/source/lib/pace
      - name: deploy to github
      env:
      HEXO_ALGOLIA_INDEXING_KEY: ${{ secrets.HEXO_ALGOLIA_INDEXING_KEY }}
      run: |
      hexo generate && hexo algolia && hexo deploy

    小结

    总的来说,就部署 Hexo 而言,速度比 Travis 部署 速度更快一点,同时由于现在还处于测试阶段,功能相对还是比较欠缺一点。不过作为一站式的功能来说,还是不错的。

    参考链接

    • Workflow syntax for GitHub Actions

    ---EOF---

    背景

    Bitwarden 是一个类似 1Password 和 LastPass 的开源密码管理软件,Bitwarden RS 是基于 Rust 语言的一个实现,更轻量一些,可能效率也会更高一点点,并且是完全兼容官方 App 的,比如各种浏览器扩展,手机 App 等。

    TL;DR

    Bitwarden RS 已完成功能

    • Basic single user functionality
    • Organizations support
    • Attachments
    • Vault API support
    • Serving the static files for Vault interface
    • Website icons API
    • Authenticator and U2F support
    • YubiKey OTP

    简而言之就是日常用用是差不多的,离官方实现还有点路要走。

    准备工作

    • 一个域名
    • 一台公网服务器
    • docker-compose
      1
      2
      3
      4
      5
      ➜ docker-compose version
      docker-compose version 1.23.2, build 1110ad01
      docker-py version: 3.6.0
      CPython version: 3.6.6
      OpenSSL version: OpenSSL 1.1.0h 27 Mar 2018
    • traefik
      traefik 配置证书,可以参考 traefik 配置 docker 容器支持 HTTPS,这里就不赘述了。

    Read more »

    缘起

    Go 语言除了语法精炼、并发支持好外,还有一个优点就是可以调用 C 代码。可以直接在 Go 源代码里写 C 代码,也可以引 C 语言的外部库。这样在性能遇到瓶颈的地方可以重写,或者某些功能 Go 和第三方还缺失,但 C 语言有现成的库就可以直接用了。

    官方 Cgo 这块目前有一篇 博客命令行文档。比如 sqlite 的 golang 驱动 go-sqlite3 就是基于 Cgo 的实现。编译本地版本,Go 本身已经支持得非常好,基本不需要额外设置,直接通过 go build 编译即可,但是要想编译其他平台的二进制版本,就需要跨平台的 $(CC), $(CXX) 支持。

    方案

    按照 Cgo 的编译思路,基本思路就是必须有一个跨平台的 C/C++ 编译器才可能实现交叉编译。

    macOS

    • 安装编译器

      1
      2
      brew install FiloSottile/musl-cross/musl-cross
      brew install mingw-w64
    • 编译

      Make 文件中指定 $(CC),$(GCC)musl-cross 提供的编译器,编译安装

    注:此方案未验证,有兴趣的可以自行研究

    Read more »

    需求

    编译 Golang 程序时自动更新版本号,主版本号手动指定,子版本号通过 Git rev 和编译时间自动更新

    实现方法

    Go Linker

    go tool link 中有选项可以设置在编译时设置字符串或者未初始化的变量

    -X importpath.name=value
    Set the value of the string variable in importpath named name to value.
    This is only effective if the variable is declared in the source code either uninitialized
    or initialized to a constant string expression. -X will not work if the initializer makes
    a function call or refers to other variables.
    Note that before Go 1.5 this option took two separate arguments.

    Read more »
    0%