关于linux:获取vi内部文件的root权限?

关于linux:获取vi内部文件的root权限?

Getting root permissions on a file inside of vi?

通常在编辑配置文件时,我会用vi打开一个文件,然后在保存时意识到我没有输入

1
sudo vi filename

有什么办法赋予vi sudo特权来保存文件? 我似乎回想起不久前在查找有关vi的一些东西时看到了一些有关此内容的信息,但现在找不到了。


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

1
:w !sudo tee %

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

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

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

通过上面的命令,您可以键入:W保存文件。自从我写这篇文章以来,我发现了一种更好的方法(按照我的观点):

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

这样,您可以键入:w!!并将其扩展到完整的命令行,将光标保留在末尾,因此您可以根据需要使用自己的文件名替换%


通常,您无法更改vi进程的有效用户ID,但是可以执行以下操作:

1
:w !sudo tee myfile


常见警告

解决只读文件问题的最常见方法是使用sudo tee的实现以超级用户身份打开到当前文件的管道。但是,我在Internet上发现的所有最流行的解决方案都有以下几个潜在警告:

  • 整个文件以及文件都将写入终端。对于大文件,这可能会很慢,尤其是在网络连接速度慢的情况下。
  • 该文件丢失其模式和相似属性。
  • 带有不寻常字符或空格的文件路径可能无法正确处理。
  • 解决方案

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

    1
    2
    3
    4
    5
    " 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'

    这些可以缩短,敬请注意:

    1
    2
    :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,它将在外壳中运行命令,然后将整个文件写入stdin

    sudo应该很明显,因为这就是您在这里的原因。以超级用户身份运行命令。网上有很多有关其工作原理的信息。

    teestdin用管道传输到给定的文件。 :write将写入stdin,然后超级用户tee将接收文件内容并写入文件。它不会创建新文件-只会覆盖内容-因此将保留文件模式和属性。

    shellescape()在给定文件路径中转义适合当前shell的特殊字符。仅使用一个参数,通常会根据需要将路径括在引号中。由于我们要发送到完整的Shell命令行,因此,我们希望传递一个非零值作为第二个参数,以启用其他可能反跳外壳的特殊字符的反斜杠转义。

    @%读取%寄存器的内容,其中包含当前缓冲区的文件名。它不一定是绝对路径,因此请确保您没有更改当前目录。在某些解决方案中,您将看到省略商业广告符号。根据位置的不同,%是有效的表达式,其作用与读取%寄存器的作用相同。但是,嵌套在另一个表达式中的快捷方式通常是不允许的:例如在这种情况下。

    >NUL>/dev/nullstdout重定向到平台的空设备。即使我们已经沉默了该命令,我们也不希望将与stdin管道关联回vim的所有开销-最好尽早转储。 NUL是DOS,MS-DOS和Windows上的空设备,不是有效文件。从Windows 8开始,重定向到NUL不会导致写入名为NUL的文件。尝试在桌面上创建一个名为NUL的文件,带有或不带有文件扩展名:您将无法执行此操作。 (Windows中还有一些其他的设备名称可能值得了解。)

    的?/ .vimrc

    平台相关

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

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

    这将允许您键入:W(区分大小写)命令以具有超级用户权限写入当前文件-更加容易。

    平台无关

    我使用了与平台无关的~/.vimrc文件,该文件可在计算机之间进行同步,因此我添加了多平台功能。这是一个只有相关设置的~/.vimrc

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #!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的脚本。如果发现已打开需要超级用户权限才能读取的文件,请键入

    1
    :e sudo:%

    Vim将%替换为当前文件的名称,然后sudo:指示sudo.vim脚本接管进行读取和操作。写作。


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

    如果执行步骤2,请使用:w!强制写入文件。


    当您对文件进行插入模式时,需要使用sudo权限进行编辑,您会收到一条状态消息,提示您

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

    如果我想念那,我通常会

    1
    2
    :w ~/edited_blah.tmp
    :q

    ..然后..

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

    ..要么..

    1
    sudo mv edited_blah.tmp /etc/blah

    可能有一种不太绕行的方式来做到这一点,但它确实有效。


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


    快速的Google似乎提供了以下建议:

  • 如果它是只读的,请不要尝试编辑。
  • 您也许可以更改文件的权限。 (是否让您保存取决于实验。)
  • 如果仍要进行编辑,请保存到一个临时文件,然后将其移动。
  • http://ubuntuforums.org/showthread.php?t=782136


    我的?/ .bashrc中有这个:

    1
    alias svim='sudo vim'

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


    您可以考虑的一种快速破解方法是,对正在编辑的文件执行chmod,然后用vim保存,然后将chmod恢复为原来的文件。

    1
    2
    3
    4
    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)

    当然,我不建议在担心安全性的系统中使用这种方法,因为有几秒钟的时间,任何人都可以在不知不觉中读取/更改文件。


    推荐阅读