Vi는 파일이 읽기 전용 임에도 불구하고 파일에 쓸 수 있습니다


12

다음 예제는 읽기 권한 만있는 파일을 작성하는 방법을 보여줍니다. 보시다시피, 내가 얻는 echo 명령을 사용 하여이 파일에 쓰려고 할 때 Permission denied.

그러나 왜 vi를 사용하는 경우 얻지 Permission denied 합니까? 여기에서 볼 수 있듯이 파일이 읽기 전용 인 경우에도 파일에 쓸 수 있습니다.

여기서 무슨 일이 일어나고 있습니까? 이것은 vi 버그입니까?

[admin@madona-machine1 ~]$ touch test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-rw-r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ chmod -w  test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-r--r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ echo try_to_write > test-file
-bash: test-file: Permission denied
[admin@madona-machine1 ~]$ vi test-file

I am good singer,

 ~
 ~
 ~
 ~
 ~
 ~
 ~                                                
   "test-file" 1L, 4C written

1
참고로 여기에 베타 SE 사이트가 있습니다 -vi.stackexchange.com
Raystafarian

답변:


28

참고 : 레거시 라이센스 때문에 대부분의 GNU / Linux 배포판에는 Bill Joy가 작성한 원래 vi 프로그램이 포함되어 있지 않습니다. 대신 vi 명령은 vi 호환 모드에서 Vim을 실행하여 제공됩니다. 다음 답변은 vi 호환 모드로 Vim을 실행하는 것을 기반으로합니다.

읽기 전용 파일 수정

Vim은 읽기 전용 파일의 버퍼를 수정하면 사용자에게 경고합니다 W10: Warning: Changing a readonly file. 사용자가이 파일에 쓰려고하면 다음과 같은 오류 메시지가 나타납니다 'readonly' option is set (add ! to override).

Vim 사용자가 상위 디렉토리를 쓸 수있는 경우

도움이되는 Vim !w명령에 느낌표를 추가하여 글쓰기를 강력하게 요구할 수 있음을 사용자에게 알려줍니다 . 이 강력한 버전의 쓰기 명령을 사용하는 경우 Vim은 원본 파일을 삭제합니다 (Vim 전용 backup옵션이 설정된 Vim을 사용하는 경우 원본 파일의 이름 은 실제로 백업 파일과 동일하게 변경 됩니다). 그러므로 개방되는 (생성) 새로운 파일동일한 이름 일본어 등을이 새로운 파일로 버퍼의 내용을 기록한다. 이것은 Vim을 실행하기 전후에 파일 의 inode 를 검사하여 확인할 수 있습니다 .

$ ls -l --inode t

131529 -r--r--r-- 1 anthony anthony 0 Apr 13 09:23 t

$ vi t
$ ls -l --inode t

131649 -r--r--r-- 1 anthony anthony 4 Apr 13 09:23 t

참고 : 이렇게하면 파일 및 중단 (기호) 링크의 권한 및 소유권이 변경 될 수도 있습니다. 예를 들어 원본 파일이 다른 사용자가 소유 한 경우 Vim을 실행하는 사용자가 새 파일을 소유합니다.

프로세스는 파일의 상위 디렉토리에 대한 쓰기 권한이있는 경우에만이를 수행 할 수 있습니다. 일반적으로 프로그램이 파일을 수정할 수 없도록하려면 파일 자체와 상위 디렉토리의 권한을 모두 확보해야합니다.

Vim 사용자가 상위 디렉토리를 쓸 수없는 경우

그러나이 경우에도 Vim은 여전히 ​​일관된 사용자가 파일을 덮어 쓰도록 돕기 위해 최선을 다합니다. Vim 사용자에게 파일 소유권이있는 경우 Vim은 파일의 권한을 일시적으로 변경하고 ( chmod시스템 호출 사용) 버퍼를 파일에 쓰고 파일을 닫은 다음 읽기 전용 부모 디렉토리 제한을 해결할 수 있습니다 . 다시 권한. 다음은 strace를 통해 vi를 실행하는 동안 수행 된 시스템 호출의 추출입니다 strace -o ../vi.trace vi t.

getuid()                                = 501
chmod("t", 0100644)                     = 0
open("t", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)     = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("t", 0100444)                     = 0

참고 : Vim 사용자가 Vim이 파일 권한을 변경할 수 없으므로 소유권이없는 파일을 편집하는 경우에는 이런 일이 발생하지 않습니다.

추가

GNU / Linux 시스템에서 파일을 수정할 수 없도록 chattr하려면 수퍼 유저로 명령을 실행하십시오 .

sudo chattr +i filename

보낸 사람 man chattr:

'i'속성이있는 파일은 수정할 수 없습니다. 파일을 삭제하거나 이름을 바꿀 수 없으며이 파일에 대한 링크를 만들 수 없으며 파일에 데이터를 쓸 수 없습니다. 수퍼 유저 또는 CAP_LINUX_IMMUTABLE 기능을 가진 프로세스 만이 속성을 설정하거나 지울 수 있습니다.


2
성스러운 연기, 그것은 철저했다!
Camille Goudeseune

4
@CamilleGoudeseune 내 대답의 첫 번째 버전을 게시 한 후 몇 가지 실험을하고 strace를 통해 Vim을 실행하는 데 약 한 시간을 소비하여 여러 상황에서 파일 뒤에서 수행되는 작업을 확인했습니다. 부모 디렉토리). 나는 때때로 쫓겨나지만 일단 답변을 게시하면, 내가 말한 내용이 올바른지 확인하고 싶었습니다.
Anthony Geoghegan

5

대부분의 모든되지 않으면 vi구현 당신도 같은 명령을 저장 규칙을 사용하는 경우 파일을 작성하는 방법을 방지 ZZ, :w, :wq또는 :x로 예를 들면 vim:

:w
E45: 'readonly' option is set (add ! to override)

다른 한편으로, 또는 vi같은 것을 사용하여 파일의 권한에도 불구하고 파일 을 쓰라고 지시 하면 편집기는 파일을 쓸 수 있도록 일시적으로 권한을 완화합니다.:x!:wq!

...
stat("test-file", {st_mode=S_IFREG|0444, st_size=7, ...}) = 0
getuid()                                = 1000
chmod("test-file", 0100644)             = 0
...
open("test-file", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)               = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("test-file", 0100444)             = 0
....

이 경우 inode 번호는 변경되지 않습니다.

마지막으로 파일 권한을 변경할 수없는 것처럼 버그가 아닙니다 vi.를 통해 수정할 수 없습니다 .


하! 내 대답을 게시 한 후 몇 가지 실험을하고 strace를 통해 Vim을 실행하는 데 거의 시간을 투자하여 여러 상황에서 파일 뒤에서 수행중인 작업을 확인했습니다 (사용 권한 및 파일과 부모 디렉토리의 소유권의 다른 순열). 실험 결과 요약을 마친 후에 만 ​​답을 보았습니다. 좋은 학습 경험이었습니다.
Anthony Geoghegan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.