在vi的文件中获得root权限?

经常在编辑configuration文件的时候,我会用vi打开一个,然后当我去保存时意识到我没有input

sudo vi filename 

有没有办法让vi sudo权限保存文件? 我好像回想起前面看到关于vi的一些东西,但是现在我找不到它了。

%被replace为当前文件名,因此您可以使用:

 :w !sudo tee % 

vim会检测到文件已经被更改,并询问是否要重新加载它。)

作为一个捷径,你可以定义你自己的命令。 将以下内容放在.vimrc

 command W w !sudo tee % >/dev/null 

用上面的命令可以input:W<Enter>保存文件。 自从我写这篇文章以来,我发现了一个更好的方法(在我看来)这样做:

 cmap w!! w !sudo tee >/dev/null % 

这样你可以input:w!! 并将其扩展到完整的命令行,将光标留在最后,所以如果你喜欢,你可以用你自己的文件名replace%

一般来说,您不能更改vi进程的有效用户标识,但您可以这样做:

 :w !sudo tee myfile 

常见的警告

解决只读文件问题的最常见方法是使用sudo tee的实现以超级用户的身份打开一个到当前文件的pipe道。 不过,我在互联网上find的所有最stream行的解决scheme都有几个潜在的注意事项:

  • 整个文件被写入terminal,以及文件。 对于大文件,这可能会很慢,特别是在慢速networking连接上。
  • 该文件失去其模式和类似的属性。
  • 不正常的字符或空格文件path可能无法正确处理。

解决scheme

为了解决所有这些问题,您可以使用以下命令:

 " 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' 

这些可以缩短,恭敬地:

 :sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null' :sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL' 

说明

:开始命令; 您将需要在正常模式下input此字符以开始input命令。 在脚本中应该省略。

sil[ent]禁止从命令输出。 在这种情况下,我们要停止Press any key to continue – 如运行后出现提示:! 命令。

exec[ute]执行一个string作为命令。 我们不能只运行:write因为它不会处理必要的函数调用。

! 代表:! 命令:唯一的命令:write接受。 通常情况下, :write接受要写入的文件path。 :! 它自己在shell中运行一个命令(例如,使用bash -c )。 使用:write ,它将在shell中运行命令,然后将整个文件写入stdin

sudo应该很明显,因为这就是你来这里的原因。 以超级用户身份运行该命令。 networking上有很多关于如何工作的信息。

teepipe道stdin到给定的文件。 :write将写入stdin ,然后超级用户将会收到文件内容并写入文件。 它不会创build一个新的文件 – 只是覆盖内容 – 所以文件模式和属性将被保留。

shellescape()根据当前shell的情况,在给定文件path中转义特殊字符。 仅使用一个参数,通常只需将引号括起来。 由于我们正在发送一个完整的shell命令行,所以我们需要传递一个非零值作为第二个参数来启用其他特殊字符的反斜杠转义。

@%读取包含当前缓冲区文件名的%寄存器的内容。 这不一定是绝对path,所以确保你没有改变当前的目录。 在某些解决scheme中,您将看到省略的商用符号。 取决于位置, %是一个有效的expression式,与读取%寄存器的效果相同。 嵌套在另一个expression式中的快捷方式通常是不允许的,例如在这种情况下。

>NUL>/dev/nullstdoutredirect到平台的空设备。 尽pipe我们已经放弃了这个命令,但是我们并不希望把所有的stdinpipe道连接到vim,尽可能早的把它转储出来。 NUL是DOS,MS-DOS和Windows上的空设备,而不是有效的文件。 从Windows 8redirect到NUL不会导致写入名为NUL的文件。 尝试在名为NUL的桌面上创build文件,文件扩展名可以不带或不带文件扩展名:您将无法这样做。 (Windows中还有其他几个设备名称可能值得了解。)

的〜/ .vimrc

平台相关

当然,你还是不想记住这些,每次input。 将适当的命令映射到更简单的用户命令要容易得多。 要在POSIX上执行此操作,可以~/.vimrc添加到~/.vimrc文件中,如果它尚不存在,请创build它:

 command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null' 

这将允许您input:W(区分大小写)命令来以超级用户权限写入当前文件 – 要容易得多。

平台无关

我使用一个独立于平台的~/.vimrc文件来跨计算机同步,所以我添加了多平台function。 这是一个~/.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 

如果你使用的是Vim ,有一个名为sudo.vim的脚本。 如果你发现你打开了一个你需要root权限的文件来读取,请input

  :e sudo:% 

Vim将当前文件的名称replace为%, sudo:指示sudo.vim脚本接pipe读取和写入。

Ryan的build议总的来说不错,但是,如果按照步骤3,不要移动临时文件; 它将拥有错误的所有权和权限。 相反, sudoedit正确的文件,并读取临时文件的内容(使用:r等)。

如果按照步骤2,使用:w! 强制文件被写入。

当你进入插入模式的文件,你需要sudo访问编辑,你会得到一个状态消息说

 -- INSERT -- W10: Warning: Changing a readonly file 

如果我错过了,一般我都会

 :w ~/edited_blah.tmp :q 

..然后..

 sudo "cat edited_blah.tmp > /etc/blah" 

..要么..

 sudo mv edited_blah.tmp /etc/blah 

这可能不是一个迂回的方法,但它的工作原理。

一个快速的谷歌似乎给了这个build议:

  1. 如果它是只读的,不要尝试编辑。
  2. 您可能可以更改文件的权限。 (它是否让你保存取决于实验。)
  3. 如果你仍然编辑,保存到一个临时文件,然后移动它。

http://ubuntuforums.org/showthread.php?t=782136

这是另外一个自从这个问题得到解答之后出现的一个叫做SudoEdit的插件,它提供了SudoRead和SudoWrite函数,默认情况下会先尝试使用sudo,如果失败则使用su: http : //www.vim.org/scripts/ script.php的?SCRIPT_ID = 2709

我在〜/ .bashrc中有这个:

 alias svim='sudo vim' 

现在每当我需要编辑一个configuration文件,我只是用svim打开它。

你可以考虑快速入门,就是对正在编辑的文件做一个chmod,用vim保存,然后chmod回到原来的文件。

 ls -l test.file (to see the permissions of the file) chmod 777 test.file [This is where you save in vim] chmod xxx test.file (restore the permissions you found in the first step) 

当然,我不推荐这种方法在你担心安全的系统中,因为几秒钟之后,任何人都可以在不知道的情况下读取/更改文件。

使用gksudo,而不是sudo ,即GVim

 cmap w!! w !gksudo tee >/dev/null %