Многие из вас, вероятно, видели команду, которая позволяет вам писать в файле, для которого требуется разрешение root, даже если вы забыли открыть vim с помощью sudo:
: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 Может ли кто-нибудь помочь мне разобрать эту команду?
:w !sudo cat > %
будет работать, а не загрязнять стандартный вывод?sudo
применяется кcat
, но не к>
, поэтому не допускается. Можно попробовать запустить всю команду в подоболочке sudo, например:w !sudo sh -c "cat % > yams.txt"
, но это тоже не сработает, потому что в подоболочке%
- ноль; вы удалите содержимое вашего файла.:w !sudo sh -c "cat >%"
самом деле работает так же хорошо, как иsudo tee %
потому, что Vim заменяет имя файла%
до того, как оно попадет в подоболочку. Однако ни один из них не работает, если в имени файла есть пробелы; Вы должны сделать:w !sudo sh -c "cat >'%'"
или:w !sudo tee "%"
исправить это.Ответы:
В
:w !sudo tee %
...%
означает "текущий файл"Как указал Евгений У ,
%
действительно означает «текущее имя файла», которое передается, чтобыtee
он знал, какой файл перезаписать.(В командах замещения, он немного отличается, поскольку
:help :%
показывает, что этоequal to 1,$ (the entire file)
(спасибо @Orafu для указывая на то , что это не оценивает к имени файла) Например,.:%s/foo/bar
Означает « в текущем файле , заменить вхожденияfoo
сbar
.» Если вы выделите Перед тем как набрать текст:s
, вы увидите, что выделенные строки%
заменяют ваш диапазон замещения.):w
не обновляет ваш файлОдна из запутанных частей этого трюка заключается в том, что вы можете подумать, что
:w
изменяете файл, но это не так. Если вы открыли и изменилиfile1.txt
, а затем запустили:w file2.txt
, это будет «сохранить как»;file1.txt
не будет изменен, но текущее содержимое буфера будет отправленоfile2.txt
.Вместо этого
file2.txt
вы можете заменить команду оболочки на получение содержимого буфера . Например,:w !cat
будет просто отображать содержимое.Если Vim не запускался с доступом sudo, он
:w
не может изменить защищенный файл, но если он передает содержимое буфера в оболочку, команду в оболочке можно запустить с помощью sudo . В этом случае мы используемtee
.Понимание тройника
Что касается
tee
, представьтеtee
команду как Т-образную трубу в обычной ситуации bash-трубопровода: она направляет вывод в указанный файл (-ы), а также отправляет его на стандартный вывод , который может быть захвачен следующей командой-конвейером.Например, в
ps -ax | tee processes.txt | grep 'foo'
, список процессов будет записан в текстовый файл и передан вgrep
.(Диаграмма, созданная с помощью Asciiflow .)
Смотрите
tee
man-страницу для получения дополнительной информации.Ти как взломать
В ситуации, описанной вашим вопросом, использование
tee
- это хак, потому что мы игнорируем половину того, что он делает .sudo tee
записывает в наш файл, а также отправляет содержимое буфера на стандартный вывод, но мы игнорируем стандартный вывод . В этом случае нам не нужно ничего передавать другой переданной команде; мы просто используемtee
как альтернативный способ записи файла, чтобы мы могли вызывать его с помощьюsudo
.Сделать этот трюк легко
Вы можете добавить это к своему,
.vimrc
чтобы сделать этот трюк простым в использовании: просто введите:w!!
.Эта
> /dev/null
часть явно отбрасывает стандартный вывод, поскольку, как я уже сказал, нам не нужно ничего передавать другой переданной команде.источник
tee
для его способности писать стандартный ввод в файл. Я удивлен, что нет программы, работа которой заключается в том, чтобы сделать это (я нашел программу, о которой я никогда не слышал,sponge
которая вызывает это). Я предполагаю, что типичное «записать поток в файл» выполняется встроенной оболочкой. Разве Vim!{cmd}
не разветвляется (cmd
вместо этого разветвляется )? Возможно, что-то более очевидное - использовать какой-то рабочий вариант,sh -c ">"
а неtee
.sponge
является частьюmoreutils
пакета почти во всех дистрибутивах, кроме дистрибутивов на основе Debian.moreutils
имеет довольно хорошие инструменты, которые находятся на одном уровне с более распространенными инструментами, такими какxargs
иtee
.cat
выполняется от имени пользователя root, а вывод перенаправляется оболочкой, которая не запускается от имени пользователя root. Это так же, какecho hi > /read/only/file
.В выполненной командной строке
%
обозначает текущее имя файла . Это задокументировано в:help cmdline-special
:Как вы уже узнали,
:w !cmd
передает содержимое текущего буфера в другую команду. Чтоtee
означает копирование стандартного ввода в один или несколько файлов, а также в стандартный вывод. Следовательно,:w !sudo tee % > /dev/null
эффективно записывает содержимое текущего буфера в текущий файл , будучи корневым . Еще одна команда, которая может быть использована для этогоdd
:В качестве ярлыка вы можете добавить это сопоставление к вашему
.vimrc
:С помощью вышеупомянутого вы можете напечатать,
:w!!<Enter>
чтобы сохранить файл как root.источник
:help _%
поднимает то, что вы ввели, но:help %
поднимает ключ соответствия скобок. Я бы не подумал попробовать префикс подчеркивания, это какой-то шаблон в документации vim? Есть ли какие-то «особые» вещи, которые стоит попробовать при поиске помощи?help
команда переходит на тег. Вы можете увидеть доступные теги с:h help-tags
. Вы также можете использовать завершение командной строки, чтобы увидеть совпадающие теги::h cmdline<Ctrl-D>
(или,:h cmdline<Tab>
если вы установилиwildmode
соответственно)cmap w!! w !sudo tee % > /dev/null
в моем файле .vimrc, чтобы сделать эту работу. Является%
неуместны в ответе выше? (Здесь нет эксперта по vim.)sudo tee > /dev/null /path/to/current/file
что на самом деле не имеет смысла. (Собирается редактировать это)Это также хорошо работает:
Это вдохновлено комментарием @Nathan Long.
УВЕДОМЛЕНИЕ :
"
должен использоваться вместо того,'
потому что мы хотим%
быть расширенными перед передачей в оболочку.источник
tee
на,/usr/bin/tee
чтобы предотвратить атаки с изменением PATH.:w
- Написать файл.!sudo
- Вызвать команду оболочки sudo.tee
- Вывод команды write (vim: w) перенаправлен с использованием tee. % - это не что иное, как текущее имя файла, т.е. /etc/apache2/conf.d/mediawiki.conf. Другими словами, команда tee запускается от имени пользователя root и принимает стандартный ввод и записывает его в файл, представленный%. Однако, это побудит перезагрузить файл снова (нажмите L, чтобы загрузить изменения в самом vim):учебная ссылка
источник
Принятый ответ охватывает все, поэтому я приведу еще один пример ярлыка, который я использую для записи.
Добавьте его к своему
etc/vim/vimrc
(или~/.vimrc
):cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Куда:
cnoremap
: сообщает vim, что следующий ярлык должен быть связан с командной строкой.w!!
: сам ярлыкexecute '...'
: команда, которая выполняет следующую строку.silent!
: беги молчаwrite !sudo tee % >/dev/null
: вопрос ОП, добавлено перенаправление сообщений,NULL
чтобы сделать чистую команду<bar> edit!
Этот трюк - самая лучшая вещь: он также вызываетedit
команду для перезагрузки буфера, а затем избегает сообщений, таких как изменение буфера .<bar>
как написать символ канала для разделения двух команд здесь.Надеюсь, поможет. Смотрите также для других проблем:
источник
Я хотел бы предложить другой подход к проблеме "Упс, которую я забыл написать
sudo
при открытии моего файла" :Вместо того, чтобы получать
permission denied
и вводить:w!!
, я считаю более элегантным иметь условнуюvim
команду, которая работает,sudo vim
если владельцем файла являетсяroot
.Это так же просто реализовать (могут быть даже более элегантные реализации, я явно не баш-гуру):
И это работает очень хорошо.
Это более
bash
ориентированный подход, чемvim
один, поэтому не всем он может понравиться.Конечно:
root
но требуетsudo
, но функция может быть отредактирована в любом случае)vim
файла только для чтения (насколько я понимаю, я используюtail
илиcat
для небольших файлов)Но я нахожу, что это дает гораздо лучший опыт для разработчиков , что IMHO, как правило, забывают при использовании
bash
. :-)источник
root
запрашивается пароль.ДЛЯ НЕОВИМ
Из-за проблем с интерактивными вызовами ( https://github.com/neovim/neovim/issues/1716 ) я использую это для neovim, основываясь на ответе доктора Беко:
Откроется диалоговое окно с использованием
ssh-askpass
запроса пароля sudo.источник