Здесь говорится, что вы можете переписать исполняемый файл, и процесс будет работать нормально - он будет перечитан при перезапуске процесса.
Однако, когда я пытаюсь заменить двоичный файл во время работы процесса (с помощью scp, от dev до тестового сервера), он говорит «file busy». И если я заменяю файл общей библиотеки (* .so), все процессы, которые связывают его, аварийно завершают работу.
Почему так? Я что-то пропустил? Как я могу заменить двоичные файлы без остановки / сбоя процесса?
.so
файл, используяldd filename.so
для проверки зависимостейstop app && create symlink of .so && start app
Ответы:
Как уже упоминалось в разделе Почему программный пакет работает нормально, даже когда он обновляется? блокировка помещается в индекс, а не в имя файла. Когда вы загружаете и выполняете двоичный файл, файл помечается как занятый, поэтому вы получаете ошибку ETXTBSY (файл занят), когда пытаетесь записать в него файл.
Теперь для разделяемых библиотек это немного отличается: библиотеки отображают память в адресное пространство процесса с помощью
mmap()
. Хотя этоMAP_DENYWRITE
может быть указано, по крайней мере, Glibc в Linux молча игнорирует его (согласно справочной странице, не стесняйтесь проверять источники) - проверьте эту ветку . Следовательно, вам действительно разрешено записывать файл, и, поскольку он отображен в памяти, любые изменения видны почти сразу - это означает, что, если вы попытаетесь достаточно усердно, вам удастся сделать кирпич своей машины, перезаписав библиотеку.Следовательно, правильный способ обновления:
удаление файла, который удаляет ссылку на данные из файловой системы, чтобы он был недоступен для новых приложений, которые могут его использовать, при этом данные остаются доступными для всех, у кого они уже открыты (или сопоставлены) ;
создание нового файла с обновленным содержимым.
Вновь созданные процессы будут использовать обновленное содержимое, запущенные приложения получат доступ к старой версии. Это то, что делает любая вменяемая утилита управления пакетами. Обратите внимание, что это не совсем безо всякой опасности - например, приложения, динамически загружающие код (использующие
dlsym()
и друзья), будут испытывать проблемы, если API библиотеки будет изменяться в автоматическом режиме.Если вы хотите быть действительно в безопасности, выключите систему, смонтируйте файловую систему из другого экземпляра операционной системы, обновите и снова запустите обновленную систему.
источник
Обновление rpm делает то же самое - с запущенными двоичными файлами и библиотеками, пока ничего не происходит.
Так в чем же разница:
Это НЕ заменит файл на месте: индекс, ссылающийся на двоичный файл в использовании, все еще «занят», пока не завершится последний объект, удерживающий его открытым. Новый файл будет создан с новым номером inode.
Теперь
scp
илиcp
попытается заменить файл на месте - это изменит содержимое, на которое ссылается индекс. Это не работает - как вы описали.источник