![为什么我可以修改只读文件?](https://linux22.com/image/1139785/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E5%8F%AF%E4%BB%A5%E4%BF%AE%E6%94%B9%E5%8F%AA%E8%AF%BB%E6%96%87%E4%BB%B6%EF%BC%9F.png)
简短问题:
为什么我们即使不是管理员也可以使用+++:在Vim中操作只读文件?wq!
长问题:
我有一个对所有人而言都是只读的文本文件(myFile.txt):
navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt
我无需管理员权限就可以使用 Vim 打开它:
navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt
我修改它并按:++++Esc然后我看到此错误消息::wqEnter
E45: 'readonly' option is set (add ! to override)
到目前为止,一切都说得通。但是当我按下:++++++++Esc时, Vim会保存更改。:wq!Enter
我正在使用 Ubuntu 16.04 和 VIM 7.4。
答案1
正如@Rob 已经提及,只有当您对包含该文件的目录具有写权限时,您才能执行此操作。例如,尝试对中的文件执行相同操作/etc
将会失败。
至于如何 vim
执行此操作时,它会删除文件并重新创建。为了测试这一点,我创建了一个由 root 拥有的文件:
echo foo | sudo tee fff
vim
然后按照您描述的方式继续编辑文件,但附加该过程以strace
查看发生了什么:
strace vim fff 2> strace.out
我随后检查strace.out
发现:
unlink("fff") = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11) = 11
因此,首先删除该文件 ( unlink("fff")
),然后创建一个同名的新文件 ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)
),并将我所做的修改写入该文件 ( write(4, "foasdasdao\n", 11)
)。如果您在家中尝试此操作,您会发现在使用 编辑该文件后vim
,该文件现在属于您,而不是 root。
因此,严格来说,vim
这不是编辑您无权写入的文件。而是从您有写入权限的目录中删除文件,然后创建一个您同样有写入权限的新文件。
答案2
只要您拥有父目录,您就可以删除或替换文件,无论权限如何,因为您可以更改目录的内容:)。
尝试使用其他命令(如 rm),它会提示您,但您仍然可以执行此操作。使目录不可写,这样就可以停止它。
添加:
刚刚试过,只要我拥有该文件,我仍然可以修改它,即使文件夹是只读的。但是,当我将所有权更改为 root:root 时,它无法打开文件进行写入。因此解决了修改 root(或其他人)拥有的文件的问题
答案3
使用w!
您正在删除原始文件(你被允许这样做) 并编写您自己的版本。
当您对目录具有写权限时,您可以:创建、移动或删除该目录中的文件。
$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file
现在让我切换用户并更改文件
$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file
现在看看里面有什么:
$ cat foo/file
bye
答案4
这是 VIM 向您发出的警告,考虑到 UNIX 中的权限工作方式,这可能相对重要。这显然不直观,因为 UNIX 文件系统对存储在文件 i 节点中的文件具有权限。目录结构在某种程度上是独立的,并且仅链接这些 i 节点。目录也有自己的权限,这些权限表明您是否可以将文件链接/取消链接到其中,或者读取它或遍历到子目录。这种设计允许同一个文件出现在目录结构中的几个不同位置(通过硬链接)。通过说“添加 ! 以覆盖”,VIM 试图警告您原始文件将被取消链接(因此它将保留在所有其他地方不变),并且将创建新文件并链接到目录结构中的原始位置。如果原始文件的链接数减少到零,则原始文件将被释放,但如果没有,您实际上是在克隆文件。打开文件也算作链接,因此如果某个程序打开了文件并且您同意“添加 ! 以覆盖”,则该程序将看不到您使用 VIM 对文件所做的更改。该文件仅由 VIM 从目录中取消链接,并且在另一个程序关闭文件后,该文件将被释放,除非它链接到其他地方。
请注意,在 Windows 中,文件的权限存储在目录中,因此从 Windows 权限范例的角度来看,这种 vim 行为确实可能看起来很奇怪。为了写入文件,Windows 在逻辑上可能还会检查一些目录权限,甚至是超级目录权限。如上所述,在 UNIX 中,只要您能够列出并打开文件(即所有超级目录都有 x),目录权限与文件操作无关。如果在打开后与所有目录取消链接,则在 UNIX 中打开的文件可能甚至不再具有文件名。
例如,您有文件 /home/user1/foo,它与 /home/user2/foo 是同一个文件(即硬链接到 /home/user2/foo),并且该文件不可由任何人写入,当前由程序 P 打开(由 root 启动的程序以读写方式打开)。如果 user1 使用 vim 打开它并覆盖,他会制作自己的副本,并且不再看到原始文件。如果随后 user2 使用 vim 打开他的链接并写入它,它将再次被取消链接,他将创建另一个副本。程序 P 仍将看到原始文件,并且可以自由读取或写入它。一旦程序关闭文件,该文件将消失(被文件系统释放)。