提到Linux,vi编辑器绝对是躲不开的一个坎。不管是刚装好系统的云服务器,还是只能通过串口调试的嵌入式开发板,甚至在容器里临时改个配置,最后都会落到vi手里。很多人第一次登录Linux服务器,照着教程输入vi /etc/nginx/nginx.conf,然后整个人就懵了:不知道怎么输入文字,不知道怎么保存,更不知道怎么退出,最后只能强制关闭终端。这篇文章就把vi从头到尾拆开讲,从三种模式、常用命令,到进阶配置和常见问题排查,全部覆盖,让你从“会打开”到“用得溜”,在终端里编辑文件不再发怵。
1. vi编辑器的核心价值与适用场景
1.1 为什么到现在还在用vi
很多刚接触Linux的人都有个疑问:明明有VS Code、有Sublime Text,图形界面也做得越来越好看,为什么还要学一个看起来很有年代感的编辑器?
原因很简单:在Linux服务器环境里,图形界面往往是不存在的。生产环境中绝大多数系统都是最小化安装,没有桌面环境,你只有命令行。SSH连上去以后,图形编辑器根本没有施展空间,vi(严格来说是vim)就是这种情况下最可靠的文本编辑工具。
另外,vi几乎被内置在所有Linux发行版里,不需要额外安装,不依赖图形库,内存占用极小,启动速度极快。这一点在系统负载很高、内存吃紧时尤其重要。我遇到过几次云服务器负载飙到20、内存快要耗尽的情况,图形界面起不来,但vi照样能流畅打开配置文件,帮我把问题排查完。
还有一个原因纯粹是效率。vi的设计哲学是“手不离主键盘区”,它把光标移动、删除、复制、粘贴、替换都变成了键盘快捷键的组合。熟练之后,编辑文件的速度比用鼠标点选快得多。这也是很多运维老手宁可记一大串按键序列、也不想碰鼠标的原因。
1.2 哪些场景离不开vi
用Linux做开发、做运维、做嵌入式,几乎都有躲不开vi的时刻。常见场景我列一下:
- 服务器上修改配置文件,比如
/etc/nginx/nginx.conf、/etc/ssh/sshd_config、/etc/selinux/config - 修改用户和用户组,比如编辑
/etc/passwd、/etc/sudoers - 写Shell脚本、Python脚本,但服务器上没有图形编辑器
- 嵌入式Linux设备上,通过串口或SSH登录开发板,vi基本是唯一可用的编辑工具
- 容器(Docker)里临时修改配置,镜像往往不装任何图形组件
甚至可以说,很多场景下你可能已经在用vi了——比如在某篇教程里看到“执行vim xxx.conf”,你打开后却不知道怎么退出。网络上“vi怎么退出”这个话题被搜索了无数遍,就是因为vi的模式化交互方式,跟普通编辑器的直觉完全不同。
接下来就把这套模式讲透。
提示:本文讲的“vi”在绝大多数现代Linux发行版中实际是指向vim的别名(比如Ubuntu、Debian中
vi符号链接到vim.tiny,RHEL系中链接到vim-minimal)。vim是vi的增强版,指令上完全兼容,但体验更好。下面统一以vi称呼,实际输入时用vim或vi均可。
2. 入门必会:vi的三种模式与核心操作
2.1 三种模式的设计逻辑
vi最大的特点是有三种模式,很多人第一次接触不习惯,就是因为这个模式切换跟记事本完全不一样,其实设计逻辑在当年很合理。
- 命令模式:打开vi后默认进入的模式。此时键盘上的按键不会作为文字输入,而是作为操作指令。比如按
j是向下移动光标,按dd是删除一行。 - 插入模式:按
i、a或o进入,此时键盘输入的就是文本内容。按Esc返回命令模式。 - 末行模式:在命令模式下按冒号
:进入。这一行通常位于屏幕底部,用来输入保存退出、搜索替换、设置选项等命令。执行完命令后自动返回命令模式。
为什么设计成这样?因为在vi诞生的年代,终端就是一块没有任何鼠标的屏幕,键盘上也没有F1到F12这种约定俗成的功能键,所以只能用普通字母键做指令。如果不做模式区分,按一个字母就会在文件里打出一个字母,那编辑指令就没法输入了。
理解了这个逻辑,你就明白为什么新手会在vi里打出乱七八糟的内容——因为在命令模式下按了一堆字母键,机器把这些都当成了指令执行,屏幕上一片混乱,你却以为是在输入文本。
实操中,第一急救技巧就是:不确定自己在哪个模式时,狂按Esc,它总能把你拉回命令模式。
2.2 打开、编辑、保存、退出的最小操作集
先来一套最核心的操作,这套会了,你的vi至少不会“进去出不来”。
打开文件:
vi 文件名如果文件不存在,vi会创建一个临时缓冲,保存时才真正生成文件。
进入插入模式,三种方式:
| 按键 | 作用 |
|---|---|
i | 在当前光标位置前插入 |
a | 在当前光标位置后追加 |
o | 在光标下方新建一行并进入插入模式 |
**编辑内容:**正常打字就行。
**退出插入模式:**按Esc。
保存并退出:
:wq按顺序拆开理解::进入末行模式,w是写入(write),q是退出(quit),连起来就是“保存并退出”。
不保存强制退出:
:q!叹号表示强制执行。当你改乱了文件不想保留时,这个命令就是救命稻草。
这里有几个新手容易踩的坑:
- 在插入模式下不小心按了方向键,屏幕上出现了A、B、C、D而不是光标移动,这通常是终端类型识别的问题,在5.4节有详细解法。
- 只想保存但继续编辑,用
:w不退出即可。 - 用
vi新建了一个文件,编辑后忘记保存直接关终端,内容就会全部丢失。vi在退出时如果检测到内容有变化,会提示你有修改尚未写入,这时再按:wq或:q!决定去留。
2.3 光标移动:比鼠标更快的一批按键
vi里移动光标是高频操作,练熟这批按键,你在文件里穿梭的速度能快上好几倍。
基本移动:
| 按键 | 作用 |
|---|---|
h | 左移一个字符 |
j | 下移一行 |
k | 上移一行 |
l | 右移一个字符 |
0 | 跳到行首 |
$ | 跳到行尾 |
w | 跳到下一个单词开头 |
b | 回到上一个单词开头 |
行间与页间移动:
| 按键 | 作用 |
|---|---|
gg | 跳到文件第一行 |
G | 跳到文件最后一行 |
Ctrl+d | 向下滚动半屏 |
Ctrl+u | 向上滚动半屏 |
数字配合跳转:
50G这个操作是跳到第50行。如果你开了相对行号,直接输入数字加G就能精确跳转到相对位置,这在写代码时定位错误信息特别实用。
举例:假设你要在大日志文件末尾加一行内容,先按G跳到文件最后一行,再按$到行尾,按i进入插入模式,直接在末尾追加内容。整个过程不用鼠标,也不用滚动几百屏。
3. 命令模式下高效编辑:删除、复制、粘贴、撤销
3.1 删除操作的组合逻辑
vi的删除操作遵循一个组合套路:次数 + 操作符 + 对象。理解了这套逻辑,你就能自己组装出很多命令。
字符级删除:
x:删除光标所在字符3x:删除从光标位置开始的3个字符(次数+操作符x)
行级删除:
dd:删除当前行3dd:从当前行开始向下删除3行
词级删除:
dw:删除从光标位置到当前单词结尾d$:删除从光标位置到行尾d0:删除从行首到光标位置
这里核心是d这个操作符。d后面跟什么对象,就删除什么范围。w是单词,$是行尾,0是行首,G是文件尾。都能组合。
一个很实用的场景:你想把文件里的某一行移动到别处,用dd删掉该行,然后移到目标位置按p,这行就粘贴过去了。等于完成了剪切-粘贴。
注意:p是粘贴到当前光标所在行的下方,P是粘贴到上方。大小写不同,行为完全不同,很多新手在这栽过跟头。
3.2 复制、粘贴、撤销与重做
复制对应的操作符是y(yank,拉取)。
yy:复制当前行3yy:复制从当前行开始的3行yw:复制当前单词
粘贴用p(下方)或P(上方),撤销用u,重做用Ctrl+r。
实际使用中,最常用到的组合是:用yy复制一行配置文件,到目标位置按p粘贴,然后微调参数。比如把Nginx里某个server块复制5份,改改端口就行。
这里要专门提醒一个坑:从外部复制文本(比如从浏览器复制一段配置)然后粘贴到vi,在终端模拟器里不能按Ctrl+V,因为Ctrl+V在vi里是进入可视块模式,不是粘贴。正确做法:
- 在插入模式下,用终端模拟器自带的粘贴快捷键(Windows Terminal是
Ctrl+Shift+V,Xshell是Ctrl+V或右键菜单) - 或者直接在vi里输入
:set paste再粘贴,粘完再输入:set nopaste恢复
为什么强调这个?因为没有paste模式时,vi会自动帮你的粘贴内容做缩进匹配,原本格式良好的配置会被搞得乱七八糟。我之前就遇到过同事把一段yaml粘到配置文件里,结果缩进完全乱了,排查了半天才发现是粘贴问题。
3.3 搜索与替换
搜索:
在命令模式下输入:
/关键词从光标位置向下搜索。?关键词则向上搜索。
搜索后按n跳到下一个匹配,按N跳到上一个匹配。如果希望搜索结果高亮显示,提前设置:
:set hlsearch删除高亮用:
:set nohlsearch搜索完成后如果不需要继续查找,尽早取消高亮,不然满屏黄底绿字很干扰视线。
替换:
替换的命令是vim里最需要小心使用的功能,新手务必先理解各个命令的含义。
| 命令 | 作用 |
|---|---|
:s/old/new | 只替换当前行中第一个匹配 |
:s/old/new/g | 替换当前行所有匹配(g表示全局global) |
:%s/old/new/g | 替换整个文件中所有匹配(%表示整个文件) |
:%s/old/new/gc | 每次替换前询问确认 |
为什么要用gc?批量替换时,如果目标串恰好在别的关键字符串里,一次替换很容易误伤。比如你想把配置里的test改成prod,但文件里还有contest、protocol这样的词,直接全局替换会把不该动的部分也改了。用gc可以在每次替换前让你决定是否确认,安全系数高很多。
替换时还支持正则表达式。比如:
:%s/^#//g这行命令的意思是:把每行开头的#删除。把配置文件中被注释掉的配置全部“解除注释”,在排查服务配置时这是高频操作。
3.4 多文件与分屏协作
实际生产环境里,经常需要同时参考两份文件来修改。vi支持打开多个文件:
vi file1 file2 file3打开后,用:n切换到下一个文件,:N回到上一个文件。
比多文件更好用的是分屏:
:sp 文件名 " 水平分屏 :vsp 文件名 " 垂直分屏分屏之间切换的快捷键是:按Ctrl+w松开,然后按方向键选择要去哪个窗口。
我在排查问题时最喜欢垂直分屏:左边打开nginx.conf,右边打开error.log,边看日志边改配置,改完立即重载服务看效果,效率极高。在没有图形界面的服务器环境里,这就是终端用户版的“代码对比工具”。
4. 进阶配置:打造个人化的vi环境
4.1 为什么必须学会配vimrc
vi的默认配置就一个字:能用。但离“好用”还有不少距离。默认无行号、无语法高亮、搜索不高亮、缩进不理想,体验只能算及格。
通过写一个配置文件,可以把行号、语法高亮、自动缩进、搜索高亮、剪贴板互通这些体验优化一次搞定。vi的配置文件路径是用户主目录下的~/.vimrc,系统级的是/etc/vimrc。用户级配置生效于当前用户,优先级高于系统级。
写好配置文件后重新打开vi就生效了。如果你正在vi里,可以用:
:source ~/.vimrc立即重新加载配置,不用退出,调试配置时非常方便。
4.2 一套可以直接抄的vimrc配置
下面这组配置我用了很长时间,直接复制到~/.vimrc即可:
syntax on set number set relativenumber set expandtab set tabstop=4 set shiftwidth=4 set softtabstop=4 set autoindent set hlsearch set incsearch set ignorecase set smartcase set wrap set linebreak set showcmd set cursorline set laststatus=2 set ruler set scrolloff=5逐条解释几个重点:
syntax on:开语法高亮。写脚本、配置、程序时,高亮能让你一眼发现拼写错误和结构问题。set number:显示行号。排查日志时,日志里报“第250行有问题”,你直接数到那附近对照,效率高很多。set relativenumber:显示相对行号。配合数字G跳转,比如你看到当前光标在第20行,目标在第25行,直接输5G就能跳过去,不用心算绝对行号。set expandtab:把Tab键自动转成空格。这个配置对写Python的尤其重要,因为Python靠缩进区分代码块,混用Tab和空格容易引起莫名其妙的缩进错误。set tabstop=4:Tab键显示宽度为4个空格。如果团队项目里有缩进规范,按团队规范调整这个数字。set autoindent:换行时自动保持上一行的缩进,写代码时回车换行不用一个空格一个空格敲,省力很多。set hlsearch和set incsearch:搜索时高亮匹配,并在输入关键字时实时预览匹配位置。set ignorecase和set smartcase配合:搜索时默认忽略大小写;但如果你搜的关键词里有大写字母,就自动变成区分大小写。这个组合很智能,省去手动切换大小写的麻烦。set clipboard=unnamed:使vi的复制操作直接接入系统剪贴板,复制到vi里的内容能粘贴到终端外。这个选项在纯命令行SSH环境下可能不生效(依赖X11剪贴板),但在本地图形终端下非常实用。set scrolloff=5:光标滚动到距离屏幕边缘5行时就开始滚屏,避免眼睛频繁追踪光标跳来跳去。
4.3 插件与扩展方向
vim(不只是vi)有着非常成熟的插件生态,装了插件以后,它的编辑体验能接近轻量级IDE。
插件管理器我推荐vim-plug,安装方式简单,配置也直观。在~/.vimrc中声明插件:
call plug#begin('~/.vim/plugged') Plug 'preservim/nerdtree' Plug 'vim-airline/vim-airline' Plug 'junegunn/fzf.vim' Plug 'neoclide/coc.nvim' call plug#end()然后在vi里执行:
:PlugInstall它会自动下载并安装插件。
常用插件介绍:
nerdtree:文件树侧栏,在vi里浏览文件目录vim-airline:底部状态栏增强,显示当前模式、行号、文件类型、分支信息,一眼看清所处状态fzf.vim:模糊搜索文件名和文件内容,适合大型项目里快速定位文件coc.nvim:代码补全引擎,支持LSP,配合Ctrl+p能实现类似IDE的补全体验
不过我要多说一句:在服务器或嵌入式环境里,装插件前先评估必要性。插件依赖额外进程和内存,有些环境还不允许联网。生产环境中排查问题时,最可靠的方法反而是裸vim加上熟练的快捷键。插件属于“锦上添花”,不是“雪中送炭”,别让插件管理占据你过多测试和排障时间。
4.4 中文乱码问题怎么配置
服务器上vi打开中文文件显示乱码,通常和两件事有关:系统locale设置、终端编码。
处理思路:
第一步:确认系统locale
locale如果是LANG=C或LANG=POSIX,说明系统没有启用UTF-8支持。可以安装中文语言包(Debian系用apt install locales然后dpkg-reconfigure locales勾选zh_CN.UTF-8),或者至少设置一个UTF-8的locale:
export LANG=en_US.UTF-8第二步:在vimrc里设置编码
set encoding=utf-8 set fileencodings=utf-8,gbk,gb18030,big5这样vi打开文件时会尝试按UTF-8、GBK等常见编码顺序自动识别,尽量把文件内容正确翻译出来。
第三步:检查终端编码
如果文件本身没问题,只是显示乱码,问题可能出在SSH客户端上。在Xshell、MobaXterm或Windows Terminal里,确认终端编码为UTF-8。
如果以上都排查了还乱,可以用iconv转换文件编码:
iconv -f gbk -t utf-8 文件名 > 新文件名转成UTF-8后再用vi编辑,这是处理旧系统遗留GBK文本的保底方案。
5. 常见问题与排查技巧实录
5.1 中途想退出但不会,被卡在vi里
这是新手碰到最多的状况。一定要记住这个应急口诀:按一下Esc,输入:q!,回车。
Esc回到命令模式,:q!强制退出不保存,回车确认。这组操作一定不会出错,适合在情况混乱时使用。
如果你输入:q,vi提示E37: No write since last change,说明有修改未保存,系统拒绝直接退出。这时候要么:wq保存退出,要么:q!放弃修改退出。这两个的区别一定要分清,尤其在编辑重要文件时,误按:q!会把所有改动都丢掉。
5.2 保存时提示磁盘满或没有权限
在服务器上编辑系统配置文件时,经常会遇到E212: Can't open file for writing,翻译过来就是“无法打开文件写入”,背后的原因通常是:
- 当前用户对文件没有写权限:这是最常见的情况。解决方法是改用
sudo vim 文件名打开编辑。 - 当前用户对文件所在目录没有写权限:vi保存文件需要写目录项(创建交换文件),如果目录本身不可写,即使文件有权限也会保存失败。
- 磁盘空间已满:执行
df -h查看磁盘使用率,满了就清理日志或临时文件后再保存。
一个我实际操作中经常用的技巧:如果已经用普通用户打开了文件,但发现没权限保存,不必退出,直接输入:
:w !sudo tee %这条命令的意思是:当前文件内容通过sudo tee以管理员权限写入当前文件。可以把修改直接保存,不用中断编辑重新打开。
5.3 交换文件(swap file)占用问题
vi在编辑文件时,会在同一目录下生成一个隐藏的交换文件,以.文件名.swp形式存在。比如你编辑nginx.conf,目录下就会出现.nginx.conf.swp。这个文件的作用是防止多人同时编辑同一文件,以及在崩溃时恢复未保存的内容。
如果你上次没有正常退出(比如终端断电、SSH断线),下次再打开同一个文件,就会出现类似提示:
Swap file ".nginx.conf.swp" already exists!这时候有几种处理方式:
- 按
O以只读方式打开:可以查看文件,但不能修改保存 - 按
R恢复:用交换文件里的内容恢复上次未保存的修改 - 按
D删除交换文件:确认上次的内容不需要恢复,直接删除锁文件
处理顺序很重要:先按R恢复看看有没有要的内容,确认不需要后再按D删除。如果直接删交换文件,可能把上次意外断开时未保存的修改彻底弄丢。
确认不需要恢复后,可以手动清理:
rm .nginx.conf.swp我处理这类情况的经验是:不要急着删。先把文件打开看一遍,确认最后的内容是否完整,再决定是按D还是按R。
5.4 方向键变成ABCD的问题
在vi的插入模式下按方向键,屏幕不移动光标,反而出现了A、B、C、D,这个问题的本质是终端没有把箭头按键的转义序列正确传给vi,vi没有识别出你使用的终端类型。
解决办法分两步。
第一步:在vimrc里关闭兼容模式
set nocompatible第二步:检查终端类型
echo $TERM正常的输出值通常是xterm-256color或screen。如果输出不正确,可以临时设置:
export TERM=xterm-256color如果你用的是SSH登录远程服务器,可能需要考虑本地终端与远程终端类型匹配的问题。大多数现代SSH客户端设置的TERM值是对的,如果不对,在这个变量上调整即可。
补充一个相关配置:
set backspace=indent,eol,start这个配置让退格键可以删除缩进、跨越行尾、从插入模式刚开始的位置一直往回删。默认情况下,vi的退格键在插入模式有较多限制,加上这行后更符合现代编辑器的使用习惯,不然你会发现退格键删不了某些内容,非常难受。
5.5 误删内容和崩溃后怎么恢复
如果你在vi里不小心删掉了关键内容,只要还没退出,立刻按u撤销即可。如果需要撤销多次,按几次u,或者用Ctrl+r重做。
如果已经保存并退出了,恢复的难度就大了。不过还是有几条路可以尝试:
- 查看
~/.viminfo文件里记录的操作历史,这个文件记录了vi会话中的操作,但它保存的是命令记录,不是文件内容。 - 如果文件在Git仓库管理下,直接用
git checkout回退到上一个版本。这是最可靠的恢复方式。 - 如果使用etckeeper等工具管理
/etc目录的版本,系统配置文件也可以回滚。
说到这,我个人的强烈建议是:对高频修改的配置文件目录建一个Git仓库。比如/etc目录,初始化仓库后每次修改前提交一次,出问题就能随时回滚。我在生产环境中的做法是定期对/etc和关键项目目录做版本快照,这个习惯已经帮我避免了无数次的“把配置改坏了但不知道从哪里恢复”的窘境。
6. 实操心得与进阶建议
6.1 从只会编辑到肌肉记忆
vi的学习曲线确实比较陡峭,但一旦跨越了最开始的不适感,后续提升非常快。我的练习思路是:把日常操作中必须用鼠标做的事,刻意用vi的快捷键替代。
举个例子:你正在看日志文件,想翻到第200行,不要用鼠标滚动,直接输200G。改配置文件时想复制上一行内容,不要全选复制粘贴,用yy和p。搜索关键字时,不要用终端模拟器的Ctrl+F,用/关键词。
把这些动作重复到形成肌肉记忆,大概需要两到三周时间。这之后你就会发现,在终端里编辑文件其实可以非常流畅。
我建议的学习顺序:
- 第一周:把最小操作集和光标移动指令背熟,保证自己能开、能改、能存、能退
- 第二周:练dd、yy、p、u这几个高频编辑操作
- 第三周:学搜索替换,然后配好vimrc
- 第四周:开始尝试分屏、多文件,甚至插件
6.2 vi在面试和日常运维中的地位
很多Linux面试题都爱问vi,比如“如何查看某文件并跳到第100行”“如何在vi中全文替换某个单词”。看起来很基础,但实际动手环节里,考官特别看重你对vi的熟练度。因为vi是Linux操作的地基,连地基都不稳的人,很难让人相信他有丰富的服务器实战经验。
日常系统管理同样绕不开vi:新建用户时要编辑用户属性,修改SSH配置时要编辑sshd_config,排查启动问题时要看journal日志、改systemd服务文件,写定时任务跑crontab -e——所有这些操作,编辑器几乎都是vi。
从我的观察来看,凡是能在终端里从头到尾不碰鼠标完成一次完整排障的工程师,面对突发故障的定力和效率都明显高出一截。这种能力很大程度就建立在vi和其他命令行的熟练度上。
6.3 学习路径与最后的小建议
最后分享一个我自己的习惯:每台新服务器或新开发机落地之后,第一件事就是把~/.vimrc配好。配置好之后,每次编辑文件都在享受这套环境;换机器也简单,直接把vimrc复制过去,分分钟还原出熟悉的工作环境。
vi的高级功能还有宏录制、可视模式、寄存器、多窗口协同等等,这些不需要在一开始全部掌握。先把基础操作练到自然反应,遇到具体需求时再按需学习,效率更高。
系统自带的vimtutor是个好东西,输入vimtutor就能打开一个交互式教程,边看边练,内容从基础到进阶覆盖很全面。如果你刚接触vi,我强烈建议跟着它过一遍,比自己硬看文档效果好太多。
vi这个编辑器虽然已经存在了几十年,但在Linux世界里依然是不可或缺的基本技能。无论以后是向开发方向走,还是往运维、嵌入式方向发展,把vi练好,都算是迈出了踏实的第一步。
提示:如果在练习过程中遇到具体的报错,比如某个命令行为不符合预期,建议把错误信息和操作步骤记录下来,对照排查。多动手比多看书重要,练上两周,自然就顺了。