Обновил файл, а читатель видит старое: сравнение cp, sed -i и os.replace

opium 48 минут назад Краткое содержание статьи Обновил файл, а читатель видит старое: сравнение cp, sed -i и os.replace 3 мин 1.3K Серверное администрирование * Python * Настройка Linux * В скрипте обновления конфига...
Will Anthropic have the best AI model at the end of October 2026?
Вот важная новость с фронта ИИ: opium 48 минут назад Краткое содержание статьи Обновил файл, а читатель видит старое: сравнение cp, sed -i и os. 3K Серверное администрирование * Python * Настройка Linux * В скрипте обновления конфига обычно проверяют две вещи: команда завершилась без ошибки и по прежнему пути читается новый текст. Этого мало, если файл уже открыт другим процессом, на него есть жёсткая ссылка или его права нужно сохранить.
Я сравнил несколько способов обновить маленький файл: перезапись на месте, cp, sed -i, install и замену через временный файл. Это синтетический лабораторный опыт на Linux. Проверяемое поведение описано в документации; цель опыта — сравнить последствия нескольких команд в одинаковых условиях.
Технические детали
7 в контейнере, файловая система overlayfs. Запуск от обычного пользователя (UID 1002), umask 022. Каждый вариант работал в отдельном каталоге.
Исходный файл config имел права 0640 и дополнительную жёсткую ссылку, а один читатель заранее держал его открытым. Сначала выполнялось обновление, и только после его завершения читатель начинал читать. Одновременного чтения и записи в опыте не было.
Что получилосьСпособ обновленияПрава послеinode прежнийПо исходному путиУже открытый дескрипторЖёсткая ссылкаopen(config, 'w запись на месте0640дановыйновыйновыйcp source config0640дановыйновыйновыйsed -i 's/old/new/' config0640нетновыйстарыйстарыйcp --remove-destination source config0644нетновыйстарыйстарыйinstall -m 640 source config0640нетновыйстарыйстарыйopen(temp, 'w затем os. replace0644нетновыйстарыйстарыйmkstemp, затем os. replace0600нетновыйстарыйстарыйmkstemp, fchmod(0640), затем os.
Отраслевые последствия
replace0640нетновыйстарыйстарыйТаблица делится на две группы. Если inode остаётся прежним, как при записи на месте или обычном cp, новые данные после окончания записи видят все: путь, открытый дескриптор и жёсткая ссылка. Если под именем появляется новый файл (sed -i, install, cp --remove-destination, os.
replace), новое видно только по пути. Открытый дескриптор и жёсткая ссылка остаются на прежнем inode со старым текстом. Механизм документирован.
GNU sed для -i пишет результат во временный файл, который потом занимает место исходного. В описании rename(2) сказано, что открытые дескрипторы переименование не затрагивает. sed -i при этом сохранил 0640, поэтому проверка одних прав через stat не показывает, какую версию прочитает процесс с открытым файлом.
Событие, по словам экспертов, усилит конкуренцию в сфере ИИ.




