Як оновити спільну бібліотеку без збоїв?


18

Тут написано, що ви можете переписати виконуваний файл, і процес буде працювати нормально - він буде перечитаний, коли процес перезапуститься.

Однак, коли я намагаюся замінити бінарний файл під час запущеного процесу (з scp, від dev до тестового сервера), він каже: "файл зайнятий". І якщо я заміню спільний файл бібліотеки (* .so), всі процеси, які пов’язують його, руйнуються.

Чому так? Я щось пропускаю? Як я можу замінити бінарні файли без зупинки / збоїв процесу?


Ви можете перевірити .soфайл за допомогою ldd filename.soперевірки залежностей
Rahul Patil

Я знаю залежності. Я хочу, щоб замінити ці файли, не впливаючи на запущені процеси. Як випливає з пов'язаного питання
Сем

час простою потрібен .. або ви можете зробити так, як stop app && create symlink of .so && start app
Рахул Патіл

Відповіді:


21

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

Тепер для бібліотек, що поділяються, дещо інакше: бібліотеки отримують пам'ять, відображену в адресному просторі процесу mmap(). Хоча, MAP_DENYWRITEможливо, вказано, щонайменше Glibc в Linux мовчки ігнорує це (згідно зі сторінкою man, не соромтеся перевіряти джерела) - перевірте цю тему . Отже , ви на самому справі дозволяється писати файл і, як це пам'ять відображається, будь-які зміни видно майже відразу - а це означає , що якщо ви спробуєте досить важко ви можете управляти цегла машиною перезапису бібліотеки.

Отже, правильний спосіб оновлення:

  1. видалення файлу, який видаляє посилання на дані з файлової системи, так що він не є доступним для новозапущених додатків, які можуть захотіти ним користуватися, зберігаючи дані доступними для всіх, хто вже має їх відкритими (або нанесено на карту) ;

  2. створення нового файлу з оновленим вмістом.

Новостворені процеси використовуватимуть оновлений вміст, запущені програми отримають доступ до старої версії. Це те, що робить будь-яка зручна програма управління пакетами. Зауважте, що це не зовсім без будь-якої небезпеки - наприклад, програми, що динамічно завантажують код (за допомогою dlsym()та друзів), матимуть проблеми, якщо API бібліотеки змінюється безшумно.

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


6

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

То в чому різниця:

  1. від’єднати файл
  2. написати новий файл з такою ж назвою

Це НЕ замінить файл inplace: inode, що посилається на використовуваний бінарний файл, все ще "зайнятий", поки не закінчиться останній об'єкт, який тримає його відкритим. Новий файл буде створений з новим номером inode.

Тепер scpабо cpспробуємо замінити файл на місці - що змінило б вміст, на який посилається inode. Це не працює - як ви описали.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.