通常在编辑配置文件时,我会用vi打开一个,然后当我去保存它时意识到我没有输入
sudo vi filename
Run Code Online (Sandbox Code Playgroud)
有没有办法提供vi sudo权限来保存文件?我似乎记得在不久前查找关于vi的一些东西时看到了一些关于这个的东西,但现在我找不到了.
小智 290
% 被替换为当前文件名,因此您可以使用:
:w !sudo tee %
Run Code Online (Sandbox Code Playgroud)
(vim将检测到文件已被更改并询问您是否要重新加载.请选择[L]而不是确定.)
作为快捷方式,您可以定义自己的命令.将以下内容放入您的.vimrc:
command W w !sudo tee % >/dev/null
Run Code Online (Sandbox Code Playgroud)
使用上面的内容,您可以键入:W<Enter>以保存文件.自从我写这篇文章以来,我发现了一种更好的方式(在我看来):
cmap w!! w !sudo tee >/dev/null %
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以键入:w!!并将其扩展到完整的命令行,将光标留在末尾,这样您就可以替换%自己的文件名,如果您愿意的话.
Mar*_*son 32
通常,您无法更改vi进程的有效用户ID,但您可以这样做:
:w !sudo tee myfile
Run Code Online (Sandbox Code Playgroud)
Zen*_*xer 16
解决只读文件问题的最常用方法是使用实现的超级用户打开当前文件的管道sudo tee.但是,我在互联网上找到的所有最流行的解决方案都有几个潜在的警告:
要解决所有这些问题,可以使用以下命令:
" On POSIX (Linux/Mac/BSD):
:silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
" Depending on the implementation, you might need this on Windows:
:silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Run Code Online (Sandbox Code Playgroud)
这些可以恭敬地缩短:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Run Code Online (Sandbox Code Playgroud)
:开始命令; 您需要在正常模式下键入此字符才能开始输入命令.它应该在脚本中省略.
sil[ent]抑制命令的输出.在这种情况下,我们希望停止Press any key to continue在运行:!命令后出现的类似提示.
exec[ute]执行字符串作为命令.我们不能只运行:write因为它不会处理必要的函数调用.
!代表:!命令:唯一:write接受的命令.通常,:write接受要写入的文件路径. :!它自己在shell中运行一个命令(例如,使用bash -c).使用:write,它将在shell中运行命令,然后将整个文件写入stdin.
sudo应该是显而易见的,因为这就是你在这里的原因.以超级用户身份运行该命令.关于网络如何运作,有很多关于网络的信息.
tee管道stdin到给定文件. :write将写入stdin,然后超级用户tee将收到文件内容并写入文件.它不会创建新文件 - 只是覆盖内容 - 因此将保留文件模式和属性.
shellescape()转义给定文件路径中的特殊字符,以适合当前shell.只有一个参数,它通常只是根据需要将路径括在引号中.因为我们要发送一个完整的shell命令行,所以我们要传递一个非零值作为第二个参数,以启用反斜杠 - 转义其他可能会使shell绊倒的特殊字符.
@%读取%寄存器的内容,其中包含当前缓冲区的文件名.它不一定是绝对路径,因此请确保您没有更改当前目录.在某些解决方案中,您将看到省略了commercial-at符号.根据位置,%是一个有效的表达式,并具有与读取%寄存器相同的效果.嵌套在另一个表达式中,通常不允许使用快捷方式:例如在这种情况下.
>NUL并>/dev/null重定向stdout到平台的null设备.即使我们已经使命令静音,我们也不希望所有与管道相关的开销都stdin回到vim - 最好尽早转储它. NUL是DOS,MS-DOS和Windows上的空设备,而不是有效文件.从Windows 8到NUL的重定向不会导致写入名为NUL的文件.尝试在桌面上创建名为NUL的文件,无论是否有文件扩展名:您将无法执行此操作.(Windows中有其他几个设备名称可能值得了解.)
当然,您仍然不想记住这些并且每次都输入它们.将适当的命令映射到更简单的用户命令要容易得多.要在POSIX上执行此操作,您可以将以下行添加到您的~/.vimrc文件中,如果它尚不存在则创建它:
command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
Run Code Online (Sandbox Code Playgroud)
这将允许您键入:W(区分大小写)命令以使用超级用户权限编写当前文件 - 更容易.
我使用一个独立于平台的~/.vimrc文件,可以在计算机之间进行同步,因此我添加了多平台功能.这是一个~/.vimrc只有相关设置:
#!vim
" Use za (not a command; the keys) in normal mode to toggle a fold.
" META_COMMENT Modeline Definition: {{{1
" vim: ts=4 sw=4 sr sts=4 fdm=marker ff=unix fenc=utf-8
" ts: Actual tab character stops.
" sw: Indentation commands shift by this much.
" sr: Round existing indentation when using shift commands.
" sts: Virtual tab stops while using tab key.
" fdm: Folds are manually defined in file syntax.
" ff: Line endings should always be <NL> (line feed #09).
" fenc: Should always be UTF-8; #! must be first bytes, so no BOM.
" General Commands: User Ex commands. {{{1
command W call WriteAsSuperUser(@%) " Write file as super-user.
" Helper Functions: Used by user Ex commands. {{{1
function GetNullDevice() " Gets the path to the null device. {{{2
if filewritable('/dev/null')
return '/dev/null'
else
return 'NUL'
endif
endfunction
function WriteAsSuperUser(file) " Write buffer to a:file as the super user (on POSIX, root). {{{2
exec '%write !sudo tee ' . shellescape(a:file, 1) . ' >' . GetNullDevice()
endfunction
" }}}1
" EOF
Run Code Online (Sandbox Code Playgroud)
Ryan的建议一般都很好,但是,如果按照步骤3,不要移动临时文件; 它将拥有错误的所有权和权限.而是sudoedit正确的文件并读:r入临时文件的内容(使用等).
如果执行步骤2,则使用:w!强制写入文件.