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.