Получение root-прав на файл внутри vi?
Вопрос
Часто при редактировании конфигурационных файлов я открываю один из них с помощью vi, а затем, когда я иду, чтобы сохранить его, понимаю, что я не вводил
sudo vi filename
Есть ли какой-нибудь способ предоставить vi права sudo для сохранения файла?Кажется, я припоминаю, что видел что-то по этому поводу, когда некоторое время назад просматривал кое-какие материалы о vi, но сейчас я не могу этого найти.
Решение
%
заменяется текущим именем файла, таким образом, вы можете использовать:
:w !sudo tee %
(vim
обнаружит, что файл был изменен, и спросит, хотите ли вы, чтобы он был перезагружен.Скажи "да", выбрав [L]
скорее, чем нормально.)
В качестве ярлыка вы можете определить свою собственную команду.Внесите в свой .vimrc
:
command W w !sudo tee % >/dev/null
Используя вышесказанное, вы можете ввести :W<Enter>
чтобы сохранить файл.С тех пор как я написал это, я нашел более приятный способ (на мой взгляд) сделать это:
cmap w!! w !sudo tee >/dev/null %
Таким образом, вы можете ввести :w!!
и он будет расширен до полной командной строки, оставив курсор в конце, чтобы вы могли заменить %
с вашим собственным именем файла, если хотите.
Другие советы
Как правило, вы не можете изменить действующий идентификатор пользователя процесса vi, но вы можете сделать это:
: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]
подавляет вывод команды.В этом случае мы хотим остановить Press any key to continue
-подобное приглашение, которое появляется после запуска :!
команда.
exec[ute]
выполняет строку в виде команды.Мы не можем просто сбежать :write
потому что он не обработает необходимый вызов функции.
!
представляет собой :!
команда:единственная команда , которая :write
принимает.Обычно, :write
принимает путь к файлу, в который требуется записать. :!
сам по себе запускает команду в командной оболочке (например, используя bash -c
).С :write
, он запустит команду в командной оболочке, а затем запишет весь файл в stdin
.
sudo
это должно быть очевидно, поскольку именно поэтому вы здесь.Запустите команду от имени суперпользователя.В сети есть много информации о том, как это работает.
tee
трубы stdin
к данному файлу. :write
напишу по адресу stdin
, затем суперпользователь tee
получит содержимое файла и запишет файл.Он не создаст новый файл - просто перезапишет содержимое, поэтому режимы и атрибуты файла будут сохранены.
shellescape()
экранирует специальные символы в заданном пути к файлу в соответствии с текущей командной оболочкой.Имея только один параметр, он обычно просто заключает путь в кавычки по мере необходимости.Поскольку мы отправляем в командную строку полной оболочки, мы захотим передать ненулевое значение в качестве второго аргумента, чтобы включить экранирование обратной косой черты других специальных символов, которые в противном случае могли бы сбить с толку оболочку.
@%
считывает содержимое %
регистр, который содержит имя файла текущего буфера.Это не обязательно абсолютный путь, поэтому убедитесь, что вы не изменили текущий каталог.В некоторых решениях вы увидите, что символ 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
Совет Райана, как правило, хорош, однако, если вы выполните шаг 3, не перемещайте временный файл;у него будут неправильные права собственности и разрешения.Вместо этого, sudoedit
выберите правильный файл и прочтите его содержимое (используя :r
или что-то подобное) временного файла.
При выполнении шага 2 используйте :w!
чтобы принудительно записать файл.
Когда вы переходите в режим вставки файла, для редактирования которого вам нужен доступ 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
Вероятно, есть менее окольный способ сделать это, но он работает.
Быстрый поиск в Google, кажется, дает такой совет:
- Не пытайтесь редактировать, если оно доступно только для чтения.
- Возможно, вы сможете изменить права доступа к файлу.(Позволит ли это вам сэкономить или нет, зависит от экспериментов.)
- Если вы все равно что-то редактировали, сохраните во временный файл, а затем переместите его.
Вот еще один, который появился с тех пор, как был дан ответ на этот вопрос, плагин под названием SudoEdit, который предоставляет функции SudoRead и SudoWrite, которые по умолчанию сначала попытаются использовать sudo и su, если это не удастся: http://www.vim.org/scripts/script.php?script_id=2709
У меня есть это в моем ~/.bashrc:
alias svim='sudo vim'
Теперь всякий раз, когда мне нужно отредактировать конфигурационный файл, я просто открываю его с помощью svim.
Быстрый способ, который вы можете рассмотреть, - это выполнить 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)
Конечно, я не рекомендую такой подход в системе, где вы беспокоитесь о безопасности, поскольку в течение нескольких секунд любой может прочитать / изменить файл без вашего ведома.
использование гксудо вместо того, чтобы sudo для GVim , т. е.
cmap w!! w !gksudo tee >/dev/null %