252

通常在编辑配置文件时,我会用 vi 打开一个,然后当我去保存它时发现我没有输入

sudo vi filename

有没有办法给 vi sudo 权限来保存文件?我似乎记得不久前在查找有关 vi 的一些内容时看到了一些关于此的内容,但现在我找不到它。

4

10 回答 10

306

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

:w !sudo tee %

vim将检测到文件已被更改并询问您是否要重新加载它。通过选择[L]而不是 OK 说是。)

作为快捷方式,您可以定义自己的命令。将以下内容放入您的.vimrc:

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

使用上述内容,您可以键入:W<Enter>以保存文件。自从我写了这个,我找到了一个更好的方法(在我看来)来做到这一点:

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

这样你可以输入:w!!,它会被扩展为完整的命令行,把光标留在最后,所以你可以用%你自己的文件名替换,如果你喜欢。

于 2008-08-31T19:23:48.347 回答
33

一般来说,你不能改变vi进程的有效用户id,但是你可以这样做:

:w !sudo tee myfile
于 2008-08-04T06:52:32.270 回答
19

常见注意事项

解决只读文件问题的最常见方法是使用sudo tee. 但是,我在 Internet 上找到的所有最流行的解决方案都有几个潜在的警告:

  • 整个文件以及文件都被写入终端。这对于大文件可能会很慢,尤其是在网络连接速度较慢的情况下。
  • 该文件将失去其模式和类似属性。
  • 可能无法正确处理包含异常字符或空格的文件路径。

解决方案

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

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

解释

:开始命令;您需要在正常模式下键入此字符才能开始输入命令。它应该在脚本中省略。

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到平台的空设备。尽管我们已经使命令静音,但我们不希望所有与管道stdin返回 vim 相关的开销——最好尽早转储它。 NUL是 DOS、MS-DOS 和 Windows 上的空设备,不是有效文件。从 Windows 8 开始,重定向到 NUL 不会导致写入名为 NUL 的文件。尝试在您的桌面上创建一个名为 NUL 的文件,带或不带文件扩展名:您将无法这样做。(Windows 中还有其他几个可能值得了解的设备名称。)

~/.vimrc

平台相关

当然,您仍然不想记住这些并每次都输入它们。将适当的命令映射到更简单的用户命令要容易得多。要在 POSIX 上执行此操作,您可以将以下行添加到您的~/.vimrc文件中,如果它不存在则创建它:

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

这将允许您键入 :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
于 2012-10-13T06:54:18.770 回答
11

如果您使用的是Vim,则有一个名为sudo.vim的脚本可用。如果您发现您打开了一个需要 root 访问权限才能读取的文件,请键入

:e 须藤:%
Vim 将 % 替换为当前文件的名称,并sudo:指示 sudo.vim 脚本接管读取和写入。

于 2008-09-24T04:12:25.080 回答
7

Ryan 的建议通常是好的,但是,如果遵循第 3 步,请不要移动临时文件;它将拥有错误的所有权和权限。相反,sudoedit正确的文件并读入:r临时文件的内容(使用等)。

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

于 2008-08-04T04:04:52.110 回答
3

当您进入需要 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

可能有一种不那么迂回的方法,但它确实有效。

于 2008-08-12T18:37:53.133 回答
1

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

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

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

于 2008-08-04T03:39:31.163 回答
1

这是自回答此问题以来出现的另一个插件,一个名为 SudoEdit 的插件,它提供 SudoRead 和 SudoWrite 功能,默认情况下,它将首先尝试使用 sudo,如果失败,则使用 su:http: //www.vim.org/scripts/ script.php?script_id=2709

于 2010-01-29T17:21:29.890 回答
0

我的 ~/.bashrc 中有这个:

alias svim='sudo vim'

现在每当我需要编辑配置文件时,我只需用 svim 打开它。

于 2009-03-19T12:51:48.797 回答
-2

您可以考虑的一个快速破解方法是对您正在编辑的文件执行 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)

当然,我不建议在您担心安全性的系统中使用这种方法,因为几秒钟内任何人都可以在您没有意识到的情况下读取/更改文件。

于 2008-08-05T22:20:58.403 回答