cp menimpa vs rm lalu cp

18

Ketika saya mencoba untuk menimpa file biner yang saat ini diluncurkan, cpgagal menimpa, tetapi mungkin rmsaja saat itu cp. Sebagai contoh:

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

Ada yang tahu kenapa?

M4rty
sumber
2
Utas kecil yang menarik, tetapi harus di IMO Unix / Linux.SE.
underscore_d

Jawaban:

41

Dalam kasus pertama, Anda mencoba menimpa konten file yang saat ini berjalan sebagai program. Linux tidak mengizinkan itu - jika itu terjadi, Anda akan menimpa kode tepat ketika OS mengeksekusinya; perbedaan pertama akan merusak program atau membuatnya tidak berfungsi.

Tetapi dalam kasus kedua, Anda tidak benar-benar mengubah konten file lama - Anda membuat file baru di tempatnya, sedangkan yang lama hanya kehilangan nama file tetapi menjaga kontennya tidak tersentuh.

(Ingat bahwa secara teknisrm tidak menghapus file, itu hanya menghapus tautan direktori - mirip dengan bagaimana menambahkan lebih banyak tautan ke file yang sama. Hanya ketika file tidak memiliki tautan dan tidak ada referensi file yang terbuka, secara otomatis akan dihapus.)ln

Sistem mereferensikan file yang digunakan dalam inode mereka, jadi tidak masalah bahwa mereka memiliki nama file yang sama - itu masih file lama yang tetap dibuka oleh sistem, dan meskipun tidak memiliki tautan lagi, itu hanya akan dihapus setelah semua program menutupnya.

grawity
sumber
7
Trik lain yang sering digunakan menggunakan logika yang sama: Buka file (sementara) di perangkat lunak Anda dan hapus segera, tanpa menutup file terlebih dahulu. Program Anda masih dapat menggunakannya dengan cara apa pun yang diinginkan dan ketika program Anda menutupnya (terkontrol) atau lupa menutupnya (misalnya program Anda macet tanpa pembersihan), program itu akan dihapus secara otomatis oleh OS. (Akhir program, tidak peduli bagaimana itu terjadi, rilis semua referensi ke program harus ke file.)
Tonny
2
Itu juga mengapa ketika Anda menghapus beberapa file log dari proses yang sedang berjalan, perintah df tidak mengembalikan ukuran yang diperbaiki sampai Anda menghentikan proses
M4rty
Apakah ada cara untuk program eksternal (dengan hak akses root) untuk menemukan dan membuat pegangan baru untuk inode yang menggantung ini? Saya membayangkan ada program yang menggunakan ini sebagai "fitur keamanan" sehingga menarik untuk memahami cerita selengkapnya.
BenPen
3
@BenPen: Di Linux, ya - gunakan /proc/*/fduntuk mengaksesnya, dan secara opsional linkat () untuk menambahkan tautan baru ke sistem file.
grawity
3
@BenPen dan grawity: Sebenarnya, Anda tidak dapat menautkan inode kembali ke struktur direktori jika memiliki nol tautan, bahkan dengan linkat(), untuk alasan keamanan . (Pengecualian untuk aturan ini: kecuali jika dibuat dengan open(O_TMPFILE)demikian ia memulai dengan nol tautan.) Jika Anda mencoba, linkat()mengembalikan ENOENT, bahkan sebagai root. Lihat jawaban saya pada pertanyaan itu untuk skrip perl untuk benar-benar berjalan linkatdan membuktikan bahwa itu tidak bekerja, bahkan sebagai root: /
Peter Cordes