mai*_*ash 12 linux vi ls chmod
以下示例显示如何创建仅具有读取权限的文件。正如我们所见,当我尝试使用 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
Run Code Online (Sandbox Code Playgroud)
Ant*_*gan 29
注意:由于遗留许可的原因,大多数 GNU/Linux 发行版不包含 Bill Joy 编写的原始 vi 程序。相反,vi 命令是通过在 vi 兼容模式下运行 Vim 来提供的。以下答案基于运行 Vim 及其 vi 兼容模式。
如果用户修改了只读文件的缓冲区,Vim 会警告用户W10: Warning: Changing a readonly file
。如果用户尝试写入此文件,则会收到以下错误消息'readonly' option is set (add ! to override)
。
Vim 很有帮助,让用户知道他们可以通过!
在w
命令后附加感叹号来强行坚持写作。如果使用这个强制版本的 write 命令,Vim 会删除原始文件(如果使用 Vim 并设置了 Vim-onlybackup
选项,则原始文件实际上被重命名为与备份文件相同)。然后它打开(创建)一个与原始文件同名的新文件,并将其缓冲区的内容写入这个新文件。这可以通过在运行 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
Run Code Online (Sandbox Code Playgroud)
注意:这也可能改变文件的权限和所有权并破坏(符号)链接,例如,如果原始文件为另一个用户所有,新文件将由运行 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
Run Code Online (Sandbox Code Playgroud)
注意:如果 Vim 用户正在编辑一个他们没有所有权的文件,则不会发生这种情况,因为 Vim 将无法更改文件权限。
要真正确定不能修改文件(在 GNU/Linux 系统上),请chattr
以超级用户身份运行命令:
sudo chattr +i filename
Run Code Online (Sandbox Code Playgroud)
来自man chattr
:
不能修改具有“i”属性的文件:不能删除或重命名它,不能创建指向该文件的链接,也不能将数据写入该文件。只有超级用户或拥有 CAP_LINUX_IMMUTABLE 能力的进程才能设置或清除此属性。
vi
如果您使用诸如ZZ
, :w
,:wq
或 之类的常规保存命令,则大多数(如果不是全部)实现都会阻止您写入文件:x
,例如vim
:
:w
E45: 'readonly' option is set (add ! to override)
Run Code Online (Sandbox Code Playgroud)
另一方面,如果您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
....
Run Code Online (Sandbox Code Playgroud)
在这种情况下,inode 编号保持不变。
最后,这不是一个错误,就像您不允许更改文件权限一样,您无法通过vi
.
归档时间: |
|
查看次数: |
35117 次 |
最近记录: |