wc -l 在 Linux 與 macOS 上輸出的格式不同

Linux 上跑起來沒問題的 shell script 到 macOS 上發現有狀況,追了問題後發現是 wc -l 輸出的格式不同導致的。

Linux 上面是直接輸出數字:

$ echo abc | wc -l
1

macOS 上面則會在開頭看到 trailing space:

$ echo abc | wc -l
       1

可以搜到蠻多地方都有在討論這個問題,像是這篇:「WC on OSX - Return includes spaces」。

不過看起來 POSIX 標準沒有直接規定輸出的格式,只好照著語意再處理了,像是 | awk '{print $1}' 之類的方法。

Podman 下的 inotify 問題

手上有個前端專案的開發環境是在 Linux container 上跑起來,有支援修改時 auto reload,我在 Linux Desktop 上面跑起來沒有問題,但在 MacBook (M 系列) 上開發就發現不會 auto reload,這樣改起來頗麻煩...

馬上有在猜是不是 inotify 的問題,先翻了一下資料,發現 inotify 在 Podman 上沒有被完整支援:「file changes not registered by inotifywait inside podman on Mac #19430」、「cannot receive inotify on shared directories when using AppleHV #22343」。

接下來把 Podman 換成 Docker,就發現解決了,看起來我遇到的應該就是 Podman 對 inotify 的支援度問題。

這樣開發上沒辦法用 Podman,只能先繼續把票追起來。

Homebrew 上的降版與鎖版

標題是在找到「vim-indent-guides doesn't work on Neovim 0.10.x (on macOS)」這個問題時用到的方法,Homebrew 在新版不支援直接透過 command line 降版 (網路上可以找到不少 Homebrew 舊版的處理方法,但已經不能用了),就變得很麻煩...

這邊以 Neovim 為例子,可以找到對應的 formulae 在「neovim — Homebrew Formulae」這邊,裡面有 Formula code 的連結指到特定的 commit id 上,我這邊則是指到 master branch 上:「neovim.rb」。

接下來透過 History 頁面可以看到這個檔案被修改的記錄:「History for Formula/n/neovim.rb - Homebrew/homebrew-core」,可以看出來 commit 後會有機器人 BrewTestBot 編 binary package 然後更新文件內的 hash 資訊 (官方稱作 Bottles)。

接下來就是要挑一個版本點進去,我這邊舉例抓的是 0.9.5 的「neovim: update 0.9.5 bottle.」這個,然後從三個點的 icon 上點開,裡面的 View file 點下去後就會出現單一檔案的畫面,裡面有 Raw 可以點,就可以抓到像是 https://raw.githubusercontent.com/Homebrew/homebrew-core/63aa44faba5b5274a1a7579510cd5a570a2cca5f/Formula/n/neovim.rb 這樣的連結了。

這邊的檔案名稱不能換,但為了測試方便,我的方法是把不同 Neovim 版本的檔案都抓下來改檔名成 neovim-0.10.1.rbneovim-0.10.0.rb 以及 neovim-0.9.5.rb,後續再用 soft link 的方式 ln -fs neovim-0.10.1.rb neovim.rb 讓 Homebrew 讀到 neovim.rb 的檔案名稱,像是這樣:

wget -O neovim-0.9.5.rb https://github.com/Homebrew/homebrew-core/blob/63aa44faba5b5274a1a7579510cd5a570a2cca5f/Formula/n/neovim.rb
wget -O neovim-0.10.0.rb https://raw.githubusercontent.com/Homebrew/homebrew-core/5990ac73d16c4544d85fc67dad4405dda1e74fd6/Formula/n/neovim.rb
wget -O neovim-0.10.1.rb https://github.com/Homebrew/homebrew-core/blob/a75fe3a7ab97f97dc9999e7390184869be73227c/Formula/n/neovim.rb
ln -sf neovim-0.9.5.rb neovim.rb

Wget 或是 cURL 抓下來後就可以要 Homebrew 安裝了,在安裝前要記得先 uninstall 現有的版本:

brew uninstall neovim
brew install -s neovim.rb

以 Neovim 來說,跑完後用 nvim --version 就可以看有沒有裝到對的版本,其他軟體應該也會有對應的版本資訊可以看。

鎖定版本以及解除鎖定比較簡單,用 pinunpin 處理就可以了:

brew pin neovim
brew unpin neovim

Ladybird 瀏覽器計畫在 2026 夏天推出 Alpha 版

在「Welcome to Ladybird, a truly independent web browser (ladybird.org)」這邊看到的,指到官網 Ladybird 上。

最主要的資訊應該是這個日期,目前計畫是 2026 夏天在 LinuxmacOS 上推出 alpha 版:

We are targeting Summer 2026 for a first Alpha version on Linux and macOS. This will be aimed at developers and early adopters.

也就是大約再兩年,看起來得花不少時間開發... 畢竟是要完全獨立開發不使用現有瀏覽器的 code。

Linux 上的 GNU sed 與 macOS 內的 sed 的 in-place 差異

結論:用 Perl

寫 shell script 的時候遇到的問題,在 Linux 上面使用 sed 換檔案裡面的字串,但不想要產生 backup file 的方式是:

sed -i -e 's/foo/bar/' example.txt

但在 macOS 內建的 sed 則是:

sed -i '' -e 's/foo/bar/' example.txt

也就是說前者 GNU sed 是處理 $1 (argv[1],anyway) 後面貼著的參數,而後者 macOS 的則是吃 $2 (argv[2]) 的參數。

Stack Overflow 上的「sed in-place flag that works both on Mac (BSD) and Linux」這邊有討論,看起來 sed 上沒有通解。

翻了 The Open Group 上的說明,sed 應該是定義在 POSIX 裡面,而從文件裡面沒有提到 backup file 可以知道這是各家自己實作的功能:「sed」。

所以一種解法是用 detection 的方式針對不同的 sed 給不同的指令;而另外一種解法是找其他工具。後者考慮到普及性,用 Perl 應該會是比較好的方式,目前不是 minimal 類的系統應該都還有 Perl 可以用:

perl -pi -e 's/foo/bar/' example.txt

但這樣跑在 CI 裡面的時候就得小心一點了,如果選到 minimal image 的話就會中獎... (煩躁?)

Mac (M1/M2) 上的 Asahi Linux 支援 OpenGL ES 3.1

在「The first conformant M1 GPU driver」這邊看到 Mac (M1 系列與 M2 系列) 上的 Asahi Linux 支援 OpenGL ES 3.1 了。

文章裡面有提到,目前 macOS 上沒有業界標準介面可以用:

Unlike ours, the manufacturer’s M1 drivers are unfortunately not conformant for any standard graphics API, whether Vulkan or OpenGL or OpenGL ES. That means that there is no guarantee that applications using the standards will work on your M1/M2 (if you’re not running Linux).

也許有機會會看到有人 backport 回 macOS 上?

macOS 要提供 DirectX 介面了

Hacker News 上看到 macOS 要提供 DirectX 介面了:「DirectX 12 Support on macOS (twitter.com/andytizer)」,原推是:

算是降低遊戲引擎維護的成本?讓開發商更有意願實作?不確定會有什麼效果...

Mac 上用 Homebrew 安裝 Java 的方式

寫個自己看的,順便整理一些簡單的歷史。

一開始可以先看一下 java 跑起來如何:

$ java --version
The operation couldn't be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.

順便一提,這邊的 java 可以用 which java 看到是出自 /usr/bin/java

然後透過 Homebrew,可以選擇不同的 JDK 套件安裝,在網路上常見的答案是 temurin (adoptopenjdk 的後繼者):

brew install temurin

這個好處是裝完可以直接用:

$ java --version
openjdk 19.0.1 2022-10-18
OpenJDK Runtime Environment Temurin-19.0.1+10 (build 19.0.1+10)
OpenJDK 64-Bit Server VM Temurin-19.0.1+10 (build 19.0.1+10, mixed mode)

另外一種是 OpenJDK,裝完後還得補個 symbolic link:

brew install openjdk
sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

可以看到這個版本的輸出不太一樣:

$ java --version
openjdk 19.0.1 2022-10-18
OpenJDK Runtime Environment Homebrew (build 19.0.1)
OpenJDK 64-Bit Server VM Homebrew (build 19.0.1, mixed mode, sharing)

然後不管哪種裝法都記得設定 JAVA_HOME

export JAVA_HOME="$(/usr/libexec/java_home)"

基本上就能動了。

在 Ubuntu (Xfce) 上改用 Albert Launcher

在噗浪上的這篇看到的工具,讓我想起來之前有想要在 Ubuntu + Xfce 上找類似的工具:

macOS 上我最常用的就是計算機與匯率換算,另外就是開應用程式。

但是因為沒辦法直接用 super key 啟動 (也稱作 meta key,或是大家更熟悉的微軟鍵),所以得迂迴設定,先透過 xcape 把左邊的 super key 對應到 Ctrl-Esc 上:

xcape -e 'Super_L=Control_L|Escape'

然後把本來的 Ctrl-Esc 拔掉:

然後這時候用 super key 時就會改抓到 Ctrl-Esc 了:

接下來就可以勾選 extensions 了,這邊勾了幾個:

然後 Python 這邊把 Currency convert 的部份勾起來:

用法是 1 usd to twd 這樣的句子:

這兩天用起來還不錯,之後遇到問題再來調整...

Apple 在 iOS 16、iPadOS 16 與 macOS Ventura 上推出 Lockdown Mode

AppleiOS 16、iPadOS 16 與 macOS Ventura 上推出了 Lockdown Mode:「Apple expands industry-leading commitment to protect users from highly targeted mercenary spyware」。

Lockdown Mode 主要是透過降低被攻擊的面積以提昇安全性,依照 Apple 的預想,主要是針對被政府單位盯上的族群:

Apple is previewing a groundbreaking security capability that offers specialized additional protection to users who may be at risk of highly targeted cyberattacks from private companies developing state-sponsored mercenary spyware.

在 Lockdown Mode 下目前列出來的限制:

  • Messages: Most message attachment types other than images are blocked. Some features, like link previews, are disabled.
  • Web browsing: Certain complex web technologies, like just-in-time (JIT) JavaScript compilation, are disabled unless the user excludes a trusted site from Lockdown Mode.
  • Apple services: Incoming invitations and service requests, including FaceTime calls, are blocked if the user has not previously sent the initiator a call or request.
  • Wired connections with a computer or accessory are blocked when iPhone is locked.
  • Configuration profiles cannot be installed, and the device cannot enroll into mobile device management (MDM), while Lockdown Mode is turned on.

列出來的這些的確都是之前 0-day 常被拿來打的東西,把攻擊面積縮小的確會有不少幫助。

這應該是業界第一個大咖跳進來做這個 (也就兩個大咖?),第一次搞未必會完美,但算是個開始,後面應該會有更多的面積被考慮進去...