What to Do with iPad Air (1st gen)

接收一代的 iPad Air 之後,就一直打主意想該怎麼利用。先是打算拿來看 Netflix,但硬體太舊,iOS 版本只能升到 12.5.5, 安裝時出現「至少需要 iOS 14」,這才明白為何擁有舊蘋果硬體的人這麼不愛升級。如果已經安裝過的,進 App Store 自己帳號底下的「已購項目」還是可以裝回,但若是我這種蘋果帳號全空,或是想裝以前沒用過的,就很麻煩。

Jailbreak 越獄

官方這種做法很可惡的是,既然以前裝過就可以裝回來,表示蘋果那邊都有留檔,只是不讓人用舊硬體新安裝,明明還可以用的硬體卻強迫升級。看網路上問類似問題的人,往往得到的回答竟然是「該買新的了」,這真的是只有果粉才能接受。總之看了各種麻煩方案,最後決定先 jailbreak 越獄再處理。光是把 Chimera 裝進去就各種麻煩,最後是用了經常在重簽的 jailbreaks.app 搞定。成功越獄後,系統裡面多了 Sileo 這個基於 APT 的套件管理系統,可以安裝第三方軟體。為了解決前述 Netflix 問題,搜尋到 App Admin 據說可以讓越獄的 iOS 裝 app 的舊版,但安裝流程老是卡住,怎麼試都不成功。後來發現有 openssh-server 裝上之後用 root password alpine 連進去,直接操作熟悉的 Unix-like 系統就很順利了。

裝舊版 App

到這一步才有點搞懂,越獄完以後最方便的應該是先裝 mterminal 之類的終端機程式,然後像 Linux 一樣操作就可以。預設使用者 mobile 可以 sudo, 密碼一樣是 alpine, 所以其實不需要 openssh-server. 這關過了之後成功裝上 App Admin 結果沒用,試另一套 AppStore++ 才搞定。發現新版已經不支援 iOS 12 的 app 只要能成功安裝一個夠舊的版本,就會出現在「已購項目」,這時再升級 app,似乎就會升到最後一個能用的版本。

OK 這樣終於可以看 Netflix 了。接下來弄好 ssh 也可以連上 Linux 主機做些簡單操作、閱讀器之類的裝一裝也差不多。另外還想充分利用這個 ppi 264 的螢幕,用來當筆電外接螢幕好像不錯。最後試出來比較 Linux 流的方式差不多是這樣:

充當外接螢幕

1
2
3
$ cvt 1024 768
# 1024x768 59.92 Hz (CVT 0.79M3) hsync: 47.82 kHz; pclk: 63.50 MHz
Modeline "1024x768_60.00" 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync

iPad 解析度 2048x1536 設計成長寬都是 1024x768 這個當年流行解析度的兩倍,拿來測試的老筆電不明原因似乎上不了這麼高,退而求其次用 1024x768, 四個點當一個點用。以 cvt 算出模式數據後,用 xrandr 加入 new mode 再隨便挑一個沒在用的 output 硬是加上去,然後假裝成真有這個螢幕設定起來。最後以 x11vnc 切在「假裝」的這一塊輸出,再從 iPad 這邊用任意 VNC client 連上,就可以當成螢幕用了。

1
2
3
4
5
# copy/paste cvt output
$ xrandr --newmode "1024x768_60.00" 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync
$ xrandr --addmode HDMI-1 1024x768_60.00
$ xrandr --output HDMI-1 --mode 1024x768_60.00 --left-of LVDS-1 --output LVDS-1 --primary
$ x11vnc -display :0 -clip 1024x768+0+0

當然這邊寫的是最簡化版,VNC 完全沒加上任何認證機制,最好還是要加一下。用起來感覺還不錯,反正只是看網頁、用編輯器,速度要求不高。這篇就是用 iPad 當作螢幕寫的。可惜的是解析度上不去,之後用別台筆電再試試好了。

Azure Data Studio on Ubuntu 20.04

發現在 Linux 上也有 SSMS 的替代品可跑,而且是 Microsoft 自家出品: Azure Data Studio.

裝起來一試果然不能用… 要解決兩個問題:

TLS 1.0

公司的 SQL Server 老舊且未更新,先前用 Java 連線就會碰到 TLS v1.0 已經不支援的問題,要改 jdk.tls.disabledAlgorithms,用 Ubuntu OpenJDK 的話就是在類似/etc/java-##-openjdk/security/java.security 這樣的地方:

1
2
3
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves

把裡面的 TLSv1, TLSv1.1 拿掉就行了。那這次 Azure Data Studio 用的是系統給的 TLS/SSL,例如 openssl, 這就要去改 openssl.cnf. 但為了這問題去改整個系統設定不太好,折衷一下就採取這邊建議的方式,新增一個 openssl-tlsv1.cnf, 然後用

1
env OPENSSL_CONF=/etc/ssl/openssl-tlsv1.cnf azuredatastudio

執行,就解決了。

Trust Server Certificate

像這種亂裝的 SQL Server 當然不可能真的把憑證搞好,所以還要把 Advanced Properties 裡面 Trust server certificate 勾起來,無條件信任,才能順利連上。

Advanced Properties

75% 鍵盤心得

話說前陣子眼看從 2012 使用至今的 KBtalKing Race 75% 日漸年華老去(其實還很好用, 外觀也新,只是 Micro USB 插孔有些舊,根本就是藉口),加上家人用的 iMac 前方桌面 有限,配上的全尺寸 Cherry G80-3484 實在太佔地方又沒支援 Mac,就開始起心動念肖想 新鍵盤,打算至少進個兩把。這幾天在網路上四處翻找,試圖補足這幾年沒什麼注意的鍵盤 新發展,最終看上的卻跟一開始沒什麼兩樣:補入一把二手的 Race 一代,以及全新 Keychron K2v2. 雖說看似簡單,過程卻是千迴百轉,簡記如下。

首先,為何專挑 75% ? 這是個相當關鍵的決定,大大限制了選擇數目。100% 也就是一般常 見的右邊九宮數字鍵、中間編輯鍵與方向鍵、左方字母鍵盤的配置,好處是標準,要換鍵帽 什麼的都容易,但我習慣打字時 FGHJ 鍵是對準螢幕中間,保持雙手置中,結果整個鍵盤就 變成偏右,滑鼠被迫到更遠處。偶爾不得已要用上滑鼠時(日常操作都以熱鍵為主,但仍然 沒法完全避免),右手簡直要翻越千山萬水。注意到這問題後購入 Filco Majestouch Tenkeyless, 就再也回不去了。所謂 tenkeyless (TKL), 就是少掉右邊數字鍵,這又稱 80% 鍵盤,在電競也常用,好處是數字九宮格相對少用,拿掉之後滑鼠更接近,遊戲時也有 更大活動空間。

Cherry G80-3484, 100%

Filco Majestouch TKL, 80%

比 80% 再縮小,常見的是 60% 及 6x%,主要就是從 80% 再拿掉右邊六個及方向鍵以及上 方 F1 ~ F12, 只留主要字母區,就叫 60%. 有些配置會加回來幾個,例如方向鍵、 PgUp/PgDn 之類的,但 F 功能鍵還是沒有,這就叫 6x%, 例如 65% 之類。這類配置通常都 會多個 Fn 鍵,碰到真的需要的場合時,例如要按 F1, 那就是 Fn 加上方數字鍵 1 之類。 有些電競不需要少掉的鍵,也是很適合,可以空出更多空間,而且容易攜帶南征北討。另外, 著名的的號稱 Unix programmer 用鍵盤 Happy Hacking Keyboard (HHKB) 也屬此類。HHKB 的 layout 很有趣, 目前我的 CapsLock 設定成 Ctrl, 以及 Backspace 與 Backslash 互換,就都是跟 HHKB 一樣。

照片取自 HHKB 官網

夾在中間的 75% 可說是選擇最少的。這種配置,簡單講就是類似一般筆電鍵盤,大多數 80% 的鍵都還在,改排在字母區上方跟右方多了一圈。那為何不去上面的 80% 或是往下去 60% 呢?首先考慮這些按鍵的常用程度。最主要是注音輸入法,時常要選字,就需要方向鍵。 另外即便裝了 Vimium 之類東西, Home/End/PgUp/PgDn 仍然時不時會需要,還有我的 F1 ~ F12 大多數在編輯器 (Emacs) 裡 面都有設定功能。此時 80% 需要移動手掌離開字母區才能按到,這是極力避免的。那 60% 及 6x% 搭配 Fn 手掌不用動都可以按,但 75% 也是不用動手掌,且不需組合鍵就直接按到, 相比起來我更喜歡一些,這就單純是個人喜好問題了。

KBtalKing Race, 75%

一旦決定 75% 配置,選項就沒剩幾個。加上對中國品牌有排斥感,中國製造勉強接受,刪 掉後又更少。基本就剩寥寥幾個 Vortex Tab 75 / Race 3, Keychron K2 或是新的 Q1, 還 有 Akko x Ducky 3084 雖是中國品牌但聯名的勉強給過,這幾個。Race 3 很不錯,問題鍵 帽是 DSA 這不行,個人最愛 Cherry 原廠高度,OEM / Filco 也行,但 DSA 全等高的就沒 辦法。換鍵帽的話,Race 3 幾個特規大小的鍵很難換,Tab 75 的配置比較常見,好換,但 慣用的紅軸款停產了,也沒有補貨計畫。聯名款的 3084 不好找,蝦皮有,但都是假裝台灣 賣家其實是中國人代購,且價錢都是坑人。至於掏寶,我知道有,但堅持不註冊。再上去, 還有些客製化鍵盤,一把光是殼跟板子大概就 150 美金以上,太貴又太花功夫,還不想去 那邊。

對 Keychron 品質期待不高,但家中需要一隻堪用的機械鍵盤,它支援 Mac 且是少數公認 在 Mac 下藍芽依舊穩定的,因此入選。但工作用的一把還是找不著,正在煩惱,剛好看到 拍賣釋出跟手上一樣的 Race 品相很新, 就直接收了。

今天 Keychron K2v2 到貨,質感真的不好,這點一如預期,但其他包括無線穩定度、與 Mac 相容程度都中規中矩,這也一如預期。有一點沒料到的是,原來功能鍵列的高度影響這 麼大。一般這種 Cherry/OEM 鍵帽,從下方數上來到第五列數字,型態分別稱為 B B C D E, 最下面 Ctrl - Win - Alt 跟 Z - X - C 這兩列是相同的,那第六列,也就是功能列, 常見的是做 E, 也就是跟數字列一樣。但在老鍵盤上,會有另一種型態 F, 高度比 E 更高, 以作為區分。在全尺寸或是 TKL 情況下,由於功能列跟數字列中間會留空,所以沒什麼問 題。但在 K2 這種緊湊布局上,如果是 E E 的型態,那要按功能鍵時手指就會「撞上」數 字鍵,相當困擾。

K2 側面,可看出最左一排與第二排高度相仿

Race 側面,最左一排與第二排有明顯高度差

這是為何當年奕之華規劃 Race 時,選擇以 F 鍵高來做功能列。Race 打習慣了,換到 K2 這問題就變得相當明顯。我想這可能也是後來 Vortex 的 75% 都採等高鍵帽的原因之一。 許多較高價位的 75% 鍵盤,會如同 TKL 一樣,在數字與功能列間留白,今天算是了解這重 要性了。

那麼話說回來,鍵盤追尋之路就到此為止了嗎?當然不。慣用紅軸是因為喜歡線性手感,此 類鍵盤軸中,應用 hall effect 為原理 的磁力軸很有趣,內部無接觸,所以極耐用(遠高於人類壽命)且摩擦力低,可達成極好的 手感。另外基於電磁原理,能感測按下深度,所以還可調整觸發深度配合打字習慣。這就是 所謂的「類比」鍵盤,在電競也有一堆應用,比如全按跟半按可以觸發不同動作,或是需要 極快反應時可以把觸發深度調到很淺等等。目前用這種軸的有 SteelSeries 賽睿的 Apex Pro 還買得到,Wooting two 賣完了要等 HE 版本, 還有 Input Club 的 Keystone 在預 購。以前有間中國的創業公司叫 Ace Pad Tech (APT) 也有做,但似乎已消失了。這非常的 生火,但最接近我需求的只有 TKL 版本可買,且是 2019 年產品,PChome 賣 5990 大洋, 現在下手可能沒多久就出新款了,所以還能先忍著。

以下 Keychron K2 開箱圖。

包裝

開蓋

上方

lsp-mode 與 Python virtualenv 的整合

Emacs 的 lsp-mode 是利用 Language Server Protocol (LSP) 來支援程式語言的編輯,LSP 一開始是為了 VS Code 開發的,可以把對語言的編輯支援與 IDE/editor 脫勾,常常是孤兒的 Emacs 就比較可以跟上時代的發展。但,慣用的 palantir/python-language-server (pyls) 在搭配 Python 幾乎一定會使用的 virtualenv 時,還是會有認不出虛擬環境裡模組的問題,如果再加上 pyenv 之類的,就還需要考慮不同 Python 版本,事情又更麻煩。以下是幾種解決方案:

每個虛擬環境都裝一套

這需要搭配 add-dir-local-variable 使用,在專案目錄底下新增一個 dir local variable pyvenv-activate 指向虛擬環境的絕對路徑,然後只要在這個環境下安裝 pyls 就可以了。這是個非常穩當的方法,所有基於虛擬環境的應用例如 pipenv 之類的也都適用。

缺點是,整套 pyls 也佔不少空間,每個專案底下都做一次很麻煩,要升級還得各自升級。

自己寫個 pyls wrapper

這算是前面方法的變體。先在自己環境裡裝一套 pyls,例如我習慣裝在 homedir 底下,那就是

1
python3 -m pip install --user 'python-language-server[all]'

這樣只要在設定環境時,用 virtualenv --system-site-packages 或者像我是用 pipenv 那就是 pipenv install --site-packages 就可以一併帶入到虛擬環境裡面。但這方法有個問題:帶入的模組是不會在虛擬環境裡新增執行檔的,也就是說 Emacs 執行 pyls 這命令時,會用到虛擬環境「外面」的執行檔,這就會出錯了。解決方法是要繞一圈,在虛擬環境裡以 python -m pyls 的方式執行。

但問題又來了:如果直接把 lsp-pyls-server-command 這變數改掉,lsp-pyls.el 的寫法是把整個值當成命令名稱來用,但系統裡面當然不該有個名稱叫做 python -m pyls 的執行檔。所以可以自己寫個 pyls.sh 裡面就寫 python -m pyls 然後把 lsp-pyls-server-command 改成 pyls.sh 就行了。這方法一樣要仰賴在每個專案正確設定 pyvenv-activate. 而我是慣用 pipenv,所以只要寫成這樣

1
2
3
4
5
6
7
8
9
#!/bin/bash

set -e

if pipenv --venv &> /dev/null; then
exec pipenv run python -m pylsp "$@"
else
exec python3 -m pylsp "$@"
fi

如此不特別設定 pyvenv-activate 也一樣會動。

pipenv 與 virtualenv 的關係

pipenv 用來管理 python 的 app 是不錯(注意不是模組,模組還是該用 distutils),不過基於 python 社群的一貫風格還是要搞點問題出來才行。先前碰到 issue 2364,搞了好久才全部弄清楚。背景知識要先知道 pyvenv, pyenv, virtualenv, pip, pipenv 這一堆東西是幹嘛的(stackoverflow 上的說明),然後要知道 virtualenv 會綁初始 pip, setuptools, wheel 的版本,就比較容易弄清楚了。

狀況是:在 Ubuntu 19.04 上面用 pipenv 設定開發的專案,Python 版本綁在系統預設的 3.6. 後來移到 20.04,由於系統版本升到 3.8,所以先裝 pyenv 然後再 pipenv sync,理論上這樣 pipenv 會先用 pyenv 裝好 3.6、產生執行 3.6 版的 virtualenv、然後裝好所有需要的模組。但最後在安裝模組階段噴錯。研究後發現裡面用到的模組需要較新的 setuptools 版本才能正確安裝,而版本是由 virtualenv 產生環境時決定的,但 pipenv 的開發者認為 virtualenv 屬於使用者環境的一部分,他們不應該去修改,使用者一番爭論後答應看一看,就又沒下文了。

當安裝 pipenv 時 (python3 -m pip install pipenv),由於 virtualenv 是一個 dependency,所以會先檢查有沒有符合的版本,沒有的話會自動帶入。這就是在 20.04 那邊出錯的原因,因為 19.04 的系統沒裝 python3-virtualenv 但 20.04 的系統有,所以最早在 19.04 那台安裝 pipenv 時帶入了新版的 virtualenv,比 20.04 系統裡面預設安裝的新,所以一直沒問題。移到 20.04 時,pip 檢查到 virtualenv 已經存在,就用現有的,所以產生的環境裡面 setuptools 比較舊,安裝模組時就失敗了。

這邊要注意的是: pyenv 在這邊的作用,並不及於 pipenv 以及 virtualenv. 也就是說,在預設為 3.8 的系統上跑 pipenv install 時,是用 3.8 搭配的 pipenv,自然也執行到了 3.8 搭配的 virtualenv. 直到以 pipenv shell 或者 pipenv run 的時候,被執行的程式才會真正用到虛擬環境裡的 python 版本,也就是 3.6.

知道以上資訊後,解法也很簡單。不管系統裡面有沒有 virtualenv,反正都用 python3 -m pip install --user virtualenv 在 home 底下裝一份新的就好。這也表示在重建 build 環境時,除了 Pipfile 裡面已經綁死的東西,也要注意用到的 virtualenv 版本是否相容。

Ubuntu 20.04 更新

平日自用的 Ubuntu 機器有三台,一台準系統接電視、另外兩台筆電分別是家用、工作用。雙十連假手癢想升級到 20.04,電視那台是標準安裝,很順利就升級完畢。筆電配置就比較奇怪,ubuntu-desktop 沒裝齊(差很多),要用 .xsession 進桌面,環境混合了 xfce, 一點點 gnome 以及 awesome 這個 tiling window manager. 考慮到這是非典型的配置,懷疑直接跑圖形界面的升級會有問題,就用命令列的 do-release-upgrade 先拿裡面沒什麼東西的家用那台試試。結果才換完 repo 就跳出 X,用 Ctrl-Alt-F1 無法換 console,用 Alt-SysRq- 那幾個鍵竟然也沒反應,最後 cold reset, 慘。重開當然進不了 X,於是就在 runlevel 3 之下把套件裝一裝,大部分都可以自動,有些 ecryptfs-utils (這個該換了)之類的要手動裝,裝完重開就大致正常了。

有了這經驗,第二台工作用筆電就直接進 runlevel 3 升級,跑完微調一下套件,很順利就完成。這樣膽子就長出來了,下次來遠端升級那一堆古董伺服器,有幾台還在 12.04 呢…

ThreadPoolExecutor 就是個坑

主要問題可參考這個 issue,裡面有以下片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import concurrent.futures as cf

bucket = range(30_000_000)

def _dns_query(target):
from time import sleep
sleep(0.1)

def run():
with cf.ThreadPoolExecutor(3) as executor:
future_to_element = dict()

for element in bucket:
future = executor.submit(_dns_query, element)
future_to_element[future] = element

for future in cf.as_completed(future_to_element):
elt = future_to_element[future]
print(elt)

run()

可發現這是照著文件例子寫的,只是數量增加一下,記憶體就爆了。問題乍看出在 future_to_element 長太大,但就算不把 submit() 的結果放在容器中,只要在 with clause 中就一樣會佔用記憶體。也就是說在工作數量大的情況下,ThreadPoolExecutor 並不實用。Issue 中建議是另外加個 loop 把總工作切成一批批的處理,每次處理一批就要等到全部跑完,然後換下一批。若為了節省時間把批次處理量加大,記憶體又消耗很多,不是很理想。

這其實是不必要的:future 可用以得知是否出錯、以及工作完成的結果,但要知道結果有其他機制可以利用,最典型的例如送到 queue,問題就只剩錯誤處理。先前在「出錯就盡快停止」的條件下,寫過類似下面的程式片段:

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
50
51
52
53
54
55
56
import threading
import typing


class ThreadExecutor:

def __init__(self, max_workers: int):
self.max_workers = max_workers
self.semaphore = threading.Semaphore(max_workers)
self.last_error = None

def _wrapper(self, fn: typing.Callable, args, kwargs):
try:
fn(*args, **kwargs)
except Exception as e:
self.last_error = e
raise e
finally:
self.semaphore.release()

def submit(self, fn: typing.Callable, *args, **kwargs) -> bool:
if self.last_error:
return False
self.semaphore.acquire()
threading.Thread(
target=self._wrapper, args=(fn, args, kwargs)
).start()
return True

def join(self):
for _ in range(self.max_workers):
self.semaphore.acquire()
if self.last_error:
raise self.last_error


def task(x):
import random
import time
if random.random() < 0.001:
raise RuntimeError(x)
print(x)
time.sleep(1)
return


def main():
excr = ThreadExecutor(100)
for x in range(500):
if not excr.submit(task, x):
break
excr.join()


if __name__ == '__main__':
main()

如此不用批次也沒有消耗記憶體問題。

但以上提的還算是表面。最終是會需要 Scala concurrent.Map 那樣的機制,而且必須是 lazy,或是 Go 用 channel 也能處理得很漂亮。只能說 Python 在 concurrency 領域還差得很遠,這也限制了它作為 backend, infrastructure 等等應用的普及度。

用虛擬 webcam 作為線上開會視訊 aka v4l2loopback on Ubuntu 18.04

會找這個來用是因為想把線上開會時的視訊整個替換掉。v4l2loopback 會在系統上做出 一個假的 webcam device,可以當成真的 webcam 來用,播放餵給它的東西。套件名稱是 v4l2loopback-utils 會依賴 v4l2loopback-dkms 一起裝進來,但版本太舊,跑起來問 題一堆,所以直接去 github 那邊抓了最 新 release v0.12.4 來用。

安裝就直接照 README.mdmake 然後 insmod v4l2loopback.ko 下去就行了。講 究一點可以照裡面說的跑 depmod -a 之類的讓它自動帶 dependencies. 先設定:

1
2
v4l2loopback-ctl set-caps 'video/x-raw,format=UYVY,width=640,height=640' \
/dev/video2

/dev/video2 是系統上 insmod 以後產生出的 device name, 然後 640x640 可以改成你 想要的解析度。

1
2
3
gst-launch-1.0 -v filesrc location="fakeportrait.jpg" \
! decodebin ! imagefreeze ! videoconvert ! videoscale \
! identity drop-allocation=1 ! v4l2sink device=/dev/video2

這例子是把一張靜態圖片做背景。用 zoom 可以看到沒問題,用 cheese 碰到問題就是不讓 我換預設 device,已經找過不用 cheese -d /dev/video2 改用 cheese --device="Dummy video device (0x0000)" 還是有問題,乾脆砍了。

zoom screenshot

awesome window manager: choose default layout

awesome window manager 也許多年了,一向都蠻順手,這 陣子單獨用筆電作業的時間比較多,也就是沒外接螢幕跟鍵盤,總覺得卡卡的。原因是筆電 螢幕解析度高,但相對應的 DPI 也調到正確值 210,一行大約 140 個字母。由於習慣一行 最多 80 個字母,所以如果螢幕寬度無法容納 160 個字,視窗就不適合用左右並列的方式。 在 awesome 的 rc.lua 裡原本是這樣寫:

1
2
3
4
5
if s.geometry.width > 1600 then
layout = awful.layout.layouts[1] -- 左右並列
else
layout = awful.layout.layouts[2] -- 上下並列
end

這樣會按照螢幕橫向解析度決定要不要並列,但現在不適用了,因為雖然筆電螢幕寬度是 2560 點,但並不希望是左右並列。解決方法是實際去計算能放幾個字。慣用的 adobe source code pro 10pt, 72pt 是一英吋,然後這字型是設計成寬度大約是字體大小的 60%, 最後加入 0.25pt 當成字距用以微調。

1
2
3
4
5
if (s.geometry.width / s.dpi) / ((10 * 0.6 + 0.25) / 72 )) >= 160 then
layout = awful.layout.layouts[1]
else
layout = awful.layout.layouts[2]
end

實際用幾組不同螢幕規格試算,結果都還符合預期。

讓 pmount 支援 exfat

一直覺得 pmount 沒支援 exfat 很麻煩,剛弄了個一行的 patch.

抓下來以後可以這樣做一個自己的 package 裝起來。

1
2
3
4
5
6
apt-get source pmount
cd pmount-0.9.23
quilt import ~/Downloads/exfat.patch
debuild -i -us -uc -b
cd ..
sudo dpkg -i pmount_0.9.23-3build1_amd64.deb

2020/09/23 更新: 不知有什麼改變了,總之現在要多個 nonempty 才會動。patch 已更新。