以往在 Ubuntu 18.04 用 sudo vim
會吃到個人的 vimrc,但 Ubuntu 19 之後突然吃不到,變回裸體的 vim。
It works, I don't know why. It doesn't work, I don't know why.
下手診斷看 vim 裡面的 environ()
、出來看 sudo sudo -V
、sudo printenv HOME
發現 $HOME
有差異,Ubuntu 18 會沿用 sudo 之前的 HOME,19 則是 root。
以為自己有做什麼特殊設定,但找一陣子都沒東西,問 google 才知道原來是 Ubuntu 的 sudo
變更,見 How does sudo handle $HOME differently since 19.10? - Ask Ubuntu。
連結的回答非常詳盡,以往 Ubuntu 的 sudo
一直是特殊 patch 版,會特別護送 HOME
這個變數到 sudo 後的世界。
其實是蠻奇怪的行為,甚至跟 man page 講的不一樣。
要維持 sudo vim
繼續用原本 user 的 HOME,原文也提供幾個解法(見 Preserving
段落),簡短摘要過來就是 $HOME
in Ubuntu 19.10 and latersudo --preserve-env=
或改 /etc/sudoers
加 Defaults env_keep +=
,或者算了,改用 sudoedit
。
考量方便性我選擇改 sudoers 設定,但微調一下限制在特定 user(我自己)才生效,也比較沒有安全疑慮。
註:最好用 sudoedit /etc/sudoers.d/新檔案
動手,以免改壞重要檔案:
Defaults:bootleq env_keep += "HOME"
很少改 sudoers 檔案,讀 man sudoers
尤其 SUDOERS FILE FORMAT
章節與之一戰,每行設定大致會是 Aliases、Defaults 或 User specification 三類之一,這次就是改 Defaults,接冒號表示只影響特定 user,可惜無法同時限制只對 vim
生效。
也總算看懂 sudoers 格式,考慮加上 NOPASSWD
不再問密碼了(安全性會降低一些)。
bootleq ALL = (ALL:ALL) NOPASSWD: ALL
這行就是 User specification,定義為 User_Spec ::= User_List Host_List '=' Cmnd_Spec_List
- 首先 bootleq 是
User_List
- 第一個 ALL 是
Host_List
-
等號後面整串是
Cmnd_Spec_List
,它的定義是一或多組Cmnd_Spec
,
Cmnd_Spec
的定義又是Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd
- (ALL:ALL) 是
Runas_Spec
,冒號前後分別是 sudo 可以變成的 user / group - 最後 NOPASSWD: ALL 則是
Tag_Spec
- (ALL:ALL) 是