Если бы происходил процесс непрерывной записи в файл, и я хотел получить контроль над файлом с помощью root, я мог бы сделать что-то вроде этого:
sudo rm somefile; sudo touch somefile
Возможно ли добавление процесса к файлу между этими двумя командами? Если так, есть ли способ гарантировать, что никакая другая команда не будет запущена между?
Ответы:
Цепная командная строка в основном представляет собой небольшой сценарий оболочки; он выполнит первую команду, используя обычную процедуру fork + exec, дождется ее завершения, а затем выполнит вторую таким же образом. Между этими двумя командами существует некоторое произвольное количество времени, которое оболочка берет на себя в своей бухгалтерии и обработке, в течение которых происходит обычная многопроцессорная обработка, и произвольные другие процессы могут выполнять произвольные другие действия. Так что ответ «нет». (Если вы действительно сделаете это, вы обнаружите, что запись каталога
somefile
исчезает, но сам файл остается (так как он открыт процессом) до тех пор, пока он не будет закрыт. Место на диске, используемое файлом, не будет восстановлено, пока это не произойдет. Тем временем ,touch
команда создаст новый, не связанный файл с тем же именем и путем.)Если вы хотите изменить владельца файла на root, просто сделайте это
sudo chown root:root somefile
(хотя я не уверен, как это повлияет на процессы с открытым дескриптором файла). Если вы хотите уничтожить содержимое текущего файла, попробуйтеtruncate -s 0 somefile
(запущенный процесс продолжит добавление к пустому файлу). Если это что-то еще, возможно, уточнить, что вы хотите сделать.источник
chown
Использование somefile не повлияет на процессы, которые имеют дескриптор файла для somefile.exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-
.Нет.
rm
Команда, сопровождаемаяtouch
командой, вовсе не является атомарной. Между этими двумя командами будет много времени - возможно, в диапазоне миллисекунд. Многое может случиться за это время. Если вам не повезло, ваши учетные данные sudo могут даже истечь.Одна программа, вызывающая вызовы
unlink
иopen
вызовы, оставила бы намного более короткое окно для гонки, но это все же могло произойти.Более безопасный подход - создать новый файл с временным именем и использовать
rename
системный вызов. «Перезапись» имени с помощьюrename
системного вызова гарантированно будет атомарной. Это может быть достигнуто с помощьюtouch
иmv
.Но процесс, который открыл старый файл для записи, может продолжать запись в него даже после того, как он был удален. Это будет иметь место как для файла, удаленного с помощью, так
unlink
и для удаленного с помощьюrename
.источник
Когда у процесса открыт файловый дескриптор для чтения, не имеет значения, что вы делаете с владельцем или разрешениями: процесс может продолжить доступ к файлу. Вы даже можете удалить файл, и процесс сможет продолжить доступ к нему через дескриптор файла.
Считайте, что разрешения являются контрольным шлюзом для получения дескриптора файла.
Если вы хотите создать файл атомарно, то вместо этого:
Вы могли бы рассмотреть это:
который будет атомно заменен
somefile
наanotherfile
. (Я бы предпочел использовать,mv -f
но я не могу найти утверждение, которое гарантирует, что это вызываетrename(2)
системный вызов.Возможно, вы могли бы обновить свой Вопрос, чтобы объяснить, что вы подразумеваете под «взять под контроль файл». У вас может быть проблема XY здесь.
источник
mv -f
для полученияrename(2)
системного вызова. Вы правы, чтоln
не будете, потому что он всегда используетlink(2)
системный вызов, который не может заменить атомарно.ln -f
просто делаетunlink(2)
на цель первым.ln
мозги. Я не был уверен, как получитьrename(2)
гарантированную причастность, и было слишком поздно, чтобы копать дальшеmv
«будет выполнять действия, эквивалентные»rename(old, new)
. pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html .mv -f
действует так, какmv -i
если место назначения не доступно для записи, но оно не похоже наcp -f
то,ln -f
где оно будет сначала отключено.Нет, но
sudo rm somefile; sudo touch somefile
безопасен в большинстве ситуаций.
Большинство процессов открывают файлы и затем используют полученный дескриптор файла для доступа к содержимому файла.
Если процесс открывает какой-то файл, в sh:
Тогда другой процесс может свободно отсоединить (= удалить) somefile, и файловый дескриптор, для которого somefile был открыт первым процессом (в данном случае 3), продолжит ссылаться на исходное содержимое somefile, который теперь является файлом в подвешенном состоянии.
создаст новый, несвязанный файл somefile, и все процессы, у которых был открыт старый файл somefile и который теперь использует только файловый дескриптор для ссылки на него, не будут затронуты, поскольку они ссылаются на другой файл - тот, который сейчас находится в подвешенном состоянии.
Если процесс без полномочий root обращается к некоторому файлу по имени, он получит ошибку EPERM, потому что новый файл принадлежит пользователю root.
Если вы хотите предотвратить повреждение файла несколькими процессами под одним и тем же пользователем (например, root), linux имеет обязательную и рекомендательную блокировку файлов. Вы можете использовать
flock
команду в сценариях оболочки для консультативной блокировки файлов (см. Man-страницу для получения дополнительной информации).источник