Получение прав root для файла внутри vi?

Часто, редактируя файлы конфигурации, я открываю один с помощью vi, а затем, когда иду, чтобы сохранить его, понимаю, что я не набирал

sudo vi filename

Есть ли способ предоставить vi sudo привилегии для сохранения файла? Кажется, я припоминаю, что видел что-то об этом, когда искал кое-что о vi некоторое время назад, но теперь я не могу этого найти.

Ответов (10)

Решение

% заменяется текущим именем файла, поэтому вы можете использовать:

:w !sudo tee %

( vim обнаружит, что файл был изменен, и спросит, хотите ли вы, чтобы он был перезагружен. Скажите «да», выбрав, [L] а не «ОК».)

В качестве ярлыка вы можете определить свою собственную команду. Поместите в свой .vimrc :

command W w !sudo tee % >/dev/null

С помощью вышеуказанного вы можете ввести, :W<Enter> чтобы сохранить файл. С тех пор, как я написал это, я нашел более приятный (на мой взгляд) способ сделать это:

cmap w!! w !sudo tee >/dev/null %

Таким образом, вы можете ввести текст, :w!! и он будет расширен до полной командной строки, оставив курсор в конце, так что вы можете заменить его % собственным именем файла, если хотите.

Общие предостережения

Наиболее распространенный метод решения проблемы файла, доступного только для чтения, - открыть канал к текущему файлу от имени суперпользователя, используя реализацию 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() экранирует специальные символы в указанном пути к файлу в соответствии с текущей оболочкой. Имея всего один параметр, он обычно просто заключает путь в кавычки по мере необходимости. Поскольку мы отправляем в полную командную строку оболочки, мы хотим передать ненулевое значение в качестве второго аргумента, чтобы включить обратную косую черту для других специальных символов, которые в противном случае могут вызвать сбой оболочки.

@% читает содержимое % регистра, который содержит имя файла текущего буфера. Это не обязательно абсолютный путь, поэтому убедитесь, что вы не изменили текущий каталог. В некоторых решениях вы увидите, что символ коммерческой продажи опущен. В зависимости от местоположения % это допустимое выражение, имеющее тот же эффект, что и чтение % регистра. Однако ярлык, вложенный внутрь другого выражения, обычно запрещен: например, в этом случае.

>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 или подобное) временного файла.

Если вы :w! выполните шаг 2, используйте для принудительной записи файла.

В общем, вы не можете изменить эффективный идентификатор пользователя процесса vi, но вы можете сделать это:

:w !sudo tee myfile

Быстрый гугл, кажется, дает такой совет:

  1. Не пытайтесь редактировать, если он предназначен только для чтения.
  2. Возможно, вы сможете изменить права доступа к файлу. (Позволит ли это вам сэкономить, зависит от экспериментов.)
  3. Если вы все равно редактировали, сохраните его во временный файл, а затем переместите его.

http://ubuntuforums.org/showthread.php?t=782136

Быстрый прием, который вы можете рассмотреть, - это выполнить 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 для редактирования, вы получаете сообщение о состоянии

-- 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

Вероятно, есть менее окольный способ сделать это, но он работает.

Если вы используете Vim , доступен сценарий sudo.vim . Если вы обнаружите, что открыли файл, для чтения которого вам нужен root-доступ, введите

: e sudo:%
Vim replaces the % with the name of the current file, and sudo: instructs the sudo.vim script to take over for reading and writing.

У меня это в ~ / .bashrc:

alias svim='sudo vim'

Теперь, когда мне нужно отредактировать файл конфигурации, я просто открываю его с помощью svim.

Вот еще один, появившийся после ответа на этот вопрос, плагин под названием SudoEdit, который предоставляет функции SudoRead и SudoWrite, которые по умолчанию будут пытаться сначала использовать sudo и su, если это не удается: http://www.vim.org/scripts/ script.php? script_id = 2709