当前位置:  开发笔记 > 编程语言 > 正文

vim"用sudo写"技巧如何工作?

如何解决《vim"用sudo写"技巧如何工作?》经验,为你挑选了6个好方法。

很多人可能已经看到了允许你在需要root权限的文件上写的命令,即使你忘了用sudo打开vim:

:w !sudo tee %

问题是我不知道这里到底发生了什么.

我已经想到了这个: w是为了这个

                                                        *:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
                        Execute {cmd} with [range] lines as standard input
                        (note the space in front of the '!').  {cmd} is
                        executed like with ":!{cmd}", any '!' is replaced with
                        the previous command |:!|.

所以它将所有行作为标准输入传递.

!sudo tee部件tee使用管理员权限调用.

为了让所有人有意义,%应输出文件名(作为参数tee),但我找不到有关此行为的帮助的参考.

tl; dr有人可以帮我剖析这个命令吗?



1> Nathan Long..:

:w !sudo tee %......

% 表示"当前文件"

正如eugene指出的那样,%确实意味着"当前的文件名".Vim中的另一个用途是替换命令.例如,tee表示" 在当前文件中,替换:help :%with的出现次数" equal to 1,$ (the entire file).如果在键入之前突出显示某些文本:%s/foo/bar,您会看到突出显示的行代替了foo替换范围.

bar 没有更新您的文件

这个技巧的一个令人困惑的部分是你可能认为:s正在修改你的文件,但事实并非如此.如果你打开并修改%,然后运行:w,它将是"另存为"; :w不会被修改,但会将当前缓冲区内容发送给file1.txt.

:w file2.txt您可以替换shell命令来接收缓冲区内容,而不是.例如,file1.txt只显示内容.

如果Vim没有使用sudo访问运行,则它file2.txt无法修改受保护的文件,但如果它将缓冲区内容传递给shell,可以使用sudo运行shell 中的命令.在这种情况下,我们使用file2.txt.

了解发球台

至于在正常的bash管道情况下:w !cat:w命令描述为T形管道:它将输出定向到指定的文件,并将其发送到标准输出,可以通过下一个管道命令捕获.

例如,在tee进程中,进程列表将被写入文本文件传递给tee.

     +-----------+    tee     +------------+
     |           |  --------  |            |
     | ps -ax    |  --------  | grep 'foo' |
     |           |     ||     |            |
     +-----------+     ||     +------------+
                       ||   
               +---------------+
               |               |
               | processes.txt |
               |               |
               +---------------+

(使用Asciiflow创建的图表.)

有关详细信息,请参见tee手册页.

发球作为一个黑客

在你的问题描述的情况下,使用ps -ax | tee processes.txt | grep 'foo'是一个黑客,因为我们忽略了它的一半.grep写入我们的文件并将缓冲区内容发送到标准输出,但我们忽略标准输出.在这种情况下,我们不需要将任何内容传递给另一个管道命令; 我们只是tee用作编写文件的替代方式,以便我们可以调用它tee.

让这个技巧变得容易

您可以将此添加到您的使用,sudo tee以使这个技巧易于使用:只需键入tee.

" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

sudo部分明确地抛弃了标准输出,因为正如我所说,我们不需要将任何东西传递给另一个管道命令.


特别喜欢你的符号"w !!" 使用"sudo !!"后很容易记住 在命令行上.
所以这使用`tee`来将stdin写入文件.我很惊讶没有一个程序可以做到这一点(我发现了一个我从来没有听说过的程序叫做"海绵"这样做).我想典型的"写一个文件流"是由内置的shell执行的.Vim的`!{cmd}`不会分叉shell(代替'cmd`)?也许更明显的一点是使用`sh -c">"`而不是`tee`的一些工作变体.
如何扩展此别名也告诉vim自动将更改的文件内容加载到当前缓冲区?它问我,它如何自动化?
@ user247077:在这种情况下,`cat`以root身份运行,输出由shell重定向,而shell不以root身份运行.它与`echo hi>/read/only/file`相同.
我想知道为什么:w!sudo cat>%不起作用呢?
@Steven Lu:`sponge`是除了基于Debian的发行版之外几乎所有发行版的`moreutils`包的一部分.`moreutils`有一些非常好的工具,与更常见的工具如`xargs`和`tee`相同.

2> Eugene Yarma..:

在执行的命令行中,%代表当前文件名.这记录在:help cmdline-special:

In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
        %       Is replaced with the current file name.

正如您已经发现的那样,:w !cmd将当前缓冲区的内容传递给另一个命令.什么tee是将标准输入复制到一个或多个文件,以及标准输出.因此,在root时:w !sudo tee % > /dev/null有效地将当前缓冲区的内容写入当前文件.可用于此的另一个命令是:dd

:w !sudo dd of=% > /dev/null

作为快捷方式,您可以将此映射添加到您的.vimrc:

" Force saving files that require root permission 
cnoremap w!! w !sudo tee > /dev/null %

使用上面的内容,您可以键入:w!!以root身份保存文件.


@David:`help`命令跳转到标签.您可以使用`:h help-tags`查看可用的标签.您还可以使用命令行完成来查看匹配的标记:`:h cmdline `(或`:h cmdline `如果您相应地设置`wildmode`)

3> feihu..:

这也很有效:

:w !sudo sh -c "cat > %"

这是受@Nathan Long评论的启发.

通知:

"必须使用而不是'因为我们希望%在传递给shell之前进行扩展.


虽然这可能有效,但它也可以让sudo访问多个程序(sh和cat).通过用`/ usr/bin/tee`替换`tee`以防止PATH修改攻击,其他示例可以更安全.

4> kev..:

:w - 写一个文件.

!sudo - 调用shell sudo命令.

tee - 使用tee重定向的write(vim:w)命令的输出.%只是当前文件名,即/etc/apache2/conf.d/mediawiki.conf.换句话说,tee命令以root身份运行,它接受标准输入并将其写入由%表示的文件.但是,这将提示再次重新加载文件(点击L加载vim本身的更改):

教程链接



5> Dr Beco..:

可接受的答案涵盖了所有内容,因此,我仅举一个记录所使用的快捷方式的示例。

将其添加到您的etc/vim/vimrc(或~/.vimrc)中:

cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' edit!

哪里:

cnoremap:告诉vim在命令行中要关联以下快捷方式。

w!!:快捷方式本身。

execute '...':执行以下字符串的命令。

silent!:静默运行

write !sudo tee % >/dev/null:OP问题,添加了消息重定向NULL以发出干净命令

edit!:这个技巧是轻而易举的事情:它还调用edit命令以重新加载缓冲区,然后避免诸如缓冲区已更改的消息。这里是如何编写管道符号以分隔两个命令的方法。

希望能帮助到你。另请参阅其他问题:

超级用户:强制vim写入文件



6> Augustin Rie..:

我想提出另一种方法来解决sudo打开文件时忘记写的操作”问题:

我发现有一个条件命令(如果文件所有者为的话)可以代替它permission denied,而不是必须输入。:w!!vimsudo vimroot

这很容易实现(甚至可能会有更优雅的实现,我显然不是bash专家):

function vim(){
  OWNER=$(stat -c '%U' $1)
  if [[ "$OWNER" == "root" ]]; then
    sudo /usr/bin/vim $*;
  else
    /usr/bin/vim $*;
  fi
}

而且效果很好。

这是一种bashvim- 更加集中的方法,因此并非每个人都喜欢它。

当然:

在某些情况下它会失败(当文件所有者不是root但需要时sudo,但该功能仍可以编辑)

vim用于只读文件时没有任何意义(就我而言,我使用的tail还是cat小文件)

但是我发现这带来了更好的开发用户体验,而IMHO在使用时往往会被遗忘bash。:-)


只是要知道,这要少得多。就我个人而言,我的大多数错误都是愚蠢的错误。因此,当我做一些既愚蠢又重要的事情时,我宁愿提神。这当然是一个优先事项,但是特权升级被认为是一种出于良心的行为。另外:如果您经常遇到这种情况,以至于使“:w !!” 足以自动静默sudo的麻烦(但仅在owner = root时);您可能需要检查当前的工作流程。
推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有