Получение root-прав на файл внутри vi? [закрыто]


245

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

sudo vi filename

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


возможно просто сохраните копию в вашем домашнем каталоге и "sudo mv" позже
paan

Ответы:


296

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

: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
останавливается

я бы не увидел причин, по которым gvim вел себя иначе ... ты уверен, что sudo само по себе работает правильно?

Если вам нужны привилегии root для сохранения нового файла, замените% на имя (включая путь) нового файла.
gvkv

Иногда вам нужно сначала добавить своего пользователя в файл sudoer, ввести пользователя root и открыть /etc/sudoersфайл, добавить его your_username ALL=(ALL) ALLпод строкой root ALL=(ALL) ALL, выйти и сохранить.
самое крутое

1
@coolesting: 1) вам нужно сделать еще около тысячи вещей ... мы не можем перечислить их все. 2) вы всегда должны использовать visudo.

32

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

:w !sudo tee myfile

1
:w !sudo tee % >/dev/nullили :w !sudo dd of=%избегайте повторного отображения содержимого файла при сохранении файла.
Jamessan

Можете ли вы объяснить, как это работает? Я поднял голову teeи увидел, что это команда канала Unix, и !вставил команду оболочки. Является ли :wнаписание к стандарту, который получает по каналу tee?
Эрик Ху,

4
@ Эрик, все верно. команда "tee myfile" скопирует стандартный ввод в myfile. запуск «sudo tee myfile» будет делать то же самое, но поскольку процесс tee принадлежит root, myfile также будет принадлежать root. На стороне vi «: w! Some command line» будет передавать все строки в «некоторую командную строку».
Марк Харрисон

16

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

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

Что если вы отключите Windows, фактически создав файл с возможностью записи для всего мира в C: \ dev \ null?
Пол Стелиан

1
@PaulStelian Возможно, но вряд ли. Вы можете легко расширить этот код для учета различных платформ и обстоятельств. В действительности, вы вряд ли столкнетесь с ситуацией в Windows, где она sudoсуществует, но ее нет /dev/null, поэтому вам нужно быть более изощренной, если вы хотите настоящую кроссплатформенную поддержку. Это скорее вступление - пища для размышлений. :)
Zenexer

11

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

: e sudo:%
Vim заменяет% на имя текущего файла и sudo:дает команду сценарию sudo.vim вступить во владение для чтения и записи.


4
Я бы не рекомендовал использовать этот скрипт, так как он не принимает надлежащих мер предосторожности при экранировании имен файлов.
Jamessan

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

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


cat $ tmp> $ target - креатив, но есть ли причина не просто sudo mv файл?
ojrac

Хороший вопрос. Была также большая проблема с sudo cat что-то> / etc / blah - он будет использовать sudo для cat файла, а затем обычный пользователь для записи в / etc / blah (что не будет работать). Исправлено в ответ, и добавил ваш лучший Судо мВ предложение ..
DBR

Предложение mv не сохраняет разрешения.
Пол Стелиан

1

Быстрый Google, кажется, дает этот совет:

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

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


1

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


0

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

alias svim='sudo vim'

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


2
Команда sudoeditдолжна быть предпочтительной, поскольку она не требует запуска vim от имени пользователя root.
Jamessan

2
Это по-прежнему не останавливает вас, связывая vim вместо svim, к которому ОП прибегает.
ScaryAardvark

3
-1, это просто говорит «не забывайте вводить sudo при открытии файла», OP хочет знать, как они могут получить привилегии root внутри vi.
Брэд Кох

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.