Часто при редактировании конфигурационных файлов я открываю один с помощью vi, а затем, когда иду, чтобы сохранить его, понимает, что я не печатал
sudo vi filename
Есть ли способ дать привилегии vi sudo для сохранения файла? Кажется, я вспомнил, что видел что-то об этом, когда искал кое-что о vi некоторое время назад, но сейчас я не могу его найти.
%
заменяется текущим именем файла, поэтому вы можете использовать:
:w !sudo tee %
( vim
обнаружит, что файл был изменен и спросит, хотите ли вы, чтобы он был перезагружен. Скажите да, выбрав, [L]
а не OK.)
В качестве ярлыка вы можете определить свою собственную команду. Поместите следующее в свой .vimrc
:
command W w !sudo tee % >/dev/null
С вышеупомянутым вы можете напечатать, :W<Enter>
чтобы сохранить файл. Так как я написал это, я нашел более хороший способ (по моему мнению) сделать это:
cmap w!! w !sudo tee >/dev/null %
Таким образом, вы можете ввести текст, :w!!
и он будет расширен до полной командной строки, оставив курсор в конце, так что вы можете заменить %
его именем файла, если хотите.
sudo: 1 incorrect password attempt
/etc/sudoers
файл, добавить его your_username ALL=(ALL) ALL
под строкой root ALL=(ALL) ALL
, выйти и сохранить. visudo
. В общем, вы не можете изменить эффективный идентификатор пользователя процесса vi, но вы можете сделать это:
:w !sudo tee myfile
:w !sudo tee % >/dev/null
или :w !sudo dd of=%
избегайте повторного отображения содержимого файла при сохранении файла. tee
и увидел, что это команда канала Unix, и !
вставил команду оболочки. Является ли :w
написание к стандарту, который получает по каналу tee
? Общие предостережения
Наиболее распространенный способ обойти проблему файла, доступного только для чтения, - открыть канал для текущего файла в качестве суперпользователя, используя реализацию 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
приглашение -like, которое появляется после запуска :!
команды.
exec[ute]
выполняет строку как команду. Мы не можем просто запустить, :write
потому что он не будет обрабатывать необходимый вызов функции.
!
представляет :!
команду: единственная команда, которая :write
принимает. Обычно :write
принимает путь к файлу для записи. :!
Сам по себе запускает команду в оболочке (например, используя bash -c
). С помощью :write
он запустит команду в оболочке, а затем запишет весь файл в stdin
.
sudo
должно быть очевидно, потому что именно поэтому ты здесь. Запустите команду как суперпользователь. В сети есть много информации о том, как это работает.
tee
трубы stdin
к данному файлу. :write
напишет stdin
, затем суперпользователь tee
получит содержимое файла и запишет файл. Он не будет создавать новый файл - просто перезаписать содержимое - таким образом, режимы и атрибуты файла будут сохранены.
shellescape()
экранирует специальные символы в указанном пути к файлу в зависимости от текущей оболочки. Имея только один параметр, он обычно заключает путь в кавычки по мере необходимости. Поскольку мы отправляем в командную строку полной оболочки, мы хотим передать ненулевое значение в качестве второго аргумента, чтобы включить экранирование от обратной косой черты других специальных символов, которые в противном случае могли бы вызвать сбой оболочки.
@%
читает содержимое %
регистра, который содержит имя файла текущего буфера. Это не обязательно абсолютный путь, поэтому убедитесь, что вы не изменили текущий каталог. В некоторых решениях вы увидите, что рекламный символ опущен. В зависимости от местоположения, %
является допустимым выражением и имеет тот же эффект, что и чтение %
регистра. Однако, вложенный в другое выражение, ярлык, как правило, не разрешен: например, в этом случае.
>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
sudo
существует, но ее нет /dev/null
, поэтому вам нужно быть более изощренной, если вы хотите настоящую кроссплатформенную поддержку. Это скорее вступление - пища для размышлений. :)Совет Райана в целом хорош, однако, если вы выполните шаг 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.
sudoedit
должна быть предпочтительной, поскольку она не требует запуска vim от имени пользователя root. Быстрый взлом, который вы можете рассмотреть, - это выполнить 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)
Конечно, я не рекомендую такой подход в системе, где вы беспокоитесь о безопасности, поскольку в течение нескольких секунд любой может прочитать / изменить файл, даже не подозревая об этом.