cp перезаписати vs rm, потім cp


18

Коли я намагаюся перезаписати бінарний файл, який зараз запущений, 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

Будь-яка ідея чому?


2
Цікавий маленький потік, але він повинен бути в IMO на Unix / Linux.SE.
підкреслити_28

Відповіді:


41

У першому випадку ви намагаєтесь перезаписати вміст файлу, який наразі працює як програма. Linux цього не дозволяє - якби це було, ви б перезаписали код правильно під час виконання ОС; Перша різниця призведе до збою програми або виходу з ладу.

Але у другому випадку ви фактично не змінюєте вміст старого файлу - ви створюєте новий файл замість нього, тоді як старий просто втрачає ім’я файлу, але зберігає його вміст не торканим.

(Пам'ятайте, що технічноrm не видаляються файли, вони просто видаляють посилання на каталоги - подібно до того, як додається більше посилань на той самий файл. Тільки коли файл не має посилань і не має посилань на відкриті файли, він автоматично видаляється.)ln

Система посилається на файли, що використовуються, за своїм inode, тому не має значення, що вони мають однакове ім'я файлу - це все ще старий файл, який залишається відкритим системою, і хоча він більше не має посилань, він буде лише видалений як тільки всі програми закривають його.


7
Ще одна хитрість, яка часто використовується за тією ж логікою: відкрийте (тимчасовий) файл у своєму програмному забезпеченні та видаліть його негайно, не закриваючи файл спочатку. Ваша програма все ще може використовувати її будь-яким способом, і коли програма закриє її (контролюється) або забуде її закрити (наприклад, ваша програма вийшла з ладу без очищення), вона автоматично буде видалена ОС. (Кінець програми, як би це не сталося, випускає всі посилання на програму, що мала на файл.)
Tonny

2
Ось чому, коли ви видаляєте файл журналу запущеного процесу, команда df не повертає виправлений розмір, поки ви не зупините процес
M4rty

Чи існує можливість зовнішньої програми (з привілейками root) знайти та створити нову ручку для цієї звисаючої inode? Я думаю, є програми, які використовують це як "функцію безпеки", тому цікаво зрозуміти повну історію.
БенПен

3
@BenPen: У Linux так - використовуйте /proc/*/fdдля доступу до нього та, можливо, linkat (), щоб додати нове посилання до файлової системи.
користувач1686

3
@BenPen та grawity: Насправді ви не можете зв'язати inode назад в структуру каталогу, якщо вона має нульові посилання, навіть з linkat()міркувань безпеки . (Виняток із цього правила: якщо воно не було створене з open(O_TMPFILE)таким чином, воно починалося з нульових посилань.) Якщо ви спробуєте, linkat()повертає ENOENT навіть як root. Дивіться мою відповідь на це питання, щоб сценарій perl насправді запустився linkatі довів, що він не працює, навіть як root: /
Peter Cordes
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.