vi 내부의 파일에 대한 루트 권한을 얻습니까? [닫은]


245

구성 파일을 편집하는 동안 종종 vi로 파일을 열고 저장하려고 할 때 입력하지 않았다는 것을 알게됩니다.

sudo vi filename

vi sudo 권한을 부여하여 파일을 저장할 수있는 방법이 있습니까? 한참 전에 vi에 대한 내용을 찾는 동안 이것에 대해 뭔가를 본 것이 기억 나지만 지금은 찾을 수 없습니다.


어쩌면 그냥 홈 디렉토리에 사본을 저장하고 나중에 "sudo mv"
— paan

답변:


296

% 는 현재 파일 이름으로 바뀌므로 다음을 사용할 수 있습니다.

:w !sudo tee %

( vim파일이 변경되었음을 감지하고 다시로드할지 여부를 묻습니다. [L]확인 대신에 예라고 말하십시오 .)

바로 가기로 자신의 명령을 정의 할 수 있습니다. 당신의 다음을 넣어 .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
— cmcginty

나는 gvim이 다르게 행동 할 이유가 없다고 생각한다. sudo 자체가 올바르게 작동한다고 확신 하는가?

새 파일을 저장하기 위해 루트 권한이 필요한 경우 %를 새 파일의 이름 (경로 포함)으로 바꾸십시오.
— gvkv

때로는 사용자를 sudoer 파일에 먼저 추가하고 루트 사용자를 입력 한 다음 /etc/sudoers파일을 열고 your_username ALL=(ALL) ALL행 아래 에 추가 root ALL=(ALL) ALL하고 종료하고 저장해야합니다.
— 가장 멋진

1
@coolesting : 1) 당신이해야 할 다른 일들이 수천 개 있습니다… 우리는 그것들을 모두 나열 할 수는 없습니다. 2) 항상 사용해야 visudo합니다.

32

일반적으로 vi 프로세스의 유효 사용자 ID를 변경할 수 없지만 다음을 수행 할 수 있습니다.

:w !sudo tee myfile

1
:w !sudo tee % >/dev/null또는 :w !sudo dd of=%파일이 저장 될 때 파일의 내용이 에코되는 것을 피하십시오.
— jamessan

이것이 어떻게 작동하는지 설명 할 수 있습니까? 나는 tee유닉스 파이프 명령을 !보고 쉘 명령을 삽입하는 것을 보았습니다 . 는 IS :w에 의해 파이프됩니다 표준 출력에 쓰기는 tee?
— Eric Hu

4
@ 에릭, 맞아. "tee myfile"명령은 stdin을 myfile에 복사합니다. "sudo tee myfile"을 실행하면 동일한 작업을 수행 할 수 있지만, 티 프로세스는 루트가 소유하므로 myfile도 루트가 소유합니다. vi :에서 ": w! some command line"은 모든 행을 "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당신이 여기에 있기 때문에 분명해야합니다. 수퍼 유저 권한으로 명령을 실행하십시오. 인터넷에는 그 작동 방식에 대한 많은 정보가 있습니다.

teestdin주어진 파일에 파이프 . :write에 쓰면 stdin수퍼 유저 tee가 파일 내용을 받아 파일을 씁니다. 내용을 덮어 쓰는 새 파일을 만들지 않으므로 파일 모드와 특성이 유지됩니다.

shellescape()주어진 파일 경로에서 현재 쉘에 적합한 특수 문자를 이스케이프합니다. 매개 변수가 하나만 있으면 일반적으로 경로를 따옴표로 묶습니다 (필요한 경우). 전체 쉘 명령 행으로 전송하기 때문에, 쉘을 넘어갈 수있는 다른 특수 문자의 백 슬래시 이스케이프를 가능하게하기 위해 0이 아닌 값을 두 번째 인수로 전달하려고합니다.

@%%현재 버퍼의 파일 이름이 포함 된 레지스터 의 내용을 읽습니다 . 반드시 절대 경로 일 필요는 없으므로 현재 디렉토리를 변경하지 않았는지 확인하십시오. 일부 솔루션에서는 상업 기호가 생략 된 것을 볼 수 있습니다. 위치에 따라 %유효한 표현식이며 %레지스터 를 읽는 것과 동일한 효과가 있습니다. 그러나 다른 식 안에 중첩되어있는 경우 바로 가기는 일반적으로 허용되지 않습니다 (예 :이 경우).

>NUL및 >/dev/null리디렉션 stdout플랫폼의 널 장치. 비록 우리가 명령을 침묵 시켰음에도 불구하고, stdinvim으로 다시 배관하는 것과 관련된 모든 오버 헤드를 원하지 않기 때문에 가능한 빨리 덤프하는 것이 가장 좋습니다. NULDOS, 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관련 설정 만있는 a 는 다음과 같습니다 .

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

C : \ dev \ null에 실제로 쓰기 가능한 파일을 만들어 Windows를 넘어 가면 어떻게됩니까?
— Paul Stelian

1
@PaulStelian 가능하지만 가능하지 않습니다. 다양한 플랫폼과 상황을 설명하기 위해이 코드를 쉽게 확장 할 수 있습니다. 실제로는 sudo존재하지만 존재하지 않는 Windows에서는 상황이 발생 하지 않을 /dev/null것이므로 진정한 크로스 플랫폼 지원을 원한다면 더 멋진 경험을해야합니다. 그것은 생각을위한 음식에 대한 소개입니다. :)
— Zenexer

11

Vim을 사용하는 경우 sudo.vim 이라는 스크립트를 사용할 수 있습니다 . 루트 액세스 권한이 필요한 파일을 열었다면 다음을 입력하십시오.

: e sudo : %
Vim은 %를 현재 파일 이름으로 sudo:바꾸고 sudo.vim 스크립트가 읽고 쓸 수 있도록 지시합니다.


4
이 스크립트는 파일 이름을 이스케이프 처리하는 데 적절한 예방 조치를 취하지 않으므로 사용하지 않는 것이 좋습니다.
— jamessan

7

Ryan의 조언은 일반적으로 좋지만 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은 창의적이지만 파일을 mv로하지 않는 이유가 있습니까?
— ojrac

좋은 지적 .. 또한 sudo cat 무언가> / etc / blah에 큰 문제가있었습니다. sudo를 사용하여 파일을 고양이로 만든 다음 일반 사용자가 / etc / blah에 쓸 수 있습니다 (작동하지 않음). 대답과 더 나은 sudo mv 제안을 추가했습니다 ..
— dbr

mv 제안은 권한을 유지하지 않습니다.
— Paul Stelian

1

빠른 Google은 다음과 같이 조언합니다.

  1. 읽기 전용 인 경우 편집하지 마십시오.
  2. 파일에 대한 권한을 변경할 수 있습니다. (저장할 수 있는지 여부는 실험에 달려 있습니다.)
  3. 그래도 여전히 편집 한 경우 임시 파일로 저장 한 다음 이동하십시오.

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



0

나는 ~ / .bashrc에 이것을 가지고있다 :

alias svim='sudo vim'

이제 구성 파일을 편집해야 할 때마다 svim으로 엽니 다.


2
sudoedit는 루트로 실행 정력을 필요로하지 않기 때문에 명령을 선호한다.
— jamessan

2
이것은 여전히 ​​OP가 회피 한 svim 대신 vim을 묶는 것을 멈추지 않습니다.
— ScaryAardvark

3
-1, 이것은 "파일을 열 때 sudo를 입력해야 함"이라고 말하고 OP는 vi 내부에서 루트 권한을 얻는 방법을 알고 싶어합니다.
— Brad Koch

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

물론 보안이 걱정되는 시스템에서는이 방법을 사용하지 않는 것이 좋습니다. 몇 초 동안 누구나 모르게 파일을 읽거나 변경할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.