前几天我像往常一样使用 Vim,突然发现有些奇怪。以下是我所做的:
~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile
然后我做了一个更改,保存并退出:wq
。很正常。但是,然后:
~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile
因此 root 应该具有 r/w 访问权限,而其他所有人应该只有读取权限。编辑文件,尝试保存 - 您不能。太棒了,按预期工作。但是,如果您使用 保存:w!
,vim 会以某种方式将文件所有权更改回用户名:用户组,并且文件被保存。即使您这样做:
~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile
你可以仍然用 覆盖:w!
!发生了什么?vim 怎么能这样破坏文件所有权和权限的规律?我查看了 vim 的帮助页面,:help :w
发现了以下内容:
:w[rite]! [++opt] Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused.
Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.
以前我无法在 vim 中写入文件,所以我想我的问题的真正核心是,如何让文件无法被 vim 编辑,以及为什么它不像我期望的那样基于文件系统权限,以及 vim 使用什么机制来编辑其他编辑器(gedit、nano)无法使用的文件?
编辑:我尝试使用的计算机使用的是 Linux 内核 3.15.5-2-ARCH。Vim 的版本号是 7.4.373-1,它是安装的pacman
- 我没有使用任何特殊选项从头编译它。
答案1
我可以看到您当前的路径是~
,即您的用户主目录。您应该对该目录具有写权限。
换个角度想想——如果您对该目录具有读写权限,那么是什么阻止您复制文件、删除旧文件并使用不同的权限重命名新文件呢?
如果你在 strace 下运行 vim,例如:
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid() = 1000
unlink("testfile") = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10) = 10
fsync(3) = 0
close(3) = 0
chmod("testfile", 0644) = 0
根据这个日志,我可以猜测以下过程:
chown
为了简洁起见,省略了一些早期的权限检查(和尝试等)。
open
尝试打开文件进行写入(失败:权限被拒绝)lstat
检查文件的所有者getuuid
检查当前用户 ID,看其是否与文件所有者匹配unlink
删除文件(这是允许的,因为目录具有写权限)open
创建同名的新文件write
文件内容(请先阅读,我输入了一些乱码)fsync
将文件刷新到磁盘(不太重要)close
chmod
将新文件的权限更改为与旧文件类似 - 它现在恰好有新的所有者。