修好了電壓不足的 Raspberry Pi

之前想要拿 Raspberry Pi 接上一個 Wi-Fi adaptor dongle 做點事情,因為插座與網路孔的配置不甚方便,所以才想要走無線網路,但是出現了「只要我一接上這個 dongle, Pi 就整個失靈當機」的情況。

與另外一片 Pi 交叉比對之下,只有這片出問題,參考 [R-Pi Troubleshooting – eLinux.org] 的指引,用三用電錶測試後,確定是電壓不足的問題,而問題的成因,就是板子上面的 F3 保險絲故障,各從 F3 兩側接點與 TP2 間量測電壓,都呈現非常低的數值,形成了「若是單純啟動 Pi 勉強可動,但是再接上一個有點吃電的 USB 裝置,就罷工給你看」的窘態。

拿尺量了一下這顆 SMT 保險絲,確定元件尺寸規格是 1812 ,便上網訂購了修復材料。

SMD 的手動焊接有點難度,但是我還是靠著紙膠帶的輔助,把新的保險絲固定住後,順利焊接上去。再測試一次,電壓回到了正常應有的數值 (4.75~5.25V),接上 dongle 後也沒再發生當機的情況了。

這種平時不接特別吃電的外接裝置時好端端的、但是接上去後就失常的硬體「內傷」,如果沒有文件指引,我也無法快速抓出問題成因,也是學了一課。

Rust 程式做 static linking

這篇主要是參考 [Advanced Linking: Static linking] 這節。

因為平時在工作時如果有處理到 Go 程式,沒有意外的話,編譯過程會產出一個 static linked binary,這對 deploy 流程很方便,所以我想在 Rust 底下也比照辦理。

截自目前,在 Linux 底下,Rust 如果要這樣做,libc 標準函式庫要用 musl,而不是最常見的 glibc,所以要先安裝 musl,在 Arch Linux 底下就是執行:

sudo pacman -S musl

多裝 musl 不會有與 glibc 打架的情況,所以可以大膽放心裝下去。(又或者是我還沒踩到兩者打架的雷?)

然後利用 rustup 工具,新增一組支援 x86_64-unknown-linux-musl 這個 build target 的 Rust toolchain:

rustup target add x86_64-unknown-linux-musl

這樣基本環境其實就搞定了,當然,在建置時,除非是將 x86_64-unknown-linux-musl 設為預設 toolchain,不然都需要特別指定使用這個 target:

cargo build --target=x86_64-unknown-linux-musl

可以用 ldd 與 file 指令觀察、對照一下這組 target 的 binary 與預設的 target 有什麼不同。

實務上,我發現如果把這個 build 出來的 binary 丟進 Docker 裡,用 alpine:3.6 這個 base image 來做個無腦執行容器映像,則會發生 ld.so, ld-linux.so 路徑、檔名不符的問題,換用 debian:stable-slim 就沒這阿雜事了。

考慮到目前頻寬足夠充裕的現實,一個約 4MB 的 alpine:3.6 與一個約 55MB 的 debian:stable-slim,疊上一個約 20MB 的 static linked binary,在 push 效率上,其實對人來說,是感覺不到會覺得「煩」、「痛」這樣的差異的,我自己真的不太喜歡使用 Alpine 這種為了精簡而常常埋雷的 base image 來給自己找麻煩,不過這與本篇沒有直接相關,只是我的一點小抱怨罷了。

在 Ansible 新開機器時,運用 add_host 於執行時期立即加進 in-memory inventory 的方法

最近在評估 GCP,不能免俗地要嘗試使用 Ansible 自動開 GCE 機器、設定組態,遇到一個之前在 AWS EC2 上印象中沒有遇過的問題。

一般來說,我們會先在 localhost 上用 gce module 透過 GCP API 發出建立機器的操作命令,大概會像這樣(註:這邊大量借用了 Ansible 這頁的範例):

- name: Create instance(s)
  hosts: localhost
  gather_facts: no
  connection: local

  vars:
    machine_type: n1-standard-1
    image: 'ubuntu-1604-xenial-v20170811'
    service_account_email: unique-id@developer.gserviceaccount.com
    credentials_file: /path/to/project.json
    project_id: project-id

  tasks:
    - name: Launch instances
      gce:
          instance_names: running_man
          machine_type: "{{ machine_type }}"
          image: "{{ image }}"
          service_account_email: "{{ service_account_email }}"
          credentials_file: "{{ credentials_file }}"
          project_id: "{{ project_id }}"
          tags: consumer_server

然後在機器建起來之後,我直覺會利用 Dynamic Inventory 透過 tag 之類的資源定位方式,把開好的機器找出來:

- name: Provision instance(s)
  hosts: tag_consumer_server
  # 以下省略

但是可能是 GCE dynamic inventory script (gce.py) 預設的 cache 時效問題,我在這步常常需要「踩發」好幾次才能成功得出機器列表。

我找了一下網上的討論,才發現我沒有看到 Ansible 的 GCE 範例文件裡有個眉眉角角的地方,叫做 add_host:

---
- name: Create instance(s)
# 中略
# ...
  tasks:
    - name: Launch instances
      gce:
          instance_names: dev
          machine_type: "{{ machine_type }}"
          image: "{{ image }}"
          service_account_email: "{{ service_account_email }}"
          credentials_file: "{{ credentials_file }}"
          project_id: "{{ project_id }}"
          tags: webserver
      register: gce

    - name: Wait for SSH to come up
      wait_for: host={{ item.public_ip }} port=22 delay=10 timeout=60
      with_items: "{{ gce.instance_data }}"

    - name: Add host to groupname
      add_host: hostname={{ item.public_ip }} groupname=new_instances
      with_items: "{{ gce.instance_data }}"

當我們處理好機器開設時,可以設一個 register,讓接下來的 tasks 去捕捉這個 task 的處理結果。

在 ‘Wait for SSH to come up’ 我們就先使用 wait_for module 先偵測 SSH port (22) 是否起來了,來判斷這台機器是否「大致上可用」(因為 Ansible 主要原理還是靠 SSH 去遠端下一些控制命令)。如果是,我們接下來在 ‘Add host to groupname’ 就用 add_host 把這台跑起來的機器加進 in-memory inventory 當中一個叫做 new_instances 的 group,於是接下來我們就可以直接利用這份 inventory 列表來對這台(些)機器進行各種組態設定:

- name: Manage new instances
  hosts: new_instances
  connection: ssh
  become: True
  tasks:
    - name: Install essential packages
      apt:
        name: "{{ item }}"
        state: present
      with_items:
        - 'redis-tools'
        - 'ruby2.3'

這個 add_host 看起來不管用在哪家雲端服務業者都可以,因此還可以省去多 call 一次 API 重抓 inventory 的工。又學到了一課。

我的蕃茄鐘挑選之路

先備知識

我的困難

  • 無論在家工作或在辦公室工作,我都希望不要打擾到別人。
  • 我希望這個蕃茄鐘也不要干擾到我,帶給我心理緊張感,保持「呼之即來揮之即去」這種程度的存在感就好。

我試過的各種蕃茄鐘(計時器)

  1. Mac 上的 Be Focused Pro,因為那個紅色圖示以及不斷跳動的時間(這個可以切換)太容易讓我往頂端功能列瞧,反而讓我很緊張,於是用了幾次就不想用了。跟作者寫信反映過,跟我打馬虎眼,於是我也放棄了。
  2. 幾個 Android 上的蕃茄鐘 Apps,因為是另一個計時裝置,所以沒有被緊迫盯人的感覺,但是也常因為我蓋著手機套上蓋、或戴著防噪耳機而忽視了提示,這算非戰之罪,不是這些 Apps 的問題。
  3. Apps 配合 ZenWatch,因為 ZenWatch 經常不明所以與手機之間的斷線(我可是有保持手機在它能收到藍牙訊號的安全距離內,也知道 Android Wear 那個「下次嘗試重連時間是當前的兩倍」,有做過功課,拜託各位路人工程師大大們就不要來戰我了,我兩邊都重開機也沒改善啊),加上最好的待機狀況下也只能撐兩天,各種麻煩,於是我也束之高閣了。我也跑過皇家俱樂部送修,但是維修跟我打「能開機、能動啊、沒問題」的馬虎眼,沒時間跟他瞎耗,算了。
  4. 生活五金行買的那種餐廚常見的計時器,除了音量因為適應原本的應用場景所以爆大聲的以外,沒有什麼缺點,單色液晶的數字顯示就算跳啊跳的也不會讓我覺得有壓迫感。但是就是怕吵到人。是說如果我稍微改個電路,可能這款對我來說就完美了。

最新一款(也希望是嘗試的最後一款)

昨天我買了 CASIO W735H,一款帶有震動提示設計的電子錶,除了看時間、設鬧鐘、碼表、倒數計時、第二時間之外,沒有什麼奇奇怪怪的機能,如果沒有震動提示設計,就是隻普通的、跟國軍愛用品牌 JAGA 沒啥兩樣的電子錶。

我覺得它就是取得了我想要的那個平衡點:不吵、低調、省電。而且那震動力道也恰恰好,不會弱到我無感,也不會強到形同發出聲響那般吵鬧。

就先這樣吧。

COSCUP 2017 雜記

關於我講的場次

  • 前面花太多時間交待「我為何選擇 Arch Linux?」到了要講 ArchTW 社群、以及我的「期中報告」時,只剩三分鐘,超慘,很失敗,很對不起來聽我這場次的聽眾。如果您是在場聽眾,希望您有看到我在此表達的歉意。
  • 事前有沒有排練?有!而且是大約 14 分鐘多講完。但是臨場表現太緊張,所以想試著在笑點上緩和一下心情,結果過猶不及,就出包了。

關於我講的公司短講

  • 其實是把之前投閃電秀不成的題目拿來這裡講,也算是一償夙願,所以還是蠻感謝同事 Aaron 的推坑,以及聯絡人 Vivian 願意讓我來講這個題目。
  • 電子節目表連接了「觀眾」與「電視網」→「頻道」→「節目」,我這個電視兒童阿叔至今還是覺得這東西的資訊加值很值得做。
  • 當然,另外那個「窮人的電波時計」也很值得做。有空的話其實還蠻想拿一張 RPi 來做個 PoC。

關於場地

  • 想找講者報到櫃台,連續碰壁兩次,到後來才看到櫃台終於貼上了指示牌。我絕對明白、也很感謝志工們的付出,不過還是希望這點小地方,來年可以提早到位。
  • 今年在台大社科院,不像中研院有交誼廳(?),沒有一處可以歇腳、方便社群朋友坐下來聊天的地方,也讓我不像以往在中研院舉辦時會盡量撐完全場(況且之前我就住在中研院附近),而是兩天各來個大約半天就想走人了(所以因此錯過了 BoF 的求婚名場面…)。空間規劃上,我個人覺得這是稍微有點可惜的地方。

關於議程

  • 今年讓社群自己安排議程,我還蠻喜歡這樣的設計。不過就像有人反映沒有 Swift 議程,我當初想投 Elixir 的議程也是遇到「找不到適合的社群可投」的尷尬狀況,建議或許來年可以保留一「misc 軌」或是開放 unconference。

 最後

  • 再次跟來聽我這場次的聽眾朋友道歉。
  • 感謝各位志工朋友,辛苦了!