cp 覆盖 vs rm 然后 cp

M4r*_*rty 18 linux unix bash

当我试图覆盖当前推出的二进制文件,cp无法覆盖,但它可能rm然后它cp。例如:

user@poste:~$ cp binaryFile /tmp
user@poste:~$ sudo cp /tmp/binaryFile binaryFile 
[sudo] password for user:
cp: cannot create regular file `binaryFile`: Text file busy
user@poste:~$ sudo rm binaryFile 
user@poste:~$ sudo cp /tmp/binaryFile  binaryFile 
user@poste:~$ file binaryFile 
binaryFile : ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x7ce005d9eb50e2574246b6a881e625802f7e49f2, not stripped
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

use*_*686 43

在第一种情况下,您试图覆盖当前作为程序运行的文件的内容。Linux 不允许这样做——如果允许,你会在操作系统执行代码时覆盖它;第一个区别会使程序崩溃或使其出现故障。

但在第二种情况下,您实际上并没有更改旧文件的内容——您是在其位置创建一个文件,而旧文件只是丢失了文件名但保持其内容不变。

(请记住,技术上rm不会删除文件,它只是删除目录链接 - 类似于向同一文件添加更多链接的方式。只有当文件没有链接没有打开的文件引用时,它才会自动被删除。)ln

系统通过它们的 inode 引用正在使用的文件,所以它们具有相同的文件名并不重要——它仍然是系统保持打开的文件,即使它不再有链接,它也只会被删除一旦所有程序关闭它。

  • 另一个经常使用相同逻辑的技巧:在您的软件中打开一个(临时)文件并立即删除它,而不是先关闭文件。您的程序仍然可以以任何方式使用它,当您的程序关闭它(受控)或忘记关闭它(例如,您的程序在没有清理的情况下崩溃)它将被操作系统自动删除。(程序结束,无论发生什么,释放对程序的所有引用都必须指向文件。) (7认同)
  • @BenPen:在 Linux 上,是的 - 使用 `/proc/*/fd` 来访问它,并且可以选择 [linkat()](http://stackoverflow.com/questions/32395329/why-does-linkat-require-a -path-name-instead-of-a-file-descriptor) 添加到文件系统的新链接。 (3认同)
  • @BenPen 和 grawity:实际上,如果 inode 具有零链接,则无法将其链接回目录结构,[即使使用 `linkat()`,出于安全原因](http://stackoverflow.com/a/4174216 /224132)。(这个规则的例外:除非它是用 `open(O_TMPFILE)` 创建的,所以它*开始*有零个链接。)如果你尝试,`linkat()` 返回 ENOENT,即使是 root。请参阅我在该问题上的回答,以获取实际运行 `linkat` 的 perl 脚本并证明它不起作用,即使以 root 身份也行不通:/ (3认同)
  • 这也是为什么当您删除正在运行的进程的某些日志文件时,df 命令在您停止进程之前不会返回正确的大小 (2认同)