通常在编辑配置文件时,我会用vi打开一个,然后当我保存它时,我意识到我没有输入
sudo vi filename
有没有办法给vi sudo特权来保存文件?我好像记得之前在查vi的时候看到过这个,但是现在找不到了。
通常在编辑配置文件时,我会用vi打开一个,然后当我保存它时,我意识到我没有输入
sudo vi filename
有没有办法给vi sudo特权来保存文件?我好像记得之前在查vi的时候看到过这个,但是现在找不到了。
当前回答
常见的警告
绕过只读文件问题的最常见方法是使用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'
可以缩写为:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
解释
:开始命令;您需要在普通模式下键入此字符以开始输入命令。在脚本中应该省略。
Sil [ent]抑制命令输出。在本例中,我们希望停止运行:!命令后出现的按任意键继续之类的提示符。命令。
Exec [ute]将字符串作为命令执行。我们不能只是run:write,因为它不会处理必要的函数调用。
! 表示:!Command::write唯一接受的命令。通常,:write接受要写入的文件路径。:! 在shell中运行命令(例如,使用bash -c)。使用:write,它将在shell中运行命令,然后将整个文件写入stdin。
Sudo应该是显而易见的,因为这就是你来这里的原因。以超级用户身份执行该命令。网上有很多关于这是如何运作的信息。
给定文件的t形管。:write将写入stdin,然后超级用户tee将接收文件内容并写入文件。它不会创建一个新文件——只是覆盖内容——因此文件模式和属性将被保留。
Shellescape()转义给定文件路径中的特殊字符,适用于当前shell。如果只有一个参数,它通常会在必要时用引号将路径括起来。由于我们要发送到一个完整的shell命令行,我们将希望传递一个非零值作为第二个参数,以启用其他特殊字符的反斜杠转义,否则可能会使shell出错。
@%读取%寄存器的内容,其中包含当前缓冲区的文件名。它不一定是一个绝对路径,所以请确保您没有更改当前目录。在某些解决方案中,您会看到commercial-at符号被省略。根据位置的不同,%是一个有效的表达式,与读取%寄存器具有相同的效果。嵌套在另一个表达式中的快捷方式通常是不允许的:例如在这种情况下。
>NUL and >/dev/null redirect stdout to the platform's null device. Even though we've silenced the command, we don't want all of the overhead associated with piping stdin back to vim--best to dump it as early as possible. NUL is the null device on DOS, MS-DOS, and Windows, not a valid file. As of Windows 8 redirections to NUL don't result in a file named NUL being written. Try creating a file on your desktop named NUL, with or without a file extension: you will be unable to do so. (There are several other device names in Windows that might be worth getting to know.)
~ / . 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
其他回答
一个快速谷歌似乎给出了这样的建议:
如果它是只读的,不要尝试编辑。 您可以更改文件的权限。(它是否能让你省钱取决于试验。) 如果你仍然编辑,保存到一个临时文件,然后移动它。
http://ubuntuforums.org/showthread.php?t=782136
这是另一个在回答这个问题后出现的插件,一个名为SudoEdit的插件,它提供SudoRead和SudoWrite函数,默认情况下将首先尝试使用sudo,如果失败则尝试使用su: http://www.vim.org/scripts/script.php?script_id=2709
一般来说,你不能改变vi进程的有效用户id,但是你可以这样做:
:w !sudo tee myfile
常见的警告
绕过只读文件问题的最常见方法是使用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'
可以缩写为:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
解释
:开始命令;您需要在普通模式下键入此字符以开始输入命令。在脚本中应该省略。
Sil [ent]抑制命令输出。在本例中,我们希望停止运行:!命令后出现的按任意键继续之类的提示符。命令。
Exec [ute]将字符串作为命令执行。我们不能只是run:write,因为它不会处理必要的函数调用。
! 表示:!Command::write唯一接受的命令。通常,:write接受要写入的文件路径。:! 在shell中运行命令(例如,使用bash -c)。使用:write,它将在shell中运行命令,然后将整个文件写入stdin。
Sudo应该是显而易见的,因为这就是你来这里的原因。以超级用户身份执行该命令。网上有很多关于这是如何运作的信息。
给定文件的t形管。:write将写入stdin,然后超级用户tee将接收文件内容并写入文件。它不会创建一个新文件——只是覆盖内容——因此文件模式和属性将被保留。
Shellescape()转义给定文件路径中的特殊字符,适用于当前shell。如果只有一个参数,它通常会在必要时用引号将路径括起来。由于我们要发送到一个完整的shell命令行,我们将希望传递一个非零值作为第二个参数,以启用其他特殊字符的反斜杠转义,否则可能会使shell出错。
@%读取%寄存器的内容,其中包含当前缓冲区的文件名。它不一定是一个绝对路径,所以请确保您没有更改当前目录。在某些解决方案中,您会看到commercial-at符号被省略。根据位置的不同,%是一个有效的表达式,与读取%寄存器具有相同的效果。嵌套在另一个表达式中的快捷方式通常是不允许的:例如在这种情况下。
>NUL and >/dev/null redirect stdout to the platform's null device. Even though we've silenced the command, we don't want all of the overhead associated with piping stdin back to vim--best to dump it as early as possible. NUL is the null device on DOS, MS-DOS, and Windows, not a valid file. As of Windows 8 redirections to NUL don't result in a file named NUL being written. Try creating a file on your desktop named NUL, with or without a file extension: you will be unable to do so. (There are several other device names in Windows that might be worth getting to know.)
~ / . 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
您可以考虑的一个快速hack是对正在编辑的文件执行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)
当然,我不建议在您担心安全性的系统中使用这种方法,因为在几秒钟内任何人都可以在您不知情的情况下读取/更改文件。