Vim “write with sudo”技巧的工作原理

Vim “write with sudo”技巧的工作原理

技术背景

在使用 Vim 编辑文件时,有时会忘记以 sudo 权限打开文件,当尝试保存对受保护文件的更改时,会遇到权限不足的问题。“write with sudo” 技巧就是为解决此问题而产生的。

实现步骤

1. 理解命令中的符号和命令

  • %:代表当前文件名。在 Vim 的 Ex 命令中,当需要使用文件名的地方,% 会被替换为当前文件名。例如,在 :w !sudo tee % 中,% 就是当前正在编辑的文件名。
  • :w:Vim 中用于写入文件的命令。但在 :w !cmd 这种形式下,它并不是直接更新文件,而是将当前缓冲区的内容传递给一个 shell 命令。
  • !:用于在 Vim 内部调用 shell 命令。
  • sudo:用于获取超级用户权限,允许执行需要管理员权限的操作。
  • tee:该命令类似于一个 T 形管道,它将输入复制到指定的文件中,同时将输出发送到标准输出。

2. 执行命令

在 Vim 中输入 :w !sudo tee %,按回车键后,当前缓冲区的内容会被传递给 sudo tee % 命令,tee 会以超级用户权限将内容写入当前文件。

3. 简化操作

为了方便使用这个技巧,可以在 .vimrc 文件中添加以下映射:

1
2
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

添加后,在 Vim 中只需输入 :w!! 即可实现以超级用户权限保存文件。

核心代码

.vimrc 中添加映射

1
2
3
4
" 静默版本
cnoremap W!! execute 'silent! write !sudo /usr/bin/tee \"%\" >/dev/null' <bar> edit!
" 非静默版本
cmap w!! w !sudo /usr/bin/tee >/dev/null \"%\"

Neovim 配置

1
cmap w!! :w !sudo -A tee % 2>/dev/null<CR>

同时,需要在 .zshrc.bashrc 或 fish 配置文件中设置环境变量:

  • Fishset -x SUDO_ASKPASS (which ssh-askpass)
  • Bash 和 Z shellexport SUDO_ASKPASS=$(which ssh-askpass)

最佳实践

  • 避免标准输出干扰:在命令中使用 > /dev/null 可以丢弃 tee 命令的标准输出,避免不必要的信息显示。
  • 使用全路径:在映射中指定 tee 的全路径,如 /usr/bin/tee,可以减轻路径修改攻击的风险。
  • 区分静默和非静默版本:根据需要选择使用 W!!(静默版本)或 w!!(非静默版本)。非静默版本在保存文件后会提示选择 [O]k[L]oad,而静默版本则不会有此提示。

常见问题

1. w!! 无法扩展

如果在输入 wW 后,输入 !! 的速度过慢,可能会出现 E492: Not an editor command: W!! 错误。此时需要快速输入 !! 并按回车键。

2. Neovim 中输入密码问题

在 Neovim 中,直接使用 :w !sudo tee % 可能会因为 shell 内联询问密码的问题而无法正常工作。可以使用 sudo -A 并结合 ssh-askpass 来解决,具体配置见上文核心代码部分。

3. 密码明文显示问题

如果使用 :w !sudo tee % <<< mypassword 这种方式,密码会以明文形式记录在 Vim 历史中,存在安全风险,不建议使用。


Vim “write with sudo”技巧的工作原理
https://119291.xyz/posts/vim-write-with-sudo-trick-explanation/
作者
ww
发布于
2025年5月27日
许可协议