vim에서 파일을 편집하고 저장하려고 시도한 후 파일이 읽기 전용으로 보고되는 경우가 종종 있습니다. 이 문제에 대한 해결책은 을 추가하는 것입니다 !wq
. vim 프로그램이 내부적으로 읽기 전용 파일에 쓸 수 있는 충분한 권한을 얻을 수 있는 방법을 알아내려고 노력 중입니다.
전환되는 내부 플래그가 있거나 vim이 잠시 동안 일시적으로 권한을 얻습니까?
답변1
Vim에서 이 작업을 수행 할 때 w!
실제로 일어나는 일은 파일 소유자에 따라 다릅니다.
당신(현재 사용자)이 파일의 소유자라면 Vim은 파일을 다시 쓰기 전에 쓰기 권한을 변경합니다. 그런 다음 쓰기 권한을 제거하고 권한 비트를 원래 상태로 되돌립니다.
당신이 파일의 소유자는 아니지만 현재 디렉토리에 쓰기 권한이 있다면 Vim은 원본 파일을 삭제하고 같은 이름의 새 파일에 문서를 쓸 것입니다. 그러면 새 파일에는 원본 파일과 동일한 권한이 할당되지만 소유권은 귀하가 갖습니다.
Vim은 파일에 쓸 수 있는 높은 권한을 전혀 얻지 못합니다.
위 메커니즘은 읽기 전용 파일에 써야 하는 모든 프로그램이 선택해야 하는 사용 가능한 옵션 중 하나입니다(예: 파일에 쓰는 동안 임시로 권한을 변경하거나 파일을 삭제하고 새 파일을 생성). Vim이 궁극적으로 선택하는 작업은 궁극적으로 많은 구성 가능한 설정에 따라 달라질 수 있습니다.
아래 댓글에서 볼 수 있듯이 위의 내용에 대해 약간의 혼란이 있습니다. 특정 브랜드의 Unix에 Vim을 설치할 때 실제로 어떤 일이 발생하는지 직접 확인하려면 읽기 전용 파일을 작성할 때 Vim이 수행하는 시스템 호출을 추적하는 것이 좋습니다. 이것이 수행되는 방법은 사용 중인 Unix에 따라 다릅니다. Linux에서는 다음과 같이 수행 할 수 있습니다 strace vim file
(그런 다음 파일을 편집하고 저장한 후 종료).w!
이것은 첫 번째 경우입니다( OpenBSD에서 ktrace
+ 출력 kdump
).
13228 vim CALL chmod(0x19b1d94b4b10,0100644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim NAMI "file"
13228 vim RET chmod 0
13228 vim CALL lseek(3,0x1000,SEEK_SET)
13228 vim RET lseek 4096/0x1000
13228 vim CALL write(3,0x19b1e0aa9000,0x1000)
이는 파일의 권한을 변경하여 쓰기 가능하게 만들고( S_IWUSR
플래그와 함께 chmod()
) 버퍼를 씁니다.
그런 다음 원래 권한을 설정합니다.
13228 vim CALL fchmod(4,0100444<S_IRUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim RET fchmod 0
13228 vim CALL close(4)
13228 vim RET close 0
다른 경우:
먼저 파일의 링크를 해제(삭제)한 다음 파일을 다시 생성합니다(파일에 쓰고 나중에 권한을 변경하기 전).
44487 vim CALL unlink(0x79fdbc1f000)
44487 vim NAMI "file"
44487 vim RET unlink 0
44487 vim CALL open(0x79fdbc1f000,0x201<O_WRONLY|O_CREAT>,0644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH>)
44487 vim NAMI "file"
44487 vim RET open 4
답변2
Vim은 추가 권한을 얻을 수 없습니다. 다음과 같은 이유로 설정될 수 있는 :w!
내부 옵션을 재정의합니다 .'readonly'
-R
명령줄 옵션이나 , 또는을:view
사용하여 파일을 열었습니다 .:edit
:setlocal readonly
- Vim은 파일에 현재 쓰기 권한이 없다는 것을 인식합니다.
후자의 경우 Vim(기본값) 때문에 파일 쓰기가 여전히 가능할 수 있습니다.새 파일 만들기그런 다음 원본 파일을 해당 파일로 바꾸십시오. 이는 여전히 이를 허용하는 방식으로 설정된 권한에 따라 달라집니다.
Vim을 여는 사용자에게 쓰기 액세스 권한이 없는 경우 실제로 액세스 권한을 얻으려면 :w !sudo tee >/dev/null file
이 트릭을 직접 사용하거나 유사한 플러그인을 통해 사용해야 합니다.Sudo편집.
답변3
쓰기 권한이 없는 파일에는 절대 쓸 수 없습니다. 그러나 디렉터리에 대한 쓰기 액세스 권한이 있으면 파일을 삭제할 수 있습니다.
VIM이 사용하는 트릭은 파일을 삭제하고 새 파일을 작성하는 것입니다.
소스 코드를 읽지 않고도 VIM에서 사용하는 방식인지 검사를 통해 확인할 수 있습니다.아이노드 번호이전과 이후:
$ touch foo
$ chmod u-w foo
$ ls -li foo
60818465 -r--r----- 1 philip philip 0 Feb 25 10:24 foo
$ vi foo
$ # edit the file and save with :w!
$ ls -li foo
60818467 -r--r----- 1 philip philip 8 Feb 25 10:25 foo
inode 번호가 변경되어 새 파일이 편집한 파일과 다르다는 것을 나타냅니다.
참고로 현재 구성은 매우 짧습니다.
runtime! debian.vim
if has("syntax")
syntax on
endif
set tabstop=4
set autoindent
설치된 데비안 패키지는 다음과 같습니다:
vim 2:8.1.0875-1
vim-common 2:8.1.0875-1
vim-runtime 2:8.1.0875-1
vim-tiny 2:8.1.0875-1
답변4
vim이 vi 호환 모드에 있을 때 :w!는 버퍼의 읽기 전용 모드만 덮어쓰지만 파일 권한을 앞뒤로 변경하거나 다른 파일 이름을 원래 이름으로 변경하여 권한을 우회하거나 다른 예비 작업을 시도하지 않습니다. 시간이 중요해요.
IMHO 이것이 유일하게 올바른 동작입니다. 이를 제어하는 플래그는 / W
에서 나옵니다 . 에서 :cpoptions
cpo
:help cpo
*'cpoptions'* *'cpo'* *cpo* 'cpoptions' 'cpo' string (Vim default: "aABceFs", Vi default: all flags) ... *cpo-W* W Don't overwrite a readonly file. When omitted, ":w!" overwrites a readonly file, if possible.
:set compatible
모든 cpo
플래그가 켜집니다. 플래그를 W
사용 하거나 변경할 수 있습니다 .:set cpo+=W
set cpo-=W