当年刚开始接触 Linux 的时候,最劝退我的不是那堆命令,而是打开配置文件之后整个人愣住——不管按什么键,屏幕上就是不出字,想退出都不知道怎么退。后来才明白,那个叫 vi 的编辑器,背后是一套跟 Windows 记事本完全不同的交互逻辑。但一旦你把它用顺了,你会发现这玩意儿在服务器上简直就是效率神器。这篇就从头到尾聊聊 vi 编辑器的实战用法,覆盖你日常运维、改配置、跨服务器临时编辑文件时最常用的那些操作。
1. vi到底是个什么来头,为什么所有Linux机器上都有它
先说个冷知识:vi 不是某个发行版自己搞出来的东西,它是 1976 年由 Bill Joy 写的,那会儿他还只是加州大学伯克利分校的学生。后来 vi 随 BSD Unix 流传开来,几乎所有 Unix 和 Linux 系统都内置了它。即便到今天,你随便开一台最小化安装的 CentOS、Ubuntu 或者 Alpine,vi 一定在,vim 未必在。所以学 vi 的第一个理由是——它是 Linux 世界的通用语言,你任何机器上都能碰到它。
在大多数发行版里,你输入vi命令,实际打开的很可能是 vim(Vi Improved)。vim 是 Bram Moolenaar 在 1991 年发布的增强版 vi,加了语法高亮、多级撤销、可视模式这些现代编辑器的功能。Ubuntu 上vi默认指向 vim.tiny,一个简化版;CentOS 上默认是完整的 vim-minimal。你可以在终端里执行vi --version或vim --version看一下自己的版本,如果命令不存在,就装个vim包。
很多人会问我,既然 vim 这么好,为什么不直接学 vim?我的回答是:你学的操作 90% 在 vi 里都能用,vi 和 vim 的核心按键完全一致,vim 只是加量不加价。所以下面讲的所有内容,你在 vi 和 vim 里都能直接跑。搞清楚这个底层逻辑,你就不会纠结"到底学哪个"这个问题。
2. 模式切换是vi的命门,理解了它你就学会了一半
vi 跟普通编辑器的本质区别在于它不是"所见即所得"的敲字工具,而是一个模式化编辑器。你敲下的每个按键,在不同模式下含义完全不同。很多人上手就卡在这里,其实就是没搞明白模式。
2.1 三种模式的划分与切换
vi 有且只有三种核心模式:
| 模式 | 作用 | 进入方式 | 退出方式 |
|---|---|---|---|
| 命令模式(Normal) | 执行删除、复制、移动光标等操作 | 启动 vi 默认就在此模式 | 按 Esc 从其他模式返回 |
| 插入模式(Insert) | 向文件里键入内容 | 按 i、a、A、o、O 等 | 按 Esc 返回命令模式 |
| 底行模式(Command-line) | 保存、退出、搜索、替换等 | 在命令模式按冒号: | 回车执行,或按 Esc 取消 |
你可以这样理解:命令模式相当于"指挥模式",你手放在键盘上做的是控制操作;插入模式才是真正的"打字模式";底行模式则是你给 vi 下达"保存""退出"这类指令的入口。最常用的切换链路就是——进 vi 后先按i进入插入模式写内容,写完按Esc回到命令模式,再输入:wq回车保存退出。
2.2 从插入模式回不到命令模式怎么办
这个是最常见的新手恐惧症。你在插入模式下写了一堆字,按 Esc 发现没反应,又按了几下,屏幕上还是没变化,就以为卡死了。其实 Esc 按多少次都没副作用,它只会让你回到命令模式。如果你已经处于命令模式,Esc 还会响一声蜂鸣(或者闪一下屏),那就说明已经在命令模式了。
如果 Esc 键实在不好使,比如某些终端把 Esc 映射走了,你可以用组合键Ctrl + [代替,效果一模一样。还有一个小技巧,在命令模式输入Ctrl + o可以直接临时进入一次插入模式,执行完一个命令后自动回到命令模式,这在某些脚本化操作里特别有用。
3. 五个命令打通vi的基本使用链路
学 vi 不需要一次背完所有键位,你只需要先掌握一条能"打开、编辑、保存、退出"的完整链路,剩下的都是锦上添花。
3.1 打开文件
vi /etc/nginx/nginx.conf文件不存在时 vi 会新建一个空白文件,保存后才真正创建。如果你不想改原文件,可以用vi -R 文件名以只读方式打开,或者用view 文件名。这些细节在排查线上配置时非常有用——避免手滑把线上文件改了。
3.2 进入插入模式的四种姿势
打开文件后你处于命令模式,此时直接敲字母是操作命令,不是输入内容。进入插入模式的常用命令有这么几个,每个适用场景不同:
| 按键 | 作用 | 典型场景 |
|---|---|---|
i | 在当前光标前插入 | 最常用的进入方式 |
a | 在当前光标后插入 | 想在字符尾部追加内容 |
A | 在当前行行尾插入 | 快速在一行末尾追加 |
o | 在当前行下方新开一行插入 | 连续添加新行 |
O | 在当前行上方新开一行插入 | 在配置上方插注释 |
实际操作中,我改配置文件时最常用的是o,直接在当前行下面开一行,不用管光标在哪一列。逐字符配i,效率差别不小。
3.3 保存、退出与组合命令
在命令模式输入冒号进入底行模式,然后敲命令回车执行。常用的就这么几个:
:q 退出(文件没改动时可用) :q! 强制退出,不保存任何改动 :w 保存文件 :wq 保存并退出 :x 保存并退出(只有当文件有改动时才写盘)x和wq看起来一样,但x在文件未修改时不更新文件的修改时间,这个细节在做日志审计或文件同步时能派上用场。如果你打开了文件但没做修改,直接输入:q就能退出,不会报错;如果改过想丢弃全部改动,一定要:q!强退。很多人第一次用:q发现退不出去,就是因为改了内容忘了保存,vi 为了保护你的劳动成果给出了错误提示。
3.4 意外退出的恢复思路
如果你在编辑过程中终端被强关了,或者 SSH 断开,vi 会在文件同目录生成一个.文件名.swp的交换文件。下次你再打开原文件时会提示:
Swap file ".nginx.conf.swp" already exists!这时你有几个选择:按R恢复上次未保存的内容;按D删除那个 swap 文件(前提是你确定不会再恢复旧数据);按Q放弃并退出。我的建议是,先按R恢复看看,把能救的内容复制出来,然后再决定删不删 swap 文件。
4. 光标移动和文本操作,把控制权掌握在手
vi 跟别的编辑器最大的差别是,你不需要动鼠标,所有操作都能在键盘上完成。熟练之后,手指不离开主键盘区,编辑效率会飙升。
4.1 让光标飞起来
很多人刚用 vi 只会方向键,这是最慢的移动方式。vi 的经典移动键位是:
h 左移一格 j 下移一行 k 上移一行 l 右移一格 w 跳到下一个单词开头 b 跳到上一个单词开头 0 跳到行首 $ 跳到行尾 gg 跳到文件第一行 G 跳到文件最后一行 ctrl+d 向下翻半屏 ctrl+u 向上翻半屏 ctrl+f 向下翻一屏 ctrl+b 向上翻一屏这些键位里,w、b、$、gg、G出现的频率最高。改配置时经常要跳到文件末尾追加内容,直接G再加o就能实现。别忘了每个移动命令前可以加数字,比如5w就是跳五个单词,3j就是往下移三行。
4.2 删除、复制、粘贴与撤销
删除操作是 vi 里最灵活的一套组合。单字符删除是x,按一次删一个;dd删除当前行,前面加数字就是删除多行,比如5dd删除从当前行往下五行。
d还可以和移动命令拼成复合指令:dw删除到下一个单词开头,d$删除从光标到行尾,d0删除从光标到行首,dG删除从当前行到文件末尾。这种"动词+方向"的组合逻辑,是 vi 最强大的地方。你只要记住d是个动词,后面接位置词,就能推导出一堆组合操作。
复制粘贴同样遵循这个逻辑:yy复制当前行,5yy复制五行,p在光标下方粘贴,P在光标上方粘贴。这里的 p 是 paste 的缩写,小写往下贴,大写往上贴,记住大小写就记住了粘贴位置。
撤销与重做是救命稻草:u撤销上一步操作,Ctrl + r重做刚才撤销的内容。vim 比 vi 强的地方在于支持多级撤销,你可以一步撤一个命令,一路往回找。旧版 vi 只能撤销最近一次,vim 里放心按u。
4.3 快速定位到指定行
排查错误日志的时候,日志文件报错信息会告诉你行号,比如 "error at line 128"。这时你可以直接:128回车,光标就跳到第 128 行。这个操作在查看大型日志、配置排查时特别高效,不用手动翻页。
展示行号的方法是底行模式输入:set nu,取消是:set nonu。后面讲 vimrc 配置时还会提到怎么永久开启行号。
5. 搜索与替换,处理大文件的核心武器
日志文件动辄上千行,配置文件也有几百行,靠肉眼翻肯定不行。vi 的搜索和替换功能能让你的效率直接拉满。
5.1 快速搜索与跳转
在命令模式下按/,输入要搜的内容再回车,光标就会跳到第一个匹配的位置。按n跳转到下一个匹配项,按N跳转到上一个。如果搜完想高亮消失,可以输入:nohlsearch关闭高亮,或者:set nohlsearch永久关闭,重启后又恢复。
搜索时注意特殊字符。/nginx.conf如果直接搜带点的内容,.会当作通配符。想精确匹配,需要转义:/nginx\.conf。或者你可以用\V开启 very nomagic 模式,让所有字符都按字面意思解释。这个细节极少有人提,但实战中搜 IP、端口、带正则符号的配置时经常踩坑。
5.2 替换命令的完整语法
vi 的替换命令长这样:
:s/old/new/ 替换当前行的第一个 old :s/old/new/g 替换当前行所有 old :%s/old/new/g 替换整个文件所有 old :%s/old/new/gc 替换整个文件所有 old,但每次询问确认%代表整个文件,g代表全局(行内所有匹配而非第一个),c代表确认。这个语法虽然是 vi 的,但很多其他工具(sed、VSCode 的替换框)都沿用了类似思路,学会了到处都能用。
5.3 带确认替换的实操场景
线上该配置的时候,最怕的是全局替换把不该改的地方也改了。比如你想把配置里的 8080 端口全部改成 9090,但有一行注释里也有 8080,确实也要改,可有的地方是 80800,如果直接%s/8080/9090/g,80800 就会变成 90900,那就出大问题了。
正确做法是:%s/8080/9090/gc,vi 会逐个匹配询问你:
replace with 9090 (y/n/a/q/l/^E/^Y)?y确认替换n跳过本次a全部替换,不再询问q退出替换l替换当前并结束
在改线上配置时,我强烈建议带 c 确认一次,肉眼扫一遍匹配结果,比任何后悔药都强。
6. 多文件编辑与分屏,运维场景的高级玩法
实际工作中,你经常要同时改好几个文件,或者一边看日志一边改配置。vi 的多文件能力和分屏机制这时候就能派上大用场。
6.1 同时打开多个文件
vi file1.txt file2.txt打开后默认显示 file1,底行模式输入:n切换到下一个文件,:N或:prev返回上一个。:ls列出所有已打开文件及编号,:b 2直接跳到编号为 2 的文件,这个缓冲区操作我几乎每天都会用。
如果你已经在 vi 里了,还可以用:e /path/to/file打开另一个文件,相当于在当前窗口加载新文件。这对临时查看某个配置特别方便,不用退出再进入。
6.2 分屏操作与跨文件复制
分成上下两个窗格的命令是:split或者简写:sp;分左右两个窗格是:vsplit或:vsp。分屏后光标跳转用Ctrl + w加方向键,比如Ctrl + w再按j跳到下方窗格,Ctrl + w再按h跳到左窗格。
分屏的经典用法是一边打开配置文件,一边打开服务日志。比如:
vi /etc/nginx/nginx.conf /var/log/nginx/error.log :sp改完配置后切到日志窗格,用G跳到文件末尾看实时输出(配合tail -f做不到 vi 内实时刷新,但你可以手动跳到末尾刷新)。跨文件复制也很简单:在 file1 里用yy复制几行,切到 file2 的窗格,按p粘贴,操作无缝衔接。
6.3 标签页模式
vim 从 7.0 开始支持标签页,命令是:tabnew 文件路径,多个标签页之间用gt向后切换、gT向前切换。这个功能跟终端的多标签行为类似,适合需要同时打开多个独立上下文但又不想分屏的场景。不过按我自己的习惯,分屏比标签页用得多,因为看配置和日志经常是上下对照着看,分屏一眼全览,标签页还得来回切。新手可以两个都试一下,找自己顺手的。
7. 异常场景应对与系统优化
用 vi 不是永远一帆风顺的,特别是你拿到一台不熟悉配置的服务器,各种状况层出不穷。这里把最常见的几个坑都列出来,你遇到的时候直接照着做就行。
7.1 swap 文件与崩溃恢复
前面提到过,vi 会生成.文件名.swp。如果系统崩溃,vi 下次打开时会提示恢复。具体步骤是:
- 打开文件,看到 swap 提示后按
R恢复。 - 把恢复出来的内容用
:w /tmp/backup.txt另存一份。 - 确认旧内容不再需要,再删除
.文件名.swp。 - 重新打开原文件继续编辑。
如果启动时没提示,你也可以手动执行vi -r 文件名来进入恢复模式。这条命令适合那种"vim 打开时报了错但我直接回车跳过了"的情况,手动恢复能捞回不少数据。
7.2 编码问题导致乱码
服务器上跑的多是 UTF-8,但 Windows 上传来的文件可能是 GBK 或 GB18030 编码。vi 打开显示乱码,不影响文件内容,但看着难受。解决办法是在打开文件前或打开后设置编码:
:set encoding=utf-8 :e ++enc=gbke ++enc=gbk是让 vi 用 GBK 编码重新加载这个文件,内容以正确编码显示。要是你想把文件转成 UTF-8 保存,可以这样操作:
:set fileencoding=utf-8 :w这个操作会以 UTF-8 重新写盘。转换前建议先备份原文件,因为编码转换出问题比乱码更麻烦——文件直接打不开都有可能。
7.3 权限不足时的强制保存
你编辑一个 root 拥有的文件,但当前用户没写权限,vi 保存时会报E212: Can't open file for writing。如果你有 sudo 权限,可以用这个组合命令:
:w !sudo tee %它会用 sudo 执行 tee 命令把当前缓冲区内容写回原文件。注意这个命令是在 vi 内部执行的,不是让你退出重来。执行后 vi 会提示再次回车确认,文件就保存成功了。这个技巧在改/etc目录下的系统配置时特别好用,不用为了一个文件退出 vi 再 sudo vi 重开。
7.4 终端信息错乱的小问题
在某些 SSH 客户端或 tmux 会话里,vi 显示会出现花屏、错位。一般是终端类型没设对。你可以在进入 vi 前输入export TERM=xterm-256color,或者直接 vim 内设置:set term=xterm-256color。另外按Ctrl + l可以重绘屏幕,刷新一下显示状态,很多花屏问题一下就解决了。
8. vimrc配置文件,把编辑器调教成顺手的样子
vi 是没有配置文件的,但 vim 有,就在你用户目录下的.vimrc文件里。如果你用的是 vi 命令但底层是 vim,配置文件一样生效。把常用设置写进去,每次打开都自动应用,体验瞬间上升一个档次。
8.1 基础设置项
下面这些是我个人项目的起步配置,没什么花哨的功能,但极其安定:
set number " 显示行号 set relativenumber " 相对行号,配合 d5j 这类操作非常好用 set tabstop=4 " Tab 显示宽度 set shiftwidth=4 " 缩进宽度 set expandtab " 用空格代替 Tab set hlsearch " 搜索结果高亮 set ignorecase " 搜索忽略大小写 set smartcase " 但输入大写时,不忽略大小写 set textwidth=80 " 自动换行的最大宽度 set fileencodings=utf-8,gbk " 自动检测编码顺序 set whichwrap+=<,>,h,l " 光标在行首行尾时允许循环移动relativenumber是 vim 7.3 推荐开启的选项,它会以光标所在行为基准显示上下各有多少行。配合d5j(向下删除五行)、y3k(向上复制三行)这种带数字的复合命令,效率比绝对行号高一截。不过如果刚接触 vi,建议先只开set number,等操作熟练了再切相对行号,不然会被一堆变化的数字搞晕。
8.2 常用快捷键映射
在.vimrc里还可以重映射按键。比如把 jj 映射成 Esc,免去按 Esc 的抬手动作:
inoremap jj <Esc>如果你经常保存文件,可以映射个快捷键:
nnoremap <C-s> :w<CR>注意这里用了nnoremap表示非递归映射,意思是这条映射只执行右侧内容,不会再触发其他映射,避免连锁反应。我见过有人把e映射成dd之后又把w映射成e,结果整个光标移动逻辑全乱了,排错排了半天。新手改映射时,一定用nnoremap而不是noremap,并且每次只改一条,保存后用:source $MYVIMRC重新加载配置测试。
8.3 插件管理,从零开始搭个趁手IDE
vim 有完善的插件生态,管理插件最常用的是 vim-plug。安装方法是在终端执行:
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim然后在.vimrc里加一段:
call plug#begin('~/.vim/plugged') Plug 'preservim/nerdtree' " 文件树 Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } " 模糊搜索 Plug 'junegunn/fzf.vim' Plug 'vim-airline/vim-airline' " 状态栏美化 Plug 'tpope/vim-commentary' " 一键注释 call plug#end()保存配置后进入 vim 执行:PlugInstall,vim-plug 会自动拉取插件列表里的仓库。装好后,<leader>n可以打开文件树,Ctrl + p用 fzf 找文件,gc注释当前行,体验直逼 IDE。
插件这块入门别贪多。先装一个文件树和一个模糊搜索就够用,用熟了再慢慢加。装太多插件不仅启动慢,出问题也难排查。
9. 进阶技巧,让你的vi操作脱胎换骨
基础操作你都能闭着眼用之后,还有几个进阶技巧能让你在同事里瞬间拉开差距。
9.1 宏录制,重复操作一键搞定
宏是 vi 里最被低估的功能,没有之一。你在命令模式按q加一个字母,比如qa,然后 vi 开始录制你对文件的所有操作,直到你按q结束录制。之后按@a就能重放这段操作,10@a重放十次。
举个例子,你的文件里有 10 行全都没有分号,每行末尾都要加;。你可以录制宏:qa开始,按A;跳到行尾加分号,按Esc,再按j跳到下一行,最后按q结束。接着按9@a,剩下九行全搞定。这个思路同样适用于批量加注释、批量缩进、批量替换。
9.2 可视模式,精确选中修改
在命令模式按v进入字符可视模式,按V进入行可视模式,按Ctrl + v进入块可视模式。用方向键选中内容后,你可以按d删除、按y复制、按>缩进。
块可视模式特别强大,可以选中多行的同一列进行处理。比如你有一段代码要批量在前面加个注释符,进入Ctrl + v,选中多行第一列,按I输入#,再按Esc,所有选中行首都会加上#。这个操作在 Python、Shell、配置文件的批量注释场景下,比你一个个改快太多了。
9.3 用外部命令与vi协作
vi 底行模式可以用!前缀调用外部命令。比如:!ls会执行 ls 并返回结果,:r !date会把当前日期插入到文件里。这个能力在做日志标记、脚本生成时特别省事。
如果把当前选中的内容通过管道传给外部命令处理,用!加范围。比如选中几行后按:!sort,这选中的几行就会被 sort 排序后替换。同理,:!python3 -m json.tool可以格式化 JSON。我在写配置文件或调试桩代码时经常这么干,不用切出 vi 就能完成数据格式化。
9.4 vimdiff,文件对比的神器
排查两个配置文件的差异,不要用diff加cat反复看,直接用 vimdiff:
vimdiff file1.conf file2.conf它会把两个文件并排显示,差异部分高亮标出。光标在非差异处时,可以用do把另一个文件的改动拿过来,用dp把当前改动推过去。这个工具在做代码评审、迁移配置、核对环境差异时非常好用,是我最推荐的进阶功能之一。
10. 一些絮叨的实操心得
写了这么多,最后分享几个我自己摸爬滚打总结出来的经验。
第一,别死记命令。vi 的命令体系非常自洽,d是删除、y是复制、p是粘贴、u是撤销,而这些动词后面接的是移动位置w(单词)、$(行尾)、gg(文件开头)。记住"动词+方向"这个模式,你就能推理出大量组合命令,根本不需要背表。
第二,买一把带实体 Esc 键的键盘。我知道有人用笔记本键盘按 Esc 很别扭,但 vi 操作频率最高的就是 Esc,这个键用着顺不顺直接影响你的使用体验。如果你实在不想按 Esc,就给.vimrc加一句inoremap jj <Esc>,用双 j 代替。
第三,在真正重要的服务器上改文件时,先把文件备份一份再动。我的习惯是cp一份带时间戳的备份,比如cp nginx.conf nginx.conf.bak20250101,再进 vi。改挂了随时能退回来。vi 很强大,但你总得给自己留条后路。
第四,如果你每天都要和服务器打交道,建议在本地电脑上装好 vim 并配好.vimrc,遇到问题先在本地练熟,再去线上操作。线上环境基本是裸的,和你本地配置完全不一样。你把本地当成练习场,线上操作才不会被突然弹出来的提示框吓住。
vi 的学习曲线确实陡,但它一旦跨过那道坎,就会变成你肌肉记忆里最自然的一部分。不用刻意背快捷键,把这篇里提到的命令一个个试过去,用两个星期,你就能在 Linux 世界里游刃有余了。