macOS 神奇的 terminal compat mode

TL;DR macOS 內建了一個 compat mode 可以使得部分 CLI 工具以 SUSv3 相容模式執行,試試看 COMMAND_MODE=[legacy|unix2003]

某天強者我朋友在社群軟體上面問了為什麼 macOS 的 less 明明在 manpage 中寫有 s (save log) 可以用,但實際按下去卻是往下捲一行……

我第一個想法當然是先看程式碼再說,看看是不是有什麼隱藏設定,但我一開始看了原版的 less 發現沒什麼可疑的地方,於是我轉念一想,那這說不定是 Apple 做的什麼神奇功能? 好在 less 是 GPL 授權,Apple 按照規定應該要放出原始碼來給大家。

於是我就找到了一個版本比較舊的(less-34)原始碼(我不知道為什麼現在 macOS 內建的已經到 100 多版了,但放出來的只有 v34……),而且還真的被我找到了一個可疑的地方[1]

/* 
 * Command table for UNIX 2003 compatibility: added first before builtin
 * so that these commands override the normal LESS commands
 */

static unsigned char UNIX03cmdtable[] =
{
	's',0,				A_F_LINE
};

Apple 在這個地方新增了一個按鍵映射,並且寫了一段註解告訴我們,這個按鍵覆蓋預設的 less 指令。 為何 Apple 在這裡多了一個奇怪的行為呢? 原來是 Apple 從 Mac OS X 10.3 就開始在內建的 CLI tools 裡面新增了這個 Single UNIX Specification v3 (SUSv3)[2] 相容模式,而某些終端機軟體預設就會把這個模式開啓(例如 iTerm2)而導致 less 等工具的行為與我們想像中的不太一樣。

在翻閱了文件[3]以及網路資料[4]之後發現,只要透過環境變數就可以控制這個相容模式的開啓與否,於是我們可以透過設定 COMMAND_MODE 這個環境變數來開關相容模式:

$ # 使用 SUSv3 相容模式
$ COMMAND_MODE=unix2003 less file.txt
$ # 不使用相容模式
$ COMMAND_MODE=legacy less file.txt

於是關掉相容模式之後就可以愉快的在 less 中使用 s 來 save log file 了!


  1. decode.c ↩︎

  2. 詳見維基百科〈Single UNIX Specification〉條目 ↩︎

  3. man 5 compat ↩︎

  4. https://www.oradba.ch/2011/04/mac-os-x-terminal-compatibility-settings/ ↩︎