伺服器維運

Vim 編輯器是什麼:三種模式與修改配置檔案實操

Vim 編輯器是 vi 的增強版,在沒有圖形介面的 Linux 伺服器上用來檢視和修改配置檔案。它靠模式工作:開啟檔案時處於普通模式,按 i 進入插入模式輸入文字,按 Esc 回到普通模式,再輸入 :wq 儲存退出。記住這個迴圈,大多數配置就能改完。

作者 頂聯產品團隊發布於 7 分鐘閱讀

Vim 編輯器是 Linux 和類 Unix 系統裡的終端文字編輯器,名字是 Vi IMproved 的縮寫,意思是“改進版的 vi”。它不用滑鼠和選單,全部靠鍵盤操作,並且用“模式”來區分你按下的鍵是在輸入文字還是在執行命令。伺服器通常沒有圖形介面,改 /etc 下的配置檔案、看一段日誌、寫個小指令碼,用的都是它。只想先把檔案改完,記住這個迴圈就夠了:vim 檔名 開啟,按 i 開始輸入,改完按 Esc,再輸入 :wq 回車儲存退出;改亂了不想儲存,按 Esc 後輸入 :q! 回車。

vim 是什麼意思:vi、Vim 與精簡版的關係

vi 是 Bill Joy 在 1976 年前後為 BSD Unix 編寫的全屏編輯器,後來被寫進 POSIX 標準,所以幾乎每個類 Unix 系統都有一個叫 vi 的命令。Vim 由 Bram Moolenaar 在 1991 年釋出,起初是 Amiga 上的一個 vi 仿製品,功能越加越多,名字也從 Vi IMitation 改成了 Vi IMproved。Bram 於 2023 年去世,Vim 此後由社群維護者繼續釋出新版本。

兩者的主要區別:

對比項 傳統 vi Vim
撤銷 只能撤銷最近一次修改,再按 u 會把撤銷本身撤回 多級撤銷,u 逐步後退,Ctrl+r 重做
語法高亮 沒有 按檔案型別著色,shell、YAML、nginx 等都能識別(需要完整版)
可視模式 沒有 v、V、Ctrl+v 按字元、按行、按列選中
插入模式下的方向鍵 不能用 可以直接移動游標
分屏與對比 沒有 :sp、:vsp 分屏,vimdiff 對比兩個檔案
配置與擴充套件 ~/.exrc,選項很少 ~/.vimrc,支援 Vim script 和外掛

現在大多數發行版裡輸入 vi,啟動的其實是某種精簡版 Vim,不同系統差別不小:

系統 輸入 vi 時實際執行的程式 完整版 Vim 怎麼裝
RHEL、Rocky、AlmaLinux、CentOS vim-minimal 軟體包提供的精簡 Vim dnf install vim-enhanced(CentOS 7 用 yum),裝好後命令是 vim
Debian、部分精簡版 Ubuntu 映象 vim-tiny,透過 alternatives 機制指向 vi apt install vim
Alpine、各類救援盤和嵌入式系統 BusyBox 內建的 vi,只有基本功能 Alpine 用 apk add vim

不確定手上這台機器用的是哪個,執行下面幾條:

readlink -f "$(command -v vi)"         # vi 最終指向哪個程式
vi --version | head -n 2               # Vim 會顯示 VIM - Vi IMproved 和版本號
vim --version | grep -o '[+-]syntax'   # +syntax 表示支援語法高亮

Debian 的 vim-tiny 有個常見困擾:在插入模式下按方向鍵,游標不動,反而多出一行字母 A、B、C 或 D。原因是 vim-tiny 預設以 vi 相容模式執行,方向鍵發出的轉義序列被拆成了幾個普通按鍵:Esc 退出插入模式,O 在上方新開一行,最後的字母被當成文字輸了進去。根本辦法是裝完整版 Vim;暫時裝不了,就在 ~/.vimrc 裡寫上 set nocompatible 和 set backspace=indent,eol,start,退格鍵刪不掉已有內容的問題也一起解決。

三種模式怎麼切換:普通、插入、命令列

開啟檔案時 Vim 處於普通模式(Normal mode,很多中文資料叫“命令模式”)。這時鍵盤上的每個鍵都是命令:x 刪除一個字元,dd 刪除一行,u 撤銷,字母並不會寫進檔案。要輸入文字得先進入插入模式;要儲存、退出、替換或跳到某一行,就按冒號進入命令列模式(也叫末行模式、底行模式),在螢幕最下面一行輸入命令。

模式 怎麼進入 螢幕上的標誌 按鍵的作用 怎麼回到普通模式
普通模式(命令模式) 開啟檔案即是;其他模式按 Esc 左下角沒有模式提示 移動游標、刪除、複製、貼上、撤銷 本身就是
插入模式 i 游標前、a 游標後、o 下方新開一行、A 行尾 左下角顯示 -- INSERT --,中文環境為 -- 插入 -- 輸入什麼就寫進什麼 Esc
命令列模式(末行模式) 普通模式下按 :;按 / 或 ? 是查詢 游標跳到最後一行,行首出現 : 或 / 輸入 w、q、s/舊/新/ 等命令後回車執行 回車執行後自動返回,Esc 放棄
可視模式 v 按字元、V 按行、Ctrl+v 按列 -- VISUAL -- 移動游標擴大選區,再按 d、y、> 處理 Esc

可視模式不在“三種模式”的常見說法裡,但改配置時經常用它選中一段再刪除或縮排,值得一起記住。

幾條讓模式切換不出錯的習慣:

  • 不知道自己在哪個模式,就連按兩次 Esc。多按不會造成任何修改,最多響一聲。
  • 在普通模式下操作前,先切到英文輸入法。中文輸入法打出的是全形冒號“:”,Vim 不認,看上去就像按了沒反應。
  • 命令區分大小寫。o 在下方開新行,O 在上方開新行;Caps Lock 開著時 j 變成 J(把兩行合併),u 變成 U,結果完全不同。
  • 按了 Ctrl+S 後螢幕不動了,是終端的流量控制把輸出暫停了,不是 Vim 卡死,按 Ctrl+Q 恢復。

實操一:用 Vim 修改 sshd_config

下面給 SSH 服務縮短登入等待時間、開啟空閒保活,演示從開啟到生效的完整過程。這兩項改錯了也不會把自己鎖在外面,適合練手。以 root 身份操作,普通使用者在命令前加 sudo。

第 1 步:備份並開啟。 配置檔案改壞了,有備份就能一條命令還原:

cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +%F).bak
vim +/LoginGraceTime /etc/ssh/sshd_config

+/關鍵詞 讓 Vim 開啟檔案後直接停在第一個匹配處。主流發行版的預設檔案裡,這一行是被註釋掉的 #LoginGraceTime 2m。

第 2 步:按下表依次按鍵。

按鍵 作用 這一行變成
0 游標移到行首的 # #LoginGraceTime 2m
x 刪除游標處的字元,即去掉註釋符 LoginGraceTime 2m
w 游標跳到下一個詞 2m 的開頭 不變
cw,輸入 30s,按 Esc 把從游標到詞尾的 2m 改寫成 30s LoginGraceTime 30s
/^#\?ClientAliveInterval 回車 查詢以 ClientAliveInterval 或 #ClientAliveInterval 開頭的行 游標停在 #ClientAliveInterval 0 行首的 # 上
x、w,再 cw,輸入 60,按 Esc 去掉註釋,把 0 改成 60 ClientAliveInterval 60
:wq 回車 儲存並退出 —

cw 只改從游標到詞尾的部分,所以先用 w 跳到詞首再改;如果用 $ 跳到行尾的 m 上再按 cw,只有 m 被換掉,這一行會變成 LoginGraceTime 230s。查詢時在關鍵詞前加 ^#\?,表示“行首,可能有一個 #”,這樣不會停在註釋說明文字裡提到這個詞的地方。要新增一行配置,就在相關的那一行上按 o,在它下方新開一行輸入;不要直接加到檔案末尾,因為檔案後部如果有生效的 Match 段,寫在它後面的配置只對匹配的使用者或位址生效。

第 3 步:檢查語法、確認生效。

sshd -t                     # 沒有任何輸出就是語法正確
sshd -T | grep -Ei '^(logingracetime|clientaliveinterval) '
systemctl reload sshd       # Debian、Ubuntu 上服務名是 ssh
diff /etc/ssh/sshd_config.$(date +%F).bak /etc/ssh/sshd_config

sshd -T 列印的是 sshd 最終採用的值,時間統一換算成秒,這裡應當看到 logingracetime 30 和 clientaliveinterval 60。如果值沒變,多半是 /etc/ssh/sshd_config.d/ 目錄裡有檔案先設定了同一個選項,sshd 對同一選項只取第一次讀到的值,用 grep -r LoginGraceTime /etc/ssh/sshd_config.d/ 找出來一併修改。reload 不會斷開現有連線,但改 SSH 配置時保持當前視窗不關,另開一個視窗測試能否登入,是值得養成的習慣。

實操二:改 nginx 配置,用上行號、塊複製和批次替換

第二個例子換一個站點配置檔案,把舊域名全部換成新域名,複製一個 location 塊,再臨時註釋幾行。

cp -a /etc/nginx/conf.d/shop.conf /root/shop.conf.bak
vim /etc/nginx/conf.d/shop.conf
  1. 顯示行號。 輸入 :set nu,後面用行號指定範圍時以它為準,:set nonu 關閉。
  2. 批次換域名。 輸入 :%s/old\.example\.com/shop.example.com/gc。% 表示全文,g 表示一行裡出現多次也全部替換,c 表示每處先問你:按 y 替換、n 跳過、a 剩下的全部替換。點號在查詢裡匹配任意字元,所以舊域名裡的 . 要寫成 \.。
  3. 複製一個 location 塊。 游標移到 location /api/ { 這一行,按 $ 跳到行尾的 {,再按 V%:V 開始按行選擇,% 跳到與之配對的 },整個塊就被選中了。按 y 複製,把游標移到要插入的位置,按 p 貼上到下方,再把新塊裡的路徑改掉。
  4. 臨時註釋第 40 到 45 行。 輸入 :40,45s/^/# /,在每行行首加上 # ;恢復時執行 :40,45s/^# //。
  5. 調整縮排。 用 V 選中幾行後按 > 右移一級、按 < 左移一級。
  6. 儲存退出。 :wq。

然後檢查並載入:

nginx -t && systemctl reload nginx

nginx -t 出錯時會給出檔名和行號,例如 unexpected "}" in /etc/nginx/conf.d/shop.conf:42。用 vim +42 /etc/nginx/conf.d/shop.conf 開啟,游標直接停在第 42 行。改到一半發現思路不對,:e! 丟棄所有未儲存的修改、重新載入檔案;已經儲存的,就用開頭備份的檔案還原。

存不了、退不出:常見提示的意思

提示 意思 怎麼辦
E37: No write since last change (add ! to override) 檔案改過還沒儲存,:q 被拒絕 要儲存就 :wq,不要就 :q!
E45: 'readonly' option is set (add ! to override) 檔案以唯讀方式開啟,例如用了 view 或 vim -R 確認有寫許可權後用 :w! 強制寫入
E212: Can't open file for writing 當前使用者沒有寫許可權,或檔案所在目錄不存在 見下文
E325: ATTENTION,並提到 swap file 這個檔案有交換檔案:可能有人正在編輯,也可能上次編輯時異常斷開 見下文
E492: Not an editor command: Wq 命令沒有識別,常見原因是大小寫或全形符號 切換到英文輸入法,用小寫重新輸入

E212:普通使用者忘了加 sudo 就開啟了 /etc 下的檔案,改了半天存不進去。不必退出重改,輸入 :w !sudo tee % > /dev/null,把當前內容交給 sudo tee 寫回原檔案(% 代表當前檔名)。寫完 Vim 會提示檔案已在外部被修改,按 L 重新載入,再 :q 退出。更穩妥的做法是先 :w /tmp/shop.conf.new 存到臨時位置,退出後用 sudo 拷回去。

E325:Vim 編輯時會在同一目錄下生成一個隱藏的交換檔案(如 .shop.conf.swp),連線意外斷開後靠它恢復內容。看到提示先確認有沒有別人正在改:ps aux | grep '[v]im'。有人在改,按 Q 退出,等對方改完;提示裡註明程序仍在執行時,Vim 也不會給出刪除選項。沒人在改,說明上次是異常退出:想找回沒儲存的內容就按 R 恢復,核對無誤後儲存,再手動刪掉交換檔案;確定不需要,就按 D 刪除交換檔案後正常編輯。

.vimrc:讓伺服器上的 Vim 順手一些

Vim 啟動時先讀系統級配置(RHEL 系是 /etc/vimrc,Debian 系是 /etc/vim/vimrc),再讀當前使用者的 ~/.vimrc。個人習慣寫進 ~/.vimrc,不要改系統檔案:軟體包升級時它可能被覆蓋,也會影響這台機器上的其他人。下面這份配置適合維運改配置檔案,需要完整版 Vim;用 vim-tiny 的機器只保留前面提到的兩行即可。

set nocompatible                      " 關閉 vi 相容模式
syntax on                             " 語法高亮
set number                            " 顯示行號
set hlsearch incsearch                " 高亮查詢結果,邊輸入邊定位
set ignorecase smartcase              " 查詢忽略大小寫,輸入了大寫字母時才區分
set backspace=indent,eol,start        " 退格鍵可以刪除任何內容
set expandtab tabstop=4 shiftwidth=4  " Tab 鍵輸入 4 個空格
autocmd FileType yaml setlocal tabstop=2 shiftwidth=2
set fileencodings=utf-8,gb18030,latin1  " 開啟檔案時依次嘗試的編碼

expandtab 讓 Tab 鍵輸入空格,YAML 不允許用 Tab 縮排,這一項能避免很多格式錯誤;反過來,Makefile 必須用真正的 Tab,改它之前先執行 :set noexpandtab。fileencodings 里加上 gb18030,開啟 Windows 上編輯過的中文檔案時不容易亂碼。

配置不必追求複雜。維運經常要在別人的機器、救援系統或剛裝好的伺服器上幹活,那裡只有預設的 vi,基本操作熟練比配置漂亮更有用。

機房場景:SSH 斷了,也要能用 Vim 改回來

sshd_config 改壞、網路卡配置寫錯,最直接的後果是 SSH 連不上,這時只能從本機控制檯登入去改。伺服器有 BMC 的話,透過帶外管理開啟的控制檯不依賴作業系統的網路,登入後同樣用 Vim 把配置改回來,備份檔案在這時就派上了用場。Toplink DCIM 的 IPMI 遠端管理在瀏覽器裡開啟走 BMC 通道的 VNC 控制檯,可以把剪貼簿內容貼上進去,也能傳送 Ctrl+Alt+Del 這類組合鍵;貼上大段配置前在 Vim 裡先執行 :set paste,免得自動縮排把格式打亂。系統已經進不去時,租用伺服器的客戶可以在客戶自助端啟動救援模式,掛載硬碟後用同樣的方法修改,硬碟上的資料不受影響。

常見問題

vim 和 nano 用哪個?

nano 把快捷鍵列在螢幕底部,上手更快;但救援系統、精簡容器和各種嵌入式系統裡往往只有 vi。日常用哪個都行,但 vi 的基本操作一定要會。crontab -e 開啟哪個編輯器由 VISUAL 或 EDITOR 環境變數決定,在 ~/.bashrc 里加一行 export EDITOR=vim 即可;Debian 系也可以用 update-alternatives --config editor 設定預設編輯器。

Neovim 和 Vim 是什麼關係?

Neovim 是 2014 年從 Vim 分出來的專案,按鍵和絕大多數命令與 Vim 相同,配置可以用 Lua,也相容大部分 Vim script。伺服器上預設裝的一般還是 Vim,會用 Vim 就能直接上手 Neovim。

有沒有能邊學邊練的教程?

完整版 Vim 自帶 vimtutor 命令,它會開啟一份教程的臨時副本,按提示一步步練習移動、刪除、插入和儲存,大約 30 分鐘走完,練習時怎麼改都不會影響系統裡的任何檔案。

想看看在你的機房裡怎麼用?

從一次產品示範開始,梳理你的業務鏈路。

查看價格
服務熱線 400-112-2951

讓我們聊聊你的 IDC 業務

掃碼新增企業微信,預約產品示範或申請試用。

Toplink 企業微信二維碼

長按儲存或使用企業微信 / 微信掃描

也可致電
400-112-2951
Telegram
@TopLink88