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

242

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

sudo vi filename

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

  • 0
    возможно просто сохраните копию в вашем домашнем каталоге и "sudo mv" позже
Теги:
vi

11 ответов

281
Лучший ответ

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

:w !sudo tee %

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

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

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

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

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

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

  • 5
    Это работает в gvim? При запуске команды Vim запрашивает пароль, но не принимает ввод. В конце концов он останавливается на две попытки и говорит: sudo: 1 incorrect password attempt
  • 0
    я не вижу причин, по которым gvim ведет себя по-другому ... вы уверены, что sudo само по себе работает правильно?
Показать ещё 5 комментариев
30

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

:w !sudo tee myfile
  • 1
    :w !sudo tee % >/dev/null или :w !sudo dd of=% избегать :w !sudo tee % >/dev/null содержимого файла при его сохранении.
  • 0
    Можете ли вы объяснить, как это работает? Я посмотрел tee и увидеть это команда Unix трубы, и ! вставляет команду оболочки Является ли :w запись стандартным, который получает по tee ?
Показать ещё 1 комментарий
14

Общие оговорки

Самый распространенный способ обойти проблему только для чтения - открыть канал для текущего файла в качестве суперпользователя, используя реализацию 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 pipe 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, который синхронизируется на разных компьютерах, поэтому я добавил многоплатформенные функции для моего. Здесь a ~/.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
  • 0
    Что если вы отключите Windows, фактически создав файл с возможностью записи для всего мира в C: \ dev \ null?
  • 1
    @PaulStelian Возможно, но вряд ли. Вы можете легко расширить этот код для учета различных платформ и обстоятельств. В действительности вы вряд ли столкнетесь с ситуацией в Windows, где sudo существует, но не /dev/null , поэтому вам нужно быть более изощренным, если вы хотите настоящую кроссплатформенную поддержку. Это скорее вступление - пища для размышлений. :)
10

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

:e sudo:%
Vim заменит% на имя текущего файла, а sudo: инструктирует sudo.vim script взять на себя ответственность за чтение и письмо.
  • 4
    Я бы не рекомендовал использовать этот скрипт, так как он не принимает надлежащих мер предосторожности при экранировании имен файлов.
7

Совет Райана, как правило, хорош, однако, если следующий шаг 3, не перемещайте временный файл; у него будут неправильные права собственности и разрешения. Вместо этого sudoedit правильный файл и прочитайте содержимое (используя :r или тому подобное) временного файла.

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

3

Когда вы переходите в режим вставки в файл, вам нужен 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

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

  • 0
    cat $ tmp> $ target - креатив, но есть ли причина не просто sudo mv файл?
  • 0
    Хороший вопрос. Была также большая проблема с sudo cat что-то> / etc / blah - он будет использовать sudo для cat файла, затем обычный пользователь будет писать в / etc / blah (что не будет работать). Исправлено в ответ, и добавил ваше лучшее предложение sudo mv ..
Показать ещё 1 комментарий
1

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

1

Быстрый Google, похоже, дает следующий совет:

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

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

0

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

alias svim='sudo vim'

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

  • 2
    Команда sudoedit должна быть предпочтительной, поскольку она не требует запуска vim от имени пользователя root.
  • 2
    Это по-прежнему не останавливает вас, связывая vim вместо svim, к которому ОП прибегает.
Показать ещё 1 комментарий
-2

Быстрый взлом, который вы можете рассмотреть, - это сделать 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)

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

-8

используйте gksudo вместо sudo для GVim i.e.

cmap w!! w !gksudo tee >/dev/null %
  • 0
    Ну, это только что закрыло мой / etc / fstab. Спасибо за это.
  • 1
    Я должен также упомянуть, что, поскольку он просит вас перезагрузить файл, отмена не происходит.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню