Перемещайте файл в Linux только тогда, когда он не используется другим процессом - PullRequest
2 голосов
/ 05 января 2012

Используя команду lsof, я могу определить, используется ли файл каким-либо процессом, но мне нужно атомарно проверить файл для использования и переместить его, только если он не используется.Эти файлы используются различными другими программами, которые я не могу контролировать, поэтому я не могу использовать консультативные блокировки.Цель состоит в том, чтобы не дать другим процессам изменить этот файл, поэтому просто переместить файл, пока процесс открыт, не в порядке.Любое решение?

ОБНОВЛЕНИЕ: мне только что пришло в голову решение, которое, я думаю, соответствует моим целям.Конечная цель - обработать эти файлы в их окончательном состоянии, когда другие программы закончат их изменение.Если я переместу файл в другой каталог, я смогу использовать lsof, чтобы проверить, используется ли он по старому пути;если это так, я просто проверяю позже, пока он больше не используется, а затем обрабатываю файл.Перемещая файл в другой каталог, он скрывает файл от пользователей и программы.Я не хочу, чтобы пользователи и программы видели файл в старом каталоге, потому что это дает им возможность открыть файл между тем, как я использую lsof, и обработать файл, что означает, что я буду обрабатывать файл в измененном состоянии.

Ответы [ 2 ]

5 голосов
/ 05 января 2012

Как насчет использования fuser?Запустите его для файла, и он отобразит PID процессов, использующих этот файл.Если PID отсутствуют, файл ничего не использует.Он также вернет ненулевой код завершения, если нет файла, использующего файл.

Однако обратите внимание, что у вас все еще может быть состояние гонки, поскольку процесс может открыть файл после возврата команды fuser и до того, как вы mv ее.переместить файл, если он не используется:

if ! fuser /my/file
then
     mv /my/file /somewhere/else
fi 
2 голосов
/ 05 января 2012

Вы можете переместить файл, к которому что-то обращается, при условии, что вы перемещаете его в той же файловой системе, используя rename (2) syscall (который mv будет использовать, если источник и цель находятся ната же файловая система).Вы даже можете удалить его, используя системный вызов unlink (2) .А перемещение такого файла действительно запретило бы другим будущим процессам доступ к нему по тому же пути.

Вы также можете использовать API inotify (7) , чтобы получать уведомления при получении доступа к нему.

Также вы можете рассмотреть обязательную блокировку , по крайней мере, для некоторых файловых систем.

но ходят слухи, что обязательная блокировка не работает должным образом и иногда может содержать ошибки1017 *

...